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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
Diffstat (limited to 'intern')
-rw-r--r--intern/CMakeLists.txt1
-rw-r--r--intern/cycles/blender/addon/__init__.py4
-rw-r--r--intern/cycles/blender/addon/engine.py4
-rw-r--r--intern/cycles/blender/addon/ui.py263
-rw-r--r--intern/cycles/blender/blender_python.cpp28
-rw-r--r--intern/cycles/blender/blender_session.cpp168
-rw-r--r--intern/cycles/blender/blender_session.h13
-rw-r--r--intern/cycles/blender/blender_shader.cpp8
-rw-r--r--intern/cycles/blender/blender_sync.cpp3
-rw-r--r--intern/cycles/device/cuda/device_cuda.h2
-rw-r--r--intern/cycles/device/cuda/device_cuda_impl.cpp52
-rw-r--r--intern/cycles/device/device_cpu.cpp28
-rw-r--r--intern/cycles/device/opencl/device_opencl.h1
-rw-r--r--intern/cycles/device/opencl/device_opencl_impl.cpp53
-rw-r--r--intern/cycles/kernel/closure/bsdf.h20
-rw-r--r--intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h11
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet.h56
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet_multi.h25
-rw-r--r--intern/cycles/kernel/kernel_bake.h152
-rw-r--r--intern/cycles/kernel/kernel_light.h16
-rw-r--r--intern/cycles/kernel/kernel_types.h17
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_cpu.h3
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h19
-rw-r--r--intern/cycles/kernel/kernels/cuda/kernel.cu11
-rw-r--r--intern/cycles/kernel/osl/osl_closures.cpp66
-rw-r--r--intern/cycles/kernel/svm/svm_closure.h94
-rw-r--r--intern/cycles/kernel/svm/svm_types.h12
-rw-r--r--intern/cycles/render/bake.cpp305
-rw-r--r--intern/cycles/render/bake.h52
-rw-r--r--intern/cycles/render/buffers.cpp34
-rw-r--r--intern/cycles/render/buffers.h3
-rw-r--r--intern/cycles/render/film.cpp17
-rw-r--r--intern/cycles/render/nodes.cpp17
-rw-r--r--intern/cycles/render/session.cpp32
-rw-r--r--intern/cycles/render/session.h1
-rw-r--r--intern/cycles/util/util_avxb.h2
-rw-r--r--intern/cycles/util/util_avxi.h2
-rw-r--r--intern/cycles/util/util_sseb.h2
-rw-r--r--intern/cycles/util/util_ssei.h2
-rw-r--r--intern/dualcon/dualcon.h2
-rw-r--r--intern/dualcon/intern/octree.cpp2
-rw-r--r--intern/ghost/CMakeLists.txt180
-rw-r--r--intern/ghost/GHOST_IContext.h1
-rw-r--r--intern/ghost/GHOST_ISystem.h4
-rw-r--r--intern/ghost/GHOST_IWindow.h8
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp11
-rw-r--r--intern/ghost/intern/GHOST_Debug.h18
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerWin32.cpp12
-rw-r--r--intern/ghost/intern/GHOST_DropTargetWin32.cpp24
-rw-r--r--intern/ghost/intern/GHOST_EventKey.h2
-rw-r--r--intern/ghost/intern/GHOST_EventPrinter.h2
-rw-r--r--intern/ghost/intern/GHOST_ISystem.cpp57
-rw-r--r--intern/ghost/intern/GHOST_IXrGraphicsBinding.h2
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.cpp2
-rw-r--r--intern/ghost/intern/GHOST_System.cpp17
-rw-r--r--intern/ghost/intern/GHOST_System.h8
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm11
-rw-r--r--intern/ghost/intern/GHOST_SystemNULL.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.cpp2
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.cpp1777
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.h111
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp2
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp6
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h2
-rw-r--r--intern/ghost/intern/GHOST_Window.h5
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.h8
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm9
-rw-r--r--intern/ghost/intern/GHOST_WindowNULL.h9
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.cpp10
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.h7
-rw-r--r--intern/ghost/intern/GHOST_WindowWayland.cpp406
-rw-r--r--intern/ghost/intern/GHOST_WindowWayland.h121
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp15
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h8
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp19
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.h7
-rw-r--r--intern/ghost/intern/GHOST_XrGraphicsBinding.cpp6
-rw-r--r--intern/ghost/intern/GHOST_Xr_openxr_includes.h2
-rw-r--r--intern/ghost/test/CMakeLists.txt3
-rw-r--r--intern/ghost/test/gears/GHOST_Test.cpp11
-rw-r--r--intern/guardedalloc/CMakeLists.txt8
-rw-r--r--intern/guardedalloc/MEM_guardedalloc.h19
-rw-r--r--intern/guardedalloc/intern/mallocn.c7
-rw-r--r--intern/guardedalloc/intern/mallocn_guarded_impl.c178
-rw-r--r--intern/guardedalloc/intern/mallocn_intern.h17
-rw-r--r--intern/guardedalloc/intern/mallocn_lockfree_impl.c109
-rw-r--r--intern/libmv/CMakeLists.txt1
-rw-r--r--intern/libmv/files.txt1
-rw-r--r--intern/libmv/intern/camera_intrinsics.cc53
-rw-r--r--intern/libmv/intern/camera_intrinsics.h4
-rw-r--r--intern/libmv/libmv/autotrack/reconstruction.h5
-rw-r--r--intern/libmv/libmv/base/map.h34
-rw-r--r--intern/libmv/libmv/simple_pipeline/bundle.cc584
-rw-r--r--intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc63
-rw-r--r--intern/libmv/libmv/simple_pipeline/camera_intrinsics.h58
-rw-r--r--intern/libmv/libmv/simple_pipeline/distortion_models.cc92
-rw-r--r--intern/libmv/libmv/simple_pipeline/distortion_models.h78
-rw-r--r--intern/libmv/libmv/simple_pipeline/initialize_reconstruction.h4
-rw-r--r--intern/libmv/libmv/simple_pipeline/intersect.h8
-rw-r--r--intern/libmv/libmv/simple_pipeline/reconstruction.cc65
-rw-r--r--intern/libmv/libmv/simple_pipeline/reconstruction.h29
-rw-r--r--intern/libmv/libmv/simple_pipeline/resect.h4
-rw-r--r--intern/libmv/libmv/simple_pipeline/tracks.h6
-rw-r--r--intern/mantaflow/intern/MANTA_main.cpp2338
-rw-r--r--intern/mantaflow/intern/MANTA_main.h124
-rw-r--r--intern/mantaflow/intern/strings/fluid_script.h70
-rw-r--r--intern/mantaflow/intern/strings/liquid_script.h12
-rw-r--r--intern/mantaflow/intern/strings/smoke_script.h36
-rw-r--r--intern/memutil/MEM_CacheLimiterC-Api.h22
-rw-r--r--intern/opensubdiv/CMakeLists.txt18
-rw-r--r--intern/opensubdiv/internal/opensubdiv.cc4
-rw-r--r--intern/opensubdiv/internal/opensubdiv_converter_factory.cc13
-rw-r--r--intern/opensubdiv/internal/opensubdiv_converter_factory.h6
-rw-r--r--intern/opensubdiv/internal/opensubdiv_converter_internal.cc6
-rw-r--r--intern/opensubdiv/internal/opensubdiv_converter_internal.h6
-rw-r--r--intern/opensubdiv/internal/opensubdiv_converter_orient.cc67
-rw-r--r--intern/opensubdiv/internal/opensubdiv_converter_orient.h49
-rw-r--r--intern/opensubdiv/internal/opensubdiv_converter_orient_impl.h69
-rw-r--r--intern/opensubdiv/internal/opensubdiv_edge_map.h10
-rw-r--r--intern/opensubdiv/internal/opensubdiv_evaluator_internal.cc12
-rw-r--r--intern/opensubdiv/internal/opensubdiv_evaluator_internal.h8
-rw-r--r--intern/opensubdiv/internal/opensubdiv_gl_mesh.cc260
-rw-r--r--intern/opensubdiv/internal/opensubdiv_gl_mesh_draw.cc577
-rw-r--r--intern/opensubdiv/internal/opensubdiv_gl_mesh_draw.h39
-rw-r--r--intern/opensubdiv/internal/opensubdiv_gl_mesh_fvar.cc171
-rw-r--r--intern/opensubdiv/internal/opensubdiv_gl_mesh_fvar.h57
-rw-r--r--intern/opensubdiv/internal/opensubdiv_gl_mesh_internal.cc32
-rw-r--r--intern/opensubdiv/internal/opensubdiv_gl_mesh_internal.h43
-rw-r--r--intern/opensubdiv/internal/opensubdiv_topology_refiner.cc24
-rw-r--r--intern/opensubdiv/internal/opensubdiv_util.cc6
-rw-r--r--intern/opensubdiv/internal/opensubdiv_util.h6
-rw-r--r--intern/opensubdiv/opensubdiv_gl_mesh_capi.h92
-rw-r--r--intern/opensubdiv/shader/gpu_shader_opensubdiv_fragment.glsl163
-rw-r--r--intern/opensubdiv/shader/gpu_shader_opensubdiv_geometry.glsl149
-rw-r--r--intern/opensubdiv/shader/gpu_shader_opensubdiv_vertex.glsl42
-rw-r--r--intern/opensubdiv/stub/opensubdiv_gl_mesh_stub.cc40
-rw-r--r--intern/rigidbody/rb_bullet_api.cpp4
-rw-r--r--intern/string/CMakeLists.txt38
-rw-r--r--intern/string/STR_String.h366
-rw-r--r--intern/string/intern/STR_String.cpp637
143 files changed, 5676 insertions, 5883 deletions
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
index 4e780dc9f0f..fa18f4d793a 100644
--- a/intern/CMakeLists.txt
+++ b/intern/CMakeLists.txt
@@ -20,7 +20,6 @@
# add_subdirectory(atomic) # header only
add_subdirectory(clog)
-add_subdirectory(string)
add_subdirectory(ghost)
add_subdirectory(guardedalloc)
add_subdirectory(libmv)
diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py
index 3d2a52d0cf6..3ab352e52a2 100644
--- a/intern/cycles/blender/addon/__init__.py
+++ b/intern/cycles/blender/addon/__init__.py
@@ -82,8 +82,8 @@ class CyclesRender(bpy.types.RenderEngine):
def render(self, depsgraph):
engine.render(self, depsgraph)
- def bake(self, depsgraph, obj, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result):
- engine.bake(self, depsgraph, obj, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result)
+ def bake(self, depsgraph, obj, pass_type, pass_filter, width, height):
+ engine.bake(self, depsgraph, obj, pass_type, pass_filter, width, height)
# viewport render
def view_update(self, context, depsgraph):
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index a1b063430f5..e7ea5e7a1f6 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -168,11 +168,11 @@ def render(engine, depsgraph):
_cycles.render(engine.session, depsgraph.as_pointer())
-def bake(engine, depsgraph, obj, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result):
+def bake(engine, depsgraph, obj, pass_type, pass_filter, width, height):
import _cycles
session = getattr(engine, "session", None)
if session is not None:
- _cycles.bake(engine.session, depsgraph.as_pointer(), obj.as_pointer(), pass_type, pass_filter, object_id, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer())
+ _cycles.bake(engine.session, depsgraph.as_pointer(), obj.as_pointer(), pass_type, pass_filter, width, height)
def reset(engine, data, depsgraph):
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 7cf615620a3..a15daee706f 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -500,8 +500,9 @@ class CYCLES_RENDER_PT_light_paths_caustics(CyclesButtonsPanel, Panel):
col = layout.column()
col.prop(cscene, "blur_glossy")
- col.prop(cscene, "caustics_reflective")
- col.prop(cscene, "caustics_refractive")
+ col = layout.column(heading="Caustics", align=True)
+ col.prop(cscene, "caustics_reflective", text="Reflective")
+ col.prop(cscene, "caustics_refractive", text="Refractive")
class CYCLES_RENDER_PT_motion_blur(CyclesButtonsPanel, Panel):
@@ -762,22 +763,16 @@ class CYCLES_RENDER_PT_filter(CyclesButtonsPanel, Panel):
rd = scene.render
view_layer = context.view_layer
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
- col = flow.column()
+ col = layout.column(heading="Include")
col.prop(view_layer, "use_sky", text="Environment")
- col = flow.column()
col.prop(view_layer, "use_ao", text="Ambient Occlusion")
- col = flow.column()
col.prop(view_layer, "use_solid", text="Surfaces")
- col = flow.column()
col.prop(view_layer, "use_strand", text="Hair")
- col = flow.column()
col.prop(view_layer, "use_volumes", text="Volumes")
if with_freestyle:
- col = flow.column()
- col.prop(view_layer, "use_freestyle", text="Freestyle")
- col.active = rd.use_freestyle
+ sub = col.row(align=True)
+ sub.prop(view_layer, "use_freestyle", text="Freestyle")
+ sub.active = rd.use_freestyle
class CYCLES_RENDER_PT_override(CyclesButtonsPanel, Panel):
@@ -819,36 +814,27 @@ class CYCLES_RENDER_PT_passes_data(CyclesButtonsPanel, Panel):
view_layer = context.view_layer
cycles_view_layer = view_layer.cycles
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- col = flow.column()
+ col = layout.column(heading="Include", align=True)
col.prop(view_layer, "use_pass_combined")
- col = flow.column()
col.prop(view_layer, "use_pass_z")
- col = flow.column()
col.prop(view_layer, "use_pass_mist")
- col = flow.column()
col.prop(view_layer, "use_pass_normal")
- col = flow.column()
- col.prop(view_layer, "use_pass_vector")
- col.active = not rd.use_motion_blur
- col = flow.column()
+ sub = col.column()
+ sub.active = not rd.use_motion_blur
+ sub.prop(view_layer, "use_pass_vector")
col.prop(view_layer, "use_pass_uv")
- col = flow.column()
+
+ col.prop(cycles_view_layer, "denoising_store_passes", text="Denoising Data")
+
+ col = layout.column(heading="Indexes", align=True)
col.prop(view_layer, "use_pass_object_index")
- col = flow.column()
col.prop(view_layer, "use_pass_material_index")
- layout.separator()
-
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- col = flow.column()
- col.prop(cycles_view_layer, "denoising_store_passes", text="Denoising Data")
- col = flow.column()
+ col = layout.column(heading="Debug", align=True)
col.prop(cycles_view_layer, "pass_debug_render_time", text="Render Time")
- col = flow.column()
col.prop(cycles_view_layer, "pass_debug_sample_count", text="Sample Count")
- layout.separator()
+
layout.prop(view_layer, "pass_alpha_threshold")
@@ -866,38 +852,26 @@ class CYCLES_RENDER_PT_passes_light(CyclesButtonsPanel, Panel):
view_layer = context.view_layer
cycles_view_layer = view_layer.cycles
- split = layout.split(factor=0.35)
- split.use_property_split = False
- split.label(text="Diffuse")
- row = split.row(align=True)
- row.prop(view_layer, "use_pass_diffuse_direct", text="Direct", toggle=True)
- row.prop(view_layer, "use_pass_diffuse_indirect", text="Indirect", toggle=True)
- row.prop(view_layer, "use_pass_diffuse_color", text="Color", toggle=True)
-
- split = layout.split(factor=0.35)
- split.use_property_split = False
- split.label(text="Glossy")
- row = split.row(align=True)
- row.prop(view_layer, "use_pass_glossy_direct", text="Direct", toggle=True)
- row.prop(view_layer, "use_pass_glossy_indirect", text="Indirect", toggle=True)
- row.prop(view_layer, "use_pass_glossy_color", text="Color", toggle=True)
-
- split = layout.split(factor=0.35)
- split.use_property_split = False
- split.label(text="Transmission")
- row = split.row(align=True)
- row.prop(view_layer, "use_pass_transmission_direct", text="Direct", toggle=True)
- row.prop(view_layer, "use_pass_transmission_indirect", text="Indirect", toggle=True)
- row.prop(view_layer, "use_pass_transmission_color", text="Color", toggle=True)
-
- split = layout.split(factor=0.35)
- split.use_property_split = False
- split.label(text="Volume")
- row = split.row(align=True)
- row.prop(cycles_view_layer, "use_pass_volume_direct", text="Direct", toggle=True)
- row.prop(cycles_view_layer, "use_pass_volume_indirect", text="Indirect", toggle=True)
+ col = layout.column(heading="Diffuse", align=True)
+ col.prop(view_layer, "use_pass_diffuse_direct", text="Direct")
+ col.prop(view_layer, "use_pass_diffuse_indirect", text="Indirect")
+ col.prop(view_layer, "use_pass_diffuse_color", text="Color")
- col = layout.column(align=True)
+ col = layout.column(heading="Glossy", align=True)
+ col.prop(view_layer, "use_pass_glossy_direct", text="Direct")
+ col.prop(view_layer, "use_pass_glossy_indirect", text="Indirect")
+ col.prop(view_layer, "use_pass_glossy_color", text="Color")
+
+ col = layout.column(heading="Transmission", align=True)
+ col.prop(view_layer, "use_pass_transmission_direct", text="Direct")
+ col.prop(view_layer, "use_pass_transmission_indirect", text="Indirect")
+ col.prop(view_layer, "use_pass_transmission_color", text="Color")
+
+ col = layout.column(heading="Volume", align=True)
+ col.prop(cycles_view_layer, "use_pass_volume_direct", text="Direct")
+ col.prop(cycles_view_layer, "use_pass_volume_indirect", text="Indirect")
+
+ col = layout.column(heading="Other", align=True)
col.prop(view_layer, "use_pass_emit", text="Emission")
col.prop(view_layer, "use_pass_environment")
col.prop(view_layer, "use_pass_shadow")
@@ -918,11 +892,10 @@ class CYCLES_RENDER_PT_passes_crypto(CyclesButtonsPanel, Panel):
cycles_view_layer = context.view_layer.cycles
- row = layout.row(align=True)
- row.use_property_split = False
- row.prop(cycles_view_layer, "use_pass_crypto_object", text="Object", toggle=True)
- row.prop(cycles_view_layer, "use_pass_crypto_material", text="Material", toggle=True)
- row.prop(cycles_view_layer, "use_pass_crypto_asset", text="Asset", toggle=True)
+ col = layout.column(heading="Include", align=True)
+ col.prop(cycles_view_layer, "use_pass_crypto_object", text="Object")
+ col.prop(cycles_view_layer, "use_pass_crypto_material", text="Material")
+ col.prop(cycles_view_layer, "use_pass_crypto_asset", text="Asset")
layout.prop(cycles_view_layer, "pass_crypto_depth", text="Levels")
@@ -1012,10 +985,9 @@ class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel):
view_layer = context.view_layer
cycles_view_layer = view_layer.cycles
- split = layout.split()
- split.active = cycles_view_layer.use_denoising
+ layout.active = cycles_view_layer.use_denoising
- col = split.column(align=True)
+ col = layout.column()
if show_optix_denoising(context):
col.prop(cycles_view_layer, "use_optix_denoising")
@@ -1026,51 +998,29 @@ class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel):
return
col.prop(cycles_view_layer, "denoising_radius", text="Radius")
+
+ col = layout.column()
col.prop(cycles_view_layer, "denoising_strength", slider=True, text="Strength")
col.prop(cycles_view_layer, "denoising_feature_strength", slider=True, text="Feature Strength")
col.prop(cycles_view_layer, "denoising_relative_pca")
layout.separator()
- split = layout.split(factor=0.5)
- split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
-
- col = split.column()
- col.alignment = 'RIGHT'
- col.label(text="Diffuse")
+ col = layout.column()
+ col.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
- row = split.row(align=True)
- row.use_property_split = False
+ row = col.row(heading="Diffuse", align=True)
row.prop(cycles_view_layer, "denoising_diffuse_direct", text="Direct", toggle=True)
row.prop(cycles_view_layer, "denoising_diffuse_indirect", text="Indirect", toggle=True)
- split = layout.split(factor=0.5)
- split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
-
- col = split.column()
- col.alignment = 'RIGHT'
- col.label(text="Glossy")
-
- row = split.row(align=True)
- row.use_property_split = False
+ row = col.row(heading="Glossy", align=True)
row.prop(cycles_view_layer, "denoising_glossy_direct", text="Direct", toggle=True)
row.prop(cycles_view_layer, "denoising_glossy_indirect", text="Indirect", toggle=True)
- split = layout.split(factor=0.5)
- split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
-
- col = split.column()
- col.alignment = 'RIGHT'
- col.label(text="Transmission")
-
- row = split.row(align=True)
- row.use_property_split = False
+ row = col.row(heading="Transmission", align=True)
row.prop(cycles_view_layer, "denoising_transmission_direct", text="Direct", toggle=True)
row.prop(cycles_view_layer, "denoising_transmission_indirect", text="Indirect", toggle=True)
- split = layout.split(factor=0.5)
- split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
-
class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel):
bl_label = "Post Processing"
@@ -1084,7 +1034,7 @@ class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel):
rd = context.scene.render
- col = layout.column(align=True)
+ col = layout.column(align=True, heading="Pipeline")
col.prop(rd, "use_compositing")
col.prop(rd, "use_sequencer")
@@ -1273,22 +1223,18 @@ class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel):
layout = self.layout
layout.use_property_split = True
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
- layout = self.layout
ob = context.object
- col = flow.column()
- col.prop(ob, "hide_viewport", text="Show in Viewports", invert_checkbox=True, toggle=False)
- col = flow.column()
- col.prop(ob, "hide_render", text="Show in Renders", invert_checkbox=True, toggle=False)
- col = flow.column()
- col.prop(ob, "hide_select", text="Selectable", invert_checkbox=True, toggle=False)
+ layout.prop(ob, "hide_select", text="Selectable", invert_checkbox=True, toggle=False)
+
+ 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)
if has_geometry_visibility(ob):
cob = ob.cycles
- col = flow.column()
+ col = layout.column(heading="Mask")
col.prop(cob, "is_shadow_catcher")
- col = flow.column()
col.prop(cob, "is_holdout")
@@ -1312,24 +1258,16 @@ class CYCLES_OBJECT_PT_visibility_ray_visibility(CyclesButtonsPanel, Panel):
cob = ob.cycles
visibility = ob.cycles_visibility
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
- col = flow.column()
+ col = layout.column()
col.prop(visibility, "camera")
- col = flow.column()
col.prop(visibility, "diffuse")
- col = flow.column()
col.prop(visibility, "glossy")
- col = flow.column()
col.prop(visibility, "transmission")
- col = flow.column()
col.prop(visibility, "scatter")
if ob.type != 'LIGHT':
- col = flow.column()
- col.prop(visibility, "shadow")
-
- layout.separator()
+ sub = col.column()
+ sub.prop(visibility, "shadow")
class CYCLES_OBJECT_PT_visibility_culling(CyclesButtonsPanel, Panel):
@@ -1352,15 +1290,13 @@ class CYCLES_OBJECT_PT_visibility_culling(CyclesButtonsPanel, Panel):
ob = context.object
cob = ob.cycles
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
- col = flow.column()
- col.active = scene.render.use_simplify and cscene.use_camera_cull
- col.prop(cob, "use_camera_cull")
+ row = layout.row()
+ row.active = scene.render.use_simplify and cscene.use_camera_cull
+ row.prop(cob, "use_camera_cull")
- col = flow.column()
- col.active = scene.render.use_simplify and cscene.use_distance_cull
- col.prop(cob, "use_distance_cull")
+ row = layout.row()
+ row.active = scene.render.use_simplify and cscene.use_distance_cull
+ row.prop(cob, "use_distance_cull")
def panel_node_draw(layout, id_data, output_type, input_name):
@@ -1474,6 +1410,8 @@ class CYCLES_LIGHT_PT_nodes(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+
light = context.light
panel_node_draw(layout, light, 'OUTPUT_LIGHT', 'Surface')
@@ -1523,6 +1461,8 @@ class CYCLES_WORLD_PT_surface(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+
world = context.world
if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
@@ -1542,6 +1482,8 @@ class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+
world = context.world
panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
@@ -1729,6 +1671,8 @@ class CYCLES_MATERIAL_PT_surface(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+
mat = context.material
if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'):
layout.prop(mat, "diffuse_color")
@@ -1747,6 +1691,8 @@ class CYCLES_MATERIAL_PT_volume(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+
mat = context.material
# cmat = mat.cycles
@@ -1765,6 +1711,8 @@ class CYCLES_MATERIAL_PT_displacement(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+
mat = context.material
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
@@ -1906,26 +1854,24 @@ class CYCLES_RENDER_PT_bake_influence(CyclesButtonsPanel, Panel):
sub.prop(cbk, "normal_b", text="B")
elif cscene.bake_type == 'COMBINED':
- row = col.row(align=True)
- row.use_property_split = False
- row.prop(cbk, "use_pass_direct", toggle=True)
- row.prop(cbk, "use_pass_indirect", toggle=True)
- flow = col.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=True)
+ col = layout.column(heading="Lighting", align=True)
+ col.prop(cbk, "use_pass_direct")
+ col.prop(cbk, "use_pass_indirect")
- flow.active = cbk.use_pass_direct or cbk.use_pass_indirect
- flow.prop(cbk, "use_pass_diffuse")
- flow.prop(cbk, "use_pass_glossy")
- flow.prop(cbk, "use_pass_transmission")
- flow.prop(cbk, "use_pass_ambient_occlusion")
- flow.prop(cbk, "use_pass_emit")
+ col = layout.column(heading="Contributions", align=True)
+ col.active = cbk.use_pass_direct or cbk.use_pass_indirect
+ col.prop(cbk, "use_pass_diffuse")
+ col.prop(cbk, "use_pass_glossy")
+ col.prop(cbk, "use_pass_transmission")
+ col.prop(cbk, "use_pass_ambient_occlusion")
+ col.prop(cbk, "use_pass_emit")
elif cscene.bake_type in {'DIFFUSE', 'GLOSSY', 'TRANSMISSION'}:
- row = col.row(align=True)
- row.use_property_split = False
- row.prop(cbk, "use_pass_direct", toggle=True)
- row.prop(cbk, "use_pass_indirect", toggle=True)
- row.prop(cbk, "use_pass_color", toggle=True)
+ col = layout.column(heading="Contributions", align=True)
+ col.prop(cbk, "use_pass_direct")
+ col.prop(cbk, "use_pass_indirect")
+ col.prop(cbk, "use_pass_color")
class CYCLES_RENDER_PT_bake_selected_to_active(CyclesButtonsPanel, Panel):
@@ -1961,10 +1907,15 @@ class CYCLES_RENDER_PT_bake_selected_to_active(CyclesButtonsPanel, Panel):
col.prop(cbk, "use_cage", text="Cage")
if cbk.use_cage:
- col.prop(cbk, "cage_extrusion", text="Extrusion")
- col.prop(cbk, "cage_object", text="Cage Object")
+ col.prop(cbk, "cage_object")
+ col = layout.column()
+ col.prop(cbk, "cage_extrusion")
+ col.active = cbk.cage_object is None
else:
- col.prop(cbk, "cage_extrusion", text="Ray Distance")
+ col.prop(cbk, "cage_extrusion", text="Extrusion")
+
+ col = layout.column()
+ col.prop(cbk, "max_ray_distance")
class CYCLES_RENDER_PT_bake_output(CyclesButtonsPanel, Panel):
@@ -2131,17 +2082,17 @@ class CYCLES_RENDER_PT_simplify_culling(CyclesButtonsPanel, Panel):
layout.active = rd.use_simplify
- col = layout.column()
- col.prop(cscene, "use_camera_cull")
- sub = col.column()
+ row = layout.row(heading="Camera Culling")
+ row.prop(cscene, "use_camera_cull", text="")
+ sub = row.column()
sub.active = cscene.use_camera_cull
- sub.prop(cscene, "camera_cull_margin")
+ sub.prop(cscene, "camera_cull_margin", text="")
- col = layout.column()
- col.prop(cscene, "use_distance_cull")
- sub = col.column()
+ row = layout.row(heading="Distance Culling")
+ row.prop(cscene, "use_distance_cull", text="")
+ sub = row.column()
sub.active = cscene.use_distance_cull
- sub.prop(cscene, "distance_cull_margin", text="Distance")
+ sub.prop(cscene, "distance_cull_margin", text="")
class CYCLES_VIEW3D_PT_shading_render_pass(Panel):
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index 8c7c0bc1daa..79c16856462 100644
--- a/intern/cycles/blender/blender_python.cpp
+++ b/intern/cycles/blender/blender_python.cpp
@@ -298,22 +298,18 @@ static PyObject *render_func(PyObject * /*self*/, PyObject *args)
static PyObject *bake_func(PyObject * /*self*/, PyObject *args)
{
PyObject *pysession, *pydepsgraph, *pyobject;
- PyObject *pypixel_array, *pyresult;
const char *pass_type;
- int num_pixels, depth, object_id, pass_filter;
+ int pass_filter, width, height;
if (!PyArg_ParseTuple(args,
- "OOOsiiOiiO",
+ "OOOsiii",
&pysession,
&pydepsgraph,
&pyobject,
&pass_type,
&pass_filter,
- &object_id,
- &pypixel_array,
- &num_pixels,
- &depth,
- &pyresult))
+ &width,
+ &height))
return NULL;
BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession);
@@ -326,23 +322,9 @@ static PyObject *bake_func(PyObject * /*self*/, PyObject *args)
RNA_id_pointer_create((ID *)PyLong_AsVoidPtr(pyobject), &objectptr);
BL::Object b_object(objectptr);
- void *b_result = PyLong_AsVoidPtr(pyresult);
-
- PointerRNA bakepixelptr;
- RNA_pointer_create(NULL, &RNA_BakePixel, PyLong_AsVoidPtr(pypixel_array), &bakepixelptr);
- BL::BakePixel b_bake_pixel(bakepixelptr);
-
python_thread_state_save(&session->python_thread_state);
- session->bake(b_depsgraph,
- b_object,
- pass_type,
- pass_filter,
- object_id,
- b_bake_pixel,
- (size_t)num_pixels,
- depth,
- (float *)b_result);
+ session->bake(b_depsgraph, b_object, pass_type, pass_filter, width, height);
python_thread_state_restore(&session->python_thread_state);
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 5ea96d6bdfd..31b09695632 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -247,9 +247,7 @@ void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsg
void BlenderSession::free_session()
{
- if (sync)
- delete sync;
-
+ delete sync;
delete session;
}
@@ -317,6 +315,7 @@ static void end_render_result(BL::RenderEngine &b_engine,
void BlenderSession::do_write_update_render_tile(RenderTile &rtile,
bool do_update_only,
+ bool do_read_only,
bool highlight)
{
int x = rtile.x - session->tile_manager.params.full_x;
@@ -342,7 +341,23 @@ void BlenderSession::do_write_update_render_tile(RenderTile &rtile,
BL::RenderLayer b_rlay = *b_single_rlay;
- if (do_update_only) {
+ if (do_read_only) {
+ /* copy each pass */
+ BL::RenderLayer::passes_iterator b_iter;
+
+ for (b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) {
+ BL::RenderPass b_pass(*b_iter);
+
+ /* find matching pass type */
+ PassType pass_type = BlenderSync::get_pass_type(b_pass);
+ int components = b_pass.channels();
+
+ rtile.buffers->set_pass_rect(pass_type, components, (float *)b_pass.rect());
+ }
+
+ end_render_result(b_engine, b_rr, false, false, false);
+ }
+ else if (do_update_only) {
/* Sample would be zero at initial tile update, which is only needed
* to tag tile form blender side as IN PROGRESS for proper highlight
* no buffers should be sent to blender yet. For denoise we also
@@ -362,9 +377,14 @@ void BlenderSession::do_write_update_render_tile(RenderTile &rtile,
}
}
+void BlenderSession::read_render_tile(RenderTile &rtile)
+{
+ do_write_update_render_tile(rtile, false, true, false);
+}
+
void BlenderSession::write_render_tile(RenderTile &rtile)
{
- do_write_update_render_tile(rtile, false, false);
+ do_write_update_render_tile(rtile, false, false, false);
}
void BlenderSession::update_render_tile(RenderTile &rtile, bool highlight)
@@ -374,9 +394,9 @@ void BlenderSession::update_render_tile(RenderTile &rtile, bool highlight)
* would need to be investigated a bit further, but for now shall be fine
*/
if (!b_engine.is_preview())
- do_write_update_render_tile(rtile, true, highlight);
+ do_write_update_render_tile(rtile, true, false, highlight);
else
- do_write_update_render_tile(rtile, false, false);
+ do_write_update_render_tile(rtile, false, false, false);
}
static void add_cryptomatte_layer(BL::RenderResult &b_rr, string name, string manifest)
@@ -593,25 +613,6 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
#endif
}
-static void populate_bake_data(BakeData *data,
- const int object_id,
- BL::BakePixel &pixel_array,
- const int num_pixels)
-{
- BL::BakePixel bp = pixel_array;
-
- int i;
- for (i = 0; i < num_pixels; i++) {
- if (bp.object_id() == object_id) {
- data->set(i, bp.primitive_id(), bp.uv(), bp.du_dx(), bp.du_dy(), bp.dv_dx(), bp.dv_dy());
- }
- else {
- data->set_null(i);
- }
- bp = bp.next();
- }
-}
-
static int bake_pass_filter_get(const int pass_filter)
{
int flag = BAKE_FILTER_NONE;
@@ -642,43 +643,26 @@ void BlenderSession::bake(BL::Depsgraph &b_depsgraph_,
BL::Object &b_object,
const string &pass_type,
const int pass_filter,
- const int object_id,
- BL::BakePixel &pixel_array,
- const size_t num_pixels,
- const int /*depth*/,
- float result[])
+ const int bake_width,
+ const int bake_height)
{
b_depsgraph = b_depsgraph_;
ShaderEvalType shader_type = get_shader_type(pass_type);
-
- /* Set baking flag in advance, so kernel loading can check if we need
- * any baking capabilities.
- */
- scene->bake_manager->set_baking(true);
-
- /* ensure kernels are loaded before we do any scene updates */
- session->load_kernels();
-
- if (shader_type == SHADER_EVAL_UV) {
- /* force UV to be available */
- Pass::add(PASS_UV, scene->film->passes);
- }
-
int bake_pass_filter = bake_pass_filter_get(pass_filter);
- bake_pass_filter = BakeManager::shader_type_to_pass_filter(shader_type, bake_pass_filter);
- /* force use_light_pass to be true if we bake more than just colors */
- if (bake_pass_filter & ~BAKE_FILTER_COLOR) {
- Pass::add(PASS_LIGHT, scene->film->passes);
- }
+ /* Initialize bake manager, before we load the baking kernels. */
+ scene->bake_manager->set(scene, b_object.name(), shader_type, bake_pass_filter);
- /* create device and update scene */
- scene->film->tag_update(scene);
- scene->integrator->tag_update(scene);
+ /* Passes are identified by name, so in order to return the combined pass we need to set the
+ * name. */
+ Pass::add(PASS_COMBINED, scene->film->passes, "Combined");
+
+ session->read_bake_tile_cb = function_bind(&BlenderSession::read_render_tile, this, _1);
+ session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1);
if (!session->progress.get_cancel()) {
- /* update scene */
+ /* Sync scene. */
BL::Object b_camera_override(b_engine.camera_override());
sync->sync_camera(b_render, b_camera_override, width, height, "");
sync->sync_data(
@@ -686,75 +670,43 @@ void BlenderSession::bake(BL::Depsgraph &b_depsgraph_,
builtin_images_load();
}
- BakeData *bake_data = NULL;
+ /* Object might have been disabled for rendering or excluded in some
+ * other way, in that case Blender will report a warning afterwards. */
+ bool object_found = false;
+ foreach (Object *ob, scene->objects) {
+ if (ob->name == b_object.name()) {
+ object_found = true;
+ break;
+ }
+ }
- if (!session->progress.get_cancel()) {
- /* get buffer parameters */
+ if (object_found && !session->progress.get_cancel()) {
+ /* Get session and buffer parameters. */
SessionParams session_params = BlenderSync::get_session_params(
b_engine, b_userpref, b_scene, background);
- BufferParams buffer_params = BlenderSync::get_buffer_params(
- b_scene, b_render, b_v3d, b_rv3d, scene->camera, width, height);
+ session_params.progressive_refine = false;
- scene->bake_manager->set_shader_limit((size_t)b_engine.tile_x(), (size_t)b_engine.tile_y());
+ BufferParams buffer_params;
+ buffer_params.width = bake_width;
+ buffer_params.height = bake_height;
+ buffer_params.passes = scene->film->passes;
- /* set number of samples */
+ /* Update session. */
session->tile_manager.set_samples(session_params.samples);
session->reset(buffer_params, session_params.samples);
- session->update_scene();
-
- /* find object index. todo: is arbitrary - copied from mesh_displace.cpp */
- size_t object_index = OBJECT_NONE;
- int tri_offset = 0;
-
- for (size_t i = 0; i < scene->objects.size(); i++) {
- const Object *object = scene->objects[i];
- const Geometry *geom = object->geometry;
- if (object->name == b_object.name() && geom->type == Geometry::MESH) {
- const Mesh *mesh = static_cast<const Mesh *>(geom);
- object_index = i;
- tri_offset = mesh->prim_offset;
- break;
- }
- }
-
- /* Object might have been disabled for rendering or excluded in some
- * other way, in that case Blender will report a warning afterwards. */
- if (object_index != OBJECT_NONE) {
- int object = object_index;
-
- bake_data = scene->bake_manager->init(object, tri_offset, num_pixels);
- populate_bake_data(bake_data, object_id, pixel_array, num_pixels);
- }
-
- /* set number of samples */
- session->tile_manager.set_samples(session_params.samples);
- session->reset(buffer_params, session_params.samples);
- session->update_scene();
session->progress.set_update_callback(
function_bind(&BlenderSession::update_bake_progress, this));
}
/* Perform bake. Check cancel to avoid crash with incomplete scene data. */
- if (!session->progress.get_cancel() && bake_data) {
- scene->bake_manager->bake(scene->device,
- &scene->dscene,
- scene,
- session->progress,
- shader_type,
- bake_pass_filter,
- bake_data,
- result);
+ if (object_found && !session->progress.get_cancel()) {
+ session->start();
+ session->wait();
}
- /* free all memory used (host and device), so we wouldn't leave render
- * engine with extra memory allocated
- */
-
- session->device_free();
-
- delete sync;
- sync = NULL;
+ session->read_bake_tile_cb = function_null;
+ session->write_render_tile_cb = function_null;
}
void BlenderSession::do_write_update_render_result(BL::RenderLayer &b_rlay,
diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h
index 3e6498bb655..34e952e312b 100644
--- a/intern/cycles/blender/blender_session.h
+++ b/intern/cycles/blender/blender_session.h
@@ -66,14 +66,12 @@ class BlenderSession {
BL::Object &b_object,
const string &pass_type,
const int custom_flag,
- const int object_id,
- BL::BakePixel &pixel_array,
- const size_t num_pixels,
- const int depth,
- float pixels[]);
+ const int bake_width,
+ const int bake_height);
void write_render_result(BL::RenderLayer &b_rlay, RenderTile &rtile);
void write_render_tile(RenderTile &rtile);
+ void read_render_tile(RenderTile &rtile);
/* update functions are used to update display buffer only after sample was rendered
* only needed for better visual feedback */
@@ -155,7 +153,10 @@ class BlenderSession {
void do_write_update_render_result(BL::RenderLayer &b_rlay,
RenderTile &rtile,
bool do_update_only);
- void do_write_update_render_tile(RenderTile &rtile, bool do_update_only, bool highlight);
+ void do_write_update_render_tile(RenderTile &rtile,
+ bool do_update_only,
+ bool do_read_only,
+ bool highlight);
void builtin_images_load();
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 7297ce829c5..f207d8ae07f 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -384,16 +384,16 @@ static ShaderNode *add_node(Scene *scene,
switch (b_aniso_node.distribution()) {
case BL::ShaderNodeBsdfAnisotropic::distribution_BECKMANN:
- aniso->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
+ aniso->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
break;
case BL::ShaderNodeBsdfAnisotropic::distribution_GGX:
- aniso->distribution = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
+ aniso->distribution = CLOSURE_BSDF_MICROFACET_GGX_ID;
break;
case BL::ShaderNodeBsdfAnisotropic::distribution_MULTI_GGX:
- aniso->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID;
+ aniso->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
break;
case BL::ShaderNodeBsdfAnisotropic::distribution_ASHIKHMIN_SHIRLEY:
- aniso->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
+ aniso->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
break;
}
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index e8031be7dd1..f16305e737d 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -481,6 +481,9 @@ PassType BlenderSync::get_pass_type(BL::RenderPass &b_pass)
MAP_PASS("AO", PASS_AO);
MAP_PASS("Shadow", PASS_SHADOW);
+ MAP_PASS("BakePrimitive", PASS_BAKE_PRIMITIVE);
+ MAP_PASS("BakeDifferential", PASS_BAKE_DIFFERENTIAL);
+
#ifdef __KERNEL_DEBUG__
MAP_PASS("Debug BVH Traversed Nodes", PASS_BVH_TRAVERSED_NODES);
MAP_PASS("Debug BVH Traversed Instances", PASS_BVH_TRAVERSED_INSTANCES);
diff --git a/intern/cycles/device/cuda/device_cuda.h b/intern/cycles/device/cuda/device_cuda.h
index 3e397da895b..3f23f0fe4c5 100644
--- a/intern/cycles/device/cuda/device_cuda.h
+++ b/intern/cycles/device/cuda/device_cuda.h
@@ -223,7 +223,7 @@ class CUDADevice : public Device {
CUdeviceptr d_wtile,
CUstream stream = 0);
- void path_trace(DeviceTask &task, RenderTile &rtile, device_vector<WorkTile> &work_tiles);
+ void render(DeviceTask &task, RenderTile &rtile, device_vector<WorkTile> &work_tiles);
void film_convert(DeviceTask &task,
device_ptr buffer,
diff --git a/intern/cycles/device/cuda/device_cuda_impl.cpp b/intern/cycles/device/cuda/device_cuda_impl.cpp
index ba5d479e0e7..acf53c3eb1b 100644
--- a/intern/cycles/device/cuda/device_cuda_impl.cpp
+++ b/intern/cycles/device/cuda/device_cuda_impl.cpp
@@ -586,20 +586,23 @@ void CUDADevice::reserve_local_memory(const DeviceRequestedFeatures &requested_f
cuMemGetInfo(&free_before, &total);
/* Get kernel function. */
- CUfunction cuPathTrace;
+ CUfunction cuRender;
- if (requested_features.use_integrator_branched) {
- cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_branched_path_trace"));
+ if (requested_features.use_baking) {
+ cuda_assert(cuModuleGetFunction(&cuRender, cuModule, "kernel_cuda_bake"));
+ }
+ else if (requested_features.use_integrator_branched) {
+ cuda_assert(cuModuleGetFunction(&cuRender, cuModule, "kernel_cuda_branched_path_trace"));
}
else {
- cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_path_trace"));
+ cuda_assert(cuModuleGetFunction(&cuRender, cuModule, "kernel_cuda_path_trace"));
}
- cuda_assert(cuFuncSetCacheConfig(cuPathTrace, CU_FUNC_CACHE_PREFER_L1));
+ cuda_assert(cuFuncSetCacheConfig(cuRender, CU_FUNC_CACHE_PREFER_L1));
int min_blocks, num_threads_per_block;
- cuda_assert(cuOccupancyMaxPotentialBlockSize(
- &min_blocks, &num_threads_per_block, cuPathTrace, NULL, 0, 0));
+ cuda_assert(
+ cuOccupancyMaxPotentialBlockSize(&min_blocks, &num_threads_per_block, cuRender, NULL, 0, 0));
/* Launch kernel, using just 1 block appears sufficient to reserve
* memory for all multiprocessors. It would be good to do this in
@@ -609,7 +612,7 @@ void CUDADevice::reserve_local_memory(const DeviceRequestedFeatures &requested_f
void *args[] = {&d_work_tiles, &total_work_size};
- cuda_assert(cuLaunchKernel(cuPathTrace, 1, 1, 1, num_threads_per_block, 1, 1, 0, 0, args, 0));
+ cuda_assert(cuLaunchKernel(cuRender, 1, 1, 1, num_threads_per_block, 1, 1, 0, 0, args, 0));
cuda_assert(cuCtxSynchronize());
@@ -1780,9 +1783,7 @@ void CUDADevice::adaptive_sampling_post(RenderTile &rtile,
0));
}
-void CUDADevice::path_trace(DeviceTask &task,
- RenderTile &rtile,
- device_vector<WorkTile> &work_tiles)
+void CUDADevice::render(DeviceTask &task, RenderTile &rtile, device_vector<WorkTile> &work_tiles)
{
scoped_timer timer(&rtile.buffers->render_time);
@@ -1790,21 +1791,24 @@ void CUDADevice::path_trace(DeviceTask &task,
return;
CUDAContextScope scope(this);
- CUfunction cuPathTrace;
+ CUfunction cuRender;
/* Get kernel function. */
- if (task.integrator_branched) {
- cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_branched_path_trace"));
+ if (rtile.task == RenderTile::BAKE) {
+ cuda_assert(cuModuleGetFunction(&cuRender, cuModule, "kernel_cuda_bake"));
+ }
+ else if (task.integrator_branched) {
+ cuda_assert(cuModuleGetFunction(&cuRender, cuModule, "kernel_cuda_branched_path_trace"));
}
else {
- cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_path_trace"));
+ cuda_assert(cuModuleGetFunction(&cuRender, cuModule, "kernel_cuda_path_trace"));
}
if (have_error()) {
return;
}
- cuda_assert(cuFuncSetCacheConfig(cuPathTrace, CU_FUNC_CACHE_PREFER_L1));
+ cuda_assert(cuFuncSetCacheConfig(cuRender, CU_FUNC_CACHE_PREFER_L1));
/* Allocate work tile. */
work_tiles.alloc(1);
@@ -1822,8 +1826,8 @@ void CUDADevice::path_trace(DeviceTask &task,
* remain conservative for GPUs connected to a display to avoid driver
* timeouts and display freezing. */
int min_blocks, num_threads_per_block;
- cuda_assert(cuOccupancyMaxPotentialBlockSize(
- &min_blocks, &num_threads_per_block, cuPathTrace, NULL, 0, 0));
+ cuda_assert(
+ cuOccupancyMaxPotentialBlockSize(&min_blocks, &num_threads_per_block, cuRender, NULL, 0, 0));
if (!info.display_device) {
min_blocks *= 8;
}
@@ -1851,7 +1855,7 @@ void CUDADevice::path_trace(DeviceTask &task,
void *args[] = {&d_work_tiles, &total_work_size};
cuda_assert(
- cuLaunchKernel(cuPathTrace, num_blocks, 1, 1, num_threads_per_block, 1, 1, 0, 0, args, 0));
+ cuLaunchKernel(cuRender, num_blocks, 1, 1, num_threads_per_block, 1, 1, 0, 0, args, 0));
/* Run the adaptive sampling kernels at selected samples aligned to step samples. */
uint filter_sample = sample + wtile->num_samples - 1;
@@ -1957,10 +1961,7 @@ void CUDADevice::shader(DeviceTask &task)
CUdeviceptr d_output = (CUdeviceptr)task.shader_output;
/* get kernel function */
- if (task.shader_eval_type >= SHADER_EVAL_BAKE) {
- cuda_assert(cuModuleGetFunction(&cuShader, cuModule, "kernel_cuda_bake"));
- }
- else if (task.shader_eval_type == SHADER_EVAL_DISPLACE) {
+ if (task.shader_eval_type == SHADER_EVAL_DISPLACE) {
cuda_assert(cuModuleGetFunction(&cuShader, cuModule, "kernel_cuda_displace"));
}
else {
@@ -2297,9 +2298,12 @@ void CUDADevice::thread_run(DeviceTask *task)
split_kernel->path_trace(task, tile, void_buffer, void_buffer);
}
else {
- path_trace(*task, tile, work_tiles);
+ render(*task, tile, work_tiles);
}
}
+ else if (tile.task == RenderTile::BAKE) {
+ render(*task, tile, work_tiles);
+ }
else if (tile.task == RenderTile::DENOISE) {
tile.sample = tile.start_sample + tile.num_samples;
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index c701c14318f..fc6febd8cee 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -188,6 +188,7 @@ class CPUDevice : public Device {
convert_to_byte_kernel;
KernelFunctions<void (*)(KernelGlobals *, uint4 *, float4 *, int, int, int, int, int)>
shader_kernel;
+ KernelFunctions<void (*)(KernelGlobals *, float *, int, int, int, int, int)> bake_kernel;
KernelFunctions<void (*)(
int, TileInfo *, int, int, float *, float *, float *, float *, float *, int *, int, int)>
@@ -270,6 +271,7 @@ class CPUDevice : public Device {
REGISTER_KERNEL(convert_to_half_float),
REGISTER_KERNEL(convert_to_byte),
REGISTER_KERNEL(shader),
+ REGISTER_KERNEL(bake),
REGISTER_KERNEL(filter_divide_shadow),
REGISTER_KERNEL(filter_get_feature),
REGISTER_KERNEL(filter_write_feature),
@@ -895,7 +897,7 @@ class CPUDevice : public Device {
}
}
- void path_trace(DeviceTask &task, RenderTile &tile, KernelGlobals *kg)
+ void render(DeviceTask &task, RenderTile &tile, KernelGlobals *kg)
{
const bool use_coverage = kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE;
@@ -919,12 +921,21 @@ class CPUDevice : public Device {
break;
}
- for (int y = tile.y; y < tile.y + tile.h; y++) {
- for (int x = tile.x; x < tile.x + tile.w; x++) {
- if (use_coverage) {
- coverage.init_pixel(x, y);
+ 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++) {
+ if (use_coverage) {
+ coverage.init_pixel(x, y);
+ }
+ path_trace_kernel()(kg, render_buffer, sample, x, y, tile.offset, tile.stride);
+ }
+ }
+ }
+ else {
+ for (int y = tile.y; y < tile.y + tile.h; y++) {
+ for (int x = tile.x; x < tile.x + tile.w; x++) {
+ bake_kernel()(kg, render_buffer, sample, x, y, tile.offset, tile.stride);
}
- path_trace_kernel()(kg, render_buffer, sample, x, y, tile.offset, tile.stride);
}
}
tile.sample = sample + 1;
@@ -1019,9 +1030,12 @@ class CPUDevice : public Device {
split_kernel->path_trace(&task, tile, kgbuffer, void_buffer);
}
else {
- path_trace(task, tile, kg);
+ render(task, tile, kg);
}
}
+ else if (tile.task == RenderTile::BAKE) {
+ render(task, tile, kg);
+ }
else if (tile.task == RenderTile::DENOISE) {
denoise(denoising, tile);
task.update_progress(&tile, tile.w * tile.h);
diff --git a/intern/cycles/device/opencl/device_opencl.h b/intern/cycles/device/opencl/device_opencl.h
index d6f4fb43061..389268e1c2a 100644
--- a/intern/cycles/device/opencl/device_opencl.h
+++ b/intern/cycles/device/opencl/device_opencl.h
@@ -451,6 +451,7 @@ class OpenCLDevice : public Device {
device_ptr rgba_half);
void shader(DeviceTask &task);
void update_adaptive(DeviceTask &task, RenderTile &tile, int sample);
+ void bake(DeviceTask &task, RenderTile &tile);
void denoise(RenderTile &tile, DenoisingTask &denoising);
diff --git a/intern/cycles/device/opencl/device_opencl_impl.cpp b/intern/cycles/device/opencl/device_opencl_impl.cpp
index 2766f85d17c..beb3174b111 100644
--- a/intern/cycles/device/opencl/device_opencl_impl.cpp
+++ b/intern/cycles/device/opencl/device_opencl_impl.cpp
@@ -1367,6 +1367,9 @@ void OpenCLDevice::thread_run(DeviceTask *task)
*/
clFinish(cqCommandQueue);
}
+ else if (tile.task == RenderTile::BAKE) {
+ bake(*task, tile);
+ }
else if (tile.task == RenderTile::DENOISE) {
tile.sample = tile.start_sample + tile.num_samples;
denoise(tile, denoising);
@@ -1858,10 +1861,7 @@ void OpenCLDevice::shader(DeviceTask &task)
cl_int d_offset = task.offset;
OpenCLDevice::OpenCLProgram *program = &background_program;
- if (task.shader_eval_type >= SHADER_EVAL_BAKE) {
- program = &bake_program;
- }
- else if (task.shader_eval_type == SHADER_EVAL_DISPLACE) {
+ if (task.shader_eval_type == SHADER_EVAL_DISPLACE) {
program = &displace_program;
}
program->wait_for_availability();
@@ -1892,6 +1892,51 @@ void OpenCLDevice::shader(DeviceTask &task)
}
}
+void OpenCLDevice::bake(DeviceTask &task, RenderTile &rtile)
+{
+ scoped_timer timer(&rtile.buffers->render_time);
+
+ /* Cast arguments to cl types. */
+ cl_mem d_data = CL_MEM_PTR(const_mem_map["__data"]->device_pointer);
+ cl_mem d_buffer = CL_MEM_PTR(rtile.buffer);
+ cl_int d_x = rtile.x;
+ cl_int d_y = rtile.y;
+ cl_int d_w = rtile.w;
+ cl_int d_h = rtile.h;
+ cl_int d_offset = rtile.offset;
+ cl_int d_stride = rtile.stride;
+
+ bake_program.wait_for_availability();
+ cl_kernel kernel = bake_program();
+
+ cl_uint start_arg_index = kernel_set_args(kernel, 0, d_data, d_buffer);
+
+ set_kernel_arg_buffers(kernel, &start_arg_index);
+
+ start_arg_index += kernel_set_args(
+ kernel, start_arg_index, d_x, d_y, d_w, d_h, d_offset, d_stride);
+
+ int start_sample = rtile.start_sample;
+ int end_sample = rtile.start_sample + rtile.num_samples;
+
+ for (int sample = start_sample; sample < end_sample; sample++) {
+ if (task.get_cancel()) {
+ if (task.need_finish_queue == false)
+ break;
+ }
+
+ kernel_set_args(kernel, start_arg_index, sample);
+
+ enqueue_kernel(kernel, d_w, d_h);
+
+ rtile.sample = sample + 1;
+
+ task.update_progress(&rtile, rtile.w * rtile.h);
+ }
+
+ clFinish(cqCommandQueue);
+}
+
string OpenCLDevice::kernel_build_options(const string *debug_src)
{
string build_options = "-cl-no-signed-zeros -cl-mad-enable ";
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index 0a9631ad931..dc80e67a891 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -229,8 +229,6 @@ ccl_device_inline int bsdf_sample(KernelGlobals *kg,
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
label = bsdf_microfacet_ggx_sample(kg,
sc,
@@ -281,7 +279,6 @@ ccl_device_inline int bsdf_sample(KernelGlobals *kg,
&sd->lcg_state);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
label = bsdf_microfacet_beckmann_sample(kg,
sc,
@@ -298,7 +295,6 @@ ccl_device_inline int bsdf_sample(KernelGlobals *kg,
pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
label = bsdf_ashikhmin_shirley_sample(sc,
sd->Ng,
sd->I,
@@ -504,8 +500,6 @@ ccl_device_inline
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf);
break;
@@ -519,12 +513,10 @@ ccl_device_inline
sc, sd->I, omega_in, pdf, &sd->lcg_state);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
eval = bsdf_ashikhmin_shirley_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
@@ -595,8 +587,6 @@ ccl_device_inline
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf);
break;
@@ -610,12 +600,10 @@ ccl_device_inline
sc, sd->I, omega_in, pdf, &sd->lcg_state);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
eval = bsdf_ashikhmin_shirley_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
@@ -679,18 +667,14 @@ ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
bsdf_microfacet_ggx_blur(sc, roughness);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
bsdf_microfacet_beckmann_blur(sc, roughness);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
bsdf_ashikhmin_shirley_blur(sc, roughness);
break;
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
@@ -719,18 +703,14 @@ ccl_device bool bsdf_merge(ShaderClosure *a, ShaderClosure *b)
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
return bsdf_microfacet_merge(a, b);
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
return bsdf_ashikhmin_velvet_merge(a, b);
diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
index 6495ae743ab..0d50172a907 100644
--- a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
+++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
@@ -34,18 +34,9 @@ CCL_NAMESPACE_BEGIN
ccl_device int bsdf_ashikhmin_shirley_setup(MicrofacetBsdf *bsdf)
{
bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
- bsdf->alpha_y = bsdf->alpha_x;
-
- bsdf->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
- return SD_BSDF | SD_BSDF_HAS_EVAL;
-}
-
-ccl_device int bsdf_ashikhmin_shirley_aniso_setup(MicrofacetBsdf *bsdf)
-{
- bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
bsdf->alpha_y = clamp(bsdf->alpha_y, 1e-4f, 1.0f);
- bsdf->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
+ bsdf->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
return SD_BSDF | SD_BSDF_HAS_EVAL;
}
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index 2884ea62a18..d9e81535b62 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -256,9 +256,7 @@ ccl_device_forceinline float3 reflection_color(const MicrofacetBsdf *bsdf, float
{
float3 F = make_float3(1.0f, 1.0f, 1.0f);
bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID ||
- bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID ||
- bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID);
-
+ bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID);
if (use_fresnel) {
float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
@@ -311,19 +309,27 @@ ccl_device int bsdf_microfacet_ggx_setup(MicrofacetBsdf *bsdf)
bsdf->extra = NULL;
bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_y = saturate(bsdf->alpha_y);
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
return SD_BSDF | SD_BSDF_HAS_EVAL;
}
+/* Required to maintain OSL interface. */
+ccl_device int bsdf_microfacet_ggx_isotropic_setup(MicrofacetBsdf *bsdf)
+{
+ bsdf->alpha_y = bsdf->alpha_x;
+
+ return bsdf_microfacet_ggx_setup(bsdf);
+}
+
ccl_device int bsdf_microfacet_ggx_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
{
bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0);
bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_y = saturate(bsdf->alpha_y);
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID;
@@ -361,32 +367,6 @@ ccl_device bool bsdf_microfacet_merge(const ShaderClosure *a, const ShaderClosur
(bsdf_a->extra->clearcoat == bsdf_b->extra->clearcoat)));
}
-ccl_device int bsdf_microfacet_ggx_aniso_setup(MicrofacetBsdf *bsdf)
-{
- bsdf->extra = NULL;
-
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = saturate(bsdf->alpha_y);
-
- bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
-
- return SD_BSDF | SD_BSDF_HAS_EVAL;
-}
-
-ccl_device int bsdf_microfacet_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
-{
- bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0);
-
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = saturate(bsdf->alpha_y);
-
- bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID;
-
- bsdf_microfacet_fresnel_color(sd, bsdf);
-
- return SD_BSDF | SD_BSDF_HAS_EVAL;
-}
-
ccl_device int bsdf_microfacet_ggx_refraction_setup(MicrofacetBsdf *bsdf)
{
bsdf->extra = NULL;
@@ -636,8 +616,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg,
*eval = make_float3(1e6f, 1e6f, 1e6f);
bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID ||
- bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID ||
- bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID);
+ bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID);
/* if fresnel is used, calculate the color with reflection_color(...) */
if (use_fresnel) {
@@ -811,19 +790,18 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg,
ccl_device int bsdf_microfacet_beckmann_setup(MicrofacetBsdf *bsdf)
{
bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_y = saturate(bsdf->alpha_y);
bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
return SD_BSDF | SD_BSDF_HAS_EVAL;
}
-ccl_device int bsdf_microfacet_beckmann_aniso_setup(MicrofacetBsdf *bsdf)
+/* Required to maintain OSL interface. */
+ccl_device int bsdf_microfacet_beckmann_isotropic_setup(MicrofacetBsdf *bsdf)
{
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = saturate(bsdf->alpha_y);
+ bsdf->alpha_y = bsdf->alpha_x;
- bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
- return SD_BSDF | SD_BSDF_HAS_EVAL;
+ return bsdf_microfacet_beckmann_setup(bsdf);
}
ccl_device int bsdf_microfacet_beckmann_refraction_setup(MicrofacetBsdf *bsdf)
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
index a5fe989bcd1..9795c8da065 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
@@ -384,7 +384,7 @@ ccl_device int bsdf_microfacet_multi_ggx_common_setup(MicrofacetBsdf *bsdf)
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
}
-ccl_device int bsdf_microfacet_multi_ggx_aniso_setup(MicrofacetBsdf *bsdf)
+ccl_device int bsdf_microfacet_multi_ggx_setup(MicrofacetBsdf *bsdf)
{
if (is_zero(bsdf->T))
bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
@@ -394,8 +394,7 @@ ccl_device int bsdf_microfacet_multi_ggx_aniso_setup(MicrofacetBsdf *bsdf)
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
}
-ccl_device int bsdf_microfacet_multi_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf,
- const ShaderData *sd)
+ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
{
if (is_zero(bsdf->T))
bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
@@ -407,26 +406,6 @@ ccl_device int bsdf_microfacet_multi_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsd
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
}
-ccl_device int bsdf_microfacet_multi_ggx_setup(MicrofacetBsdf *bsdf)
-{
- bsdf->alpha_y = bsdf->alpha_x;
-
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
-
- return bsdf_microfacet_multi_ggx_common_setup(bsdf);
-}
-
-ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
-{
- bsdf->alpha_y = bsdf->alpha_x;
-
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
-
- bsdf_microfacet_fresnel_color(sd, bsdf);
-
- return bsdf_microfacet_multi_ggx_common_setup(bsdf);
-}
-
ccl_device int bsdf_microfacet_multi_ggx_refraction_setup(MicrofacetBsdf *bsdf)
{
bsdf->alpha_y = bsdf->alpha_x;
diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h
index f1fc697553a..2709a9da734 100644
--- a/intern/cycles/kernel/kernel_bake.h
+++ b/intern/cycles/kernel/kernel_bake.h
@@ -18,38 +18,40 @@ CCL_NAMESPACE_BEGIN
#ifdef __BAKING__
-ccl_device_inline void compute_light_pass(
+ccl_device_noinline void compute_light_pass(
KernelGlobals *kg, ShaderData *sd, PathRadiance *L, uint rng_hash, int pass_filter, int sample)
{
kernel_assert(kernel_data.film.use_light_pass);
- PathRadiance L_sample;
- PathState state;
- Ray ray;
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- /* emission and indirect shader data memory used by various functions */
- ShaderData emission_sd, indirect_sd;
-
- ray.P = sd->P + sd->Ng;
- ray.D = -sd->Ng;
- ray.t = FLT_MAX;
-# ifdef __CAMERA_MOTION__
- ray.time = 0.5f;
-# endif
+ /* Emission and indirect shader data memory used by various functions. */
+ ShaderDataTinyStorage emission_sd_storage;
+ ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage);
+ ShaderData indirect_sd;
- /* init radiance */
- path_radiance_init(kg, &L_sample);
+ /* Init radiance. */
+ path_radiance_init(kg, L);
- /* init path state */
- path_state_init(kg, &emission_sd, &state, rng_hash, sample, NULL);
+ /* Init path state. */
+ PathState state;
+ path_state_init(kg, emission_sd, &state, rng_hash, sample, NULL);
- /* evaluate surface shader */
+ /* Evaluate surface shader. */
shader_eval_surface(kg, sd, &state, NULL, state.flag);
/* TODO, disable more closures we don't need besides transparent */
shader_bsdf_disable_transparency(kg, sd);
+ /* Init ray. */
+ Ray ray;
+ ray.P = sd->P + sd->Ng;
+ ray.D = -sd->Ng;
+ ray.t = FLT_MAX;
+# ifdef __CAMERA_MOTION__
+ ray.time = 0.5f;
+# endif
+
# ifdef __BRANCHED_PATH__
if (!kernel_data.integrator.branched) {
/* regular path tracer */
@@ -57,14 +59,13 @@ ccl_device_inline void compute_light_pass(
/* sample ambient occlusion */
if (pass_filter & BAKE_FILTER_AO) {
- kernel_path_ao(
- kg, sd, &emission_sd, &L_sample, &state, throughput, shader_bsdf_alpha(kg, sd));
+ kernel_path_ao(kg, sd, emission_sd, L, &state, throughput, shader_bsdf_alpha(kg, sd));
}
/* sample emission */
if ((pass_filter & BAKE_FILTER_EMISSION) && (sd->flag & SD_EMISSION)) {
float3 emission = indirect_primitive_emission(kg, sd, 0.0f, state.flag, state.ray_pdf);
- path_radiance_accum_emission(kg, &L_sample, &state, throughput, emission);
+ path_radiance_accum_emission(kg, L, &state, throughput, emission);
}
bool is_sss_sample = false;
@@ -77,12 +78,10 @@ ccl_device_inline void compute_light_pass(
SubsurfaceIndirectRays ss_indirect;
kernel_path_subsurface_init_indirect(&ss_indirect);
if (kernel_path_subsurface_scatter(
- kg, sd, &emission_sd, &L_sample, &state, &ray, &throughput, &ss_indirect)) {
+ kg, sd, emission_sd, L, &state, &ray, &throughput, &ss_indirect)) {
while (ss_indirect.num_rays) {
- kernel_path_subsurface_setup_indirect(
- kg, &ss_indirect, &state, &ray, &L_sample, &throughput);
- kernel_path_indirect(
- kg, &indirect_sd, &emission_sd, &ray, throughput, &state, &L_sample);
+ kernel_path_subsurface_setup_indirect(kg, &ss_indirect, &state, &ray, L, &throughput);
+ kernel_path_indirect(kg, &indirect_sd, emission_sd, &ray, throughput, &state, L);
}
is_sss_sample = true;
}
@@ -91,18 +90,18 @@ ccl_device_inline void compute_light_pass(
/* sample light and BSDF */
if (!is_sss_sample && (pass_filter & (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT))) {
- kernel_path_surface_connect_light(kg, sd, &emission_sd, throughput, &state, &L_sample);
+ kernel_path_surface_connect_light(kg, sd, emission_sd, throughput, &state, L);
- if (kernel_path_surface_bounce(kg, sd, &throughput, &state, &L_sample.state, &ray)) {
+ if (kernel_path_surface_bounce(kg, sd, &throughput, &state, &L->state, &ray)) {
# ifdef __LAMP_MIS__
state.ray_t = 0.0f;
# endif
/* compute indirect light */
- kernel_path_indirect(kg, &indirect_sd, &emission_sd, &ray, throughput, &state, &L_sample);
+ kernel_path_indirect(kg, &indirect_sd, emission_sd, &ray, throughput, &state, L);
/* sum and reset indirect light pass variables for the next samples */
- path_radiance_sum_indirect(&L_sample);
- path_radiance_reset_indirect(&L_sample);
+ path_radiance_sum_indirect(L);
+ path_radiance_reset_indirect(L);
}
}
# ifdef __BRANCHED_PATH__
@@ -112,13 +111,13 @@ ccl_device_inline void compute_light_pass(
/* sample ambient occlusion */
if (pass_filter & BAKE_FILTER_AO) {
- kernel_branched_path_ao(kg, sd, &emission_sd, &L_sample, &state, throughput);
+ kernel_branched_path_ao(kg, sd, emission_sd, L, &state, throughput);
}
/* sample emission */
if ((pass_filter & BAKE_FILTER_EMISSION) && (sd->flag & SD_EMISSION)) {
float3 emission = indirect_primitive_emission(kg, sd, 0.0f, state.flag, state.ray_pdf);
- path_radiance_accum_emission(kg, &L_sample, &state, throughput, emission);
+ path_radiance_accum_emission(kg, L, &state, throughput, emission);
}
# ifdef __SUBSURFACE__
@@ -127,7 +126,7 @@ ccl_device_inline void compute_light_pass(
/* When mixing BSSRDF and BSDF closures we should skip BSDF lighting
* if scattering was successful. */
kernel_branched_path_subsurface_scatter(
- kg, sd, &indirect_sd, &emission_sd, &L_sample, &state, &ray, throughput);
+ kg, sd, &indirect_sd, emission_sd, L, &state, &ray, throughput);
}
# endif
@@ -138,19 +137,16 @@ ccl_device_inline void compute_light_pass(
if (kernel_data.integrator.use_direct_light) {
int all = kernel_data.integrator.sample_all_lights_direct;
kernel_branched_path_surface_connect_light(
- kg, sd, &emission_sd, &state, throughput, 1.0f, &L_sample, all);
+ kg, sd, emission_sd, &state, throughput, 1.0f, L, all);
}
# endif
/* indirect light */
kernel_branched_path_surface_indirect_light(
- kg, sd, &indirect_sd, &emission_sd, throughput, 1.0f, &state, &L_sample);
+ kg, sd, &indirect_sd, emission_sd, throughput, 1.0f, &state, L);
}
}
# endif
-
- /* accumulate into master L */
- path_radiance_accum_sample(L, &L_sample);
}
/* this helps with AA but it's not the real solution as it does not AA the geometry
@@ -225,41 +221,28 @@ ccl_device float3 kernel_bake_evaluate_direct_indirect(KernelGlobals *kg,
return out;
}
-ccl_device void kernel_bake_evaluate(KernelGlobals *kg,
- ccl_global uint4 *input,
- ccl_global float4 *output,
- ShaderEvalType type,
- int pass_filter,
- int i,
- int offset,
- int sample)
+ccl_device void kernel_bake_evaluate(
+ KernelGlobals *kg, ccl_global float *buffer, int sample, int x, int y, int offset, int stride)
{
- ShaderData sd;
- PathState state = {0};
- uint4 in = input[i * 2];
- uint4 diff = input[i * 2 + 1];
-
- float3 out = make_float3(0.0f, 0.0f, 0.0f);
+ /* Setup render buffers. */
+ const int index = offset + x + y * stride;
+ const int pass_stride = kernel_data.film.pass_stride;
+ buffer += index * pass_stride;
- int object = in.x;
- int prim = in.y;
+ ccl_global float *primitive = buffer + kernel_data.film.pass_bake_primitive;
+ ccl_global float *differential = buffer + kernel_data.film.pass_bake_differential;
+ ccl_global float *output = buffer + kernel_data.film.pass_combined;
+ int prim = __float_as_uint(primitive[1]);
if (prim == -1)
return;
- float u = __uint_as_float(in.z);
- float v = __uint_as_float(in.w);
-
- float dudx = __uint_as_float(diff.x);
- float dudy = __uint_as_float(diff.y);
- float dvdx = __uint_as_float(diff.z);
- float dvdy = __uint_as_float(diff.w);
+ prim += kernel_data.bake.tri_offset;
+ /* Random number generator. */
+ uint rng_hash = hash_uint2(x, y) ^ kernel_data.integrator.seed;
int num_samples = kernel_data.integrator.aa_samples;
- /* random number generator */
- uint rng_hash = cmj_hash(offset + i, kernel_data.integrator.seed);
-
float filter_x, filter_y;
if (sample == 0) {
filter_x = filter_y = 0.5f;
@@ -268,23 +251,29 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg,
path_rng_2D(kg, rng_hash, sample, num_samples, PRNG_FILTER_U, &filter_x, &filter_y);
}
- /* subpixel u/v offset */
+ /* Barycentric UV with subpixel offset. */
+ float u = primitive[2];
+ float v = primitive[3];
+
+ float dudx = differential[0];
+ float dudy = differential[1];
+ float dvdx = differential[2];
+ float dvdy = differential[3];
+
if (sample > 0) {
u = bake_clamp_mirror_repeat(u + dudx * (filter_x - 0.5f) + dudy * (filter_y - 0.5f), 1.0f);
v = bake_clamp_mirror_repeat(v + dvdx * (filter_x - 0.5f) + dvdy * (filter_y - 0.5f),
1.0f - u);
}
- /* triangle */
+ /* Shader data setup. */
+ int object = kernel_data.bake.object_index;
int shader;
float3 P, Ng;
triangle_point_normal(kg, object, prim, u, v, &P, &Ng, &shader);
- /* light passes */
- PathRadiance L;
- path_radiance_init(kg, &L);
-
+ ShaderData sd;
shader_setup_from_sample(
kg,
&sd,
@@ -302,7 +291,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg,
LAMP_NONE);
sd.I = sd.N;
- /* update differentials */
+ /* Setup differentials. */
sd.dP.dx = sd.dPdu * dudx + sd.dPdv * dvdx;
sd.dP.dy = sd.dPdu * dudy + sd.dPdv * dvdy;
sd.du.dx = dudx;
@@ -310,17 +299,24 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg,
sd.dv.dx = dvdx;
sd.dv.dy = dvdy;
- /* set RNG state for shaders that use sampling */
+ /* Set RNG state for shaders that use sampling. */
+ PathState state = {0};
state.rng_hash = rng_hash;
state.rng_offset = 0;
state.sample = sample;
state.num_samples = num_samples;
state.min_ray_pdf = FLT_MAX;
- /* light passes if we need more than color */
- if (pass_filter & ~BAKE_FILTER_COLOR)
+ /* Light passes if we need more than color. */
+ PathRadiance L;
+ int pass_filter = kernel_data.bake.pass_filter;
+
+ if (kernel_data.bake.pass_filter & ~BAKE_FILTER_COLOR)
compute_light_pass(kg, &sd, &L, rng_hash, pass_filter, sample);
+ float3 out = make_float3(0.0f, 0.0f, 0.0f);
+
+ ShaderEvalType type = (ShaderEvalType)kernel_data.bake.type;
switch (type) {
/* data passes */
case SHADER_EVAL_NORMAL:
@@ -441,10 +437,8 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg,
}
/* write output */
- const float output_fac = 1.0f / num_samples;
- const float4 scaled_result = make_float4(out.x, out.y, out.z, 1.0f) * output_fac;
-
- output[i] = (sample == 0) ? scaled_result : output[i] + scaled_result;
+ const float4 result = make_float4(out.x, out.y, out.z, 1.0f);
+ kernel_write_pass_float4(output, result);
}
#endif /* __BAKING__ */
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index ce908ce0fe2..d918abed381 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -1041,11 +1041,19 @@ ccl_device_forceinline void triangle_light_sample(KernelGlobals *kg,
}
}
else {
- /* compute random point in triangle */
- randu = sqrtf(randu);
+ /* compute random point in triangle. From Eric Heitz's "A Low-Distortion Map Between Triangle
+ * and Square" */
+ float u = randu;
+ float v = randv;
+ if (v > u) {
+ u *= 0.5f;
+ v -= u;
+ }
+ else {
+ v *= 0.5f;
+ u -= v;
+ }
- const float u = 1.0f - randu;
- const float v = randv * randu;
const float t = 1.0f - u - v;
ls->P = u * V[0] + v * V[1] + t * V[2];
/* compute incoming direction, distance and pdf */
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index a1f8c35348d..304835a1685 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -395,6 +395,10 @@ typedef enum PassType {
PASS_VOLUME_INDIRECT,
/* No Scatter color since it's tricky to define what it would even mean. */
PASS_CATEGORY_LIGHT_END = 63,
+
+ PASS_BAKE_PRIMITIVE,
+ PASS_BAKE_DIFFERENTIAL,
+ PASS_CATEGORY_BAKE_END = 95
} PassType;
#define PASS_ANY (~0)
@@ -1248,6 +1252,10 @@ typedef struct KernelFilm {
float4 xyz_to_b;
float4 rgb_to_y;
+ int pass_bake_primitive;
+ int pass_bake_differential;
+ int pad;
+
#ifdef __KERNEL_DEBUG__
int pass_bvh_traversed_nodes;
int pass_bvh_traversed_instances;
@@ -1427,6 +1435,14 @@ typedef struct KernelTables {
} KernelTables;
static_assert_align(KernelTables, 16);
+typedef struct KernelBake {
+ int object_index;
+ int tri_offset;
+ int type;
+ int pass_filter;
+} KernelBake;
+static_assert_align(KernelBake, 16);
+
typedef struct KernelData {
KernelCamera cam;
KernelFilm film;
@@ -1435,6 +1451,7 @@ typedef struct KernelData {
KernelBVH bvh;
KernelCurves curve;
KernelTables tables;
+ KernelBake bake;
} KernelData;
static_assert_align(KernelData, 16);
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu.h
index 683f4b88d79..ea3103f12c3 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_cpu.h
+++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu.h
@@ -46,6 +46,9 @@ void KERNEL_FUNCTION_FULL_NAME(shader)(KernelGlobals *kg,
int offset,
int sample);
+void KERNEL_FUNCTION_FULL_NAME(bake)(
+ KernelGlobals *kg, float *buffer, int sample, int x, int y, int offset, int stride);
+
/* Split kernels */
void KERNEL_FUNCTION_FULL_NAME(data_init)(KernelGlobals *kg,
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h
index 091e53cfd83..5aa3fb14318 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h
+++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h
@@ -132,6 +132,18 @@ void KERNEL_FUNCTION_FULL_NAME(convert_to_half_float)(KernelGlobals *kg,
# endif /* KERNEL_STUB */
}
+/* Bake */
+
+void KERNEL_FUNCTION_FULL_NAME(bake)(
+ KernelGlobals *kg, float *buffer, int sample, int x, int y, int offset, int stride)
+{
+# ifdef KERNEL_STUB
+ STUB_ASSERT(KERNEL_ARCH, bake);
+# else
+ kernel_bake_evaluate(kg, buffer, sample, x, y, offset, stride);
+# endif /* KERNEL_STUB */
+}
+
/* Shader Evaluate */
void KERNEL_FUNCTION_FULL_NAME(shader)(KernelGlobals *kg,
@@ -146,12 +158,7 @@ void KERNEL_FUNCTION_FULL_NAME(shader)(KernelGlobals *kg,
# ifdef KERNEL_STUB
STUB_ASSERT(KERNEL_ARCH, shader);
# else
- if (type >= SHADER_EVAL_BAKE) {
-# ifdef __BAKING__
- kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, filter, i, offset, sample);
-# endif
- }
- else if (type == SHADER_EVAL_DISPLACE) {
+ if (type == SHADER_EVAL_DISPLACE) {
kernel_displace_evaluate(kg, input, output, i);
}
else {
diff --git a/intern/cycles/kernel/kernels/cuda/kernel.cu b/intern/cycles/kernel/kernels/cuda/kernel.cu
index c4c810c6a82..d4f41132a11 100644
--- a/intern/cycles/kernel/kernels/cuda/kernel.cu
+++ b/intern/cycles/kernel/kernels/cuda/kernel.cu
@@ -214,13 +214,16 @@ kernel_cuda_background(uint4 *input,
#ifdef __BAKING__
extern "C" __global__ void
CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS)
-kernel_cuda_bake(uint4 *input, float4 *output, int type, int filter, int sx, int sw, int offset, int sample)
+kernel_cuda_bake(WorkTile *tile, uint total_work_size)
{
- int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
+ int work_index = ccl_global_id(0);
+
+ if(work_index < total_work_size) {
+ uint x, y, sample;
+ get_work_pixel(tile, work_index, &x, &y, &sample);
- if(x < sx + sw) {
KernelGlobals kg;
- kernel_bake_evaluate(&kg, input, output, (ShaderEvalType)type, filter, x, offset, sample);
+ kernel_bake_evaluate(&kg, tile->buffer, sample, x, y, tile->offset, tile->stride);
}
}
#endif
diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp
index ea5e00ec23c..872a55143cc 100644
--- a/intern/cycles/kernel/osl/osl_closures.cpp
+++ b/intern/cycles/kernel/osl/osl_closures.cpp
@@ -100,14 +100,14 @@ CLOSURE_FLOAT3_PARAM(DiffuseClosure, params.N),
BSDF_CLOSURE_CLASS_END(AshikhminVelvet, ashikhmin_velvet)
BSDF_CLOSURE_CLASS_BEGIN(AshikhminShirley,
- ashikhmin_shirley_aniso,
+ ashikhmin_shirley,
MicrofacetBsdf,
LABEL_GLOSSY | LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, params.N),
CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, params.T),
CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, params.alpha_x),
CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, params.alpha_y),
- BSDF_CLOSURE_CLASS_END(AshikhminShirley, ashikhmin_shirley_aniso)
+ BSDF_CLOSURE_CLASS_END(AshikhminShirley, ashikhmin_shirley)
BSDF_CLOSURE_CLASS_BEGIN(DiffuseToon, diffuse_toon, ToonBsdf, LABEL_DIFFUSE)
CLOSURE_FLOAT3_PARAM(DiffuseToonClosure, params.N),
@@ -121,42 +121,42 @@ CLOSURE_FLOAT3_PARAM(DiffuseClosure, params.N),
CLOSURE_FLOAT_PARAM(GlossyToonClosure, params.smooth),
BSDF_CLOSURE_CLASS_END(GlossyToon, glossy_toon)
+ BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXIsotropic,
+ microfacet_ggx_isotropic,
+ MicrofacetBsdf,
+ LABEL_GLOSSY | LABEL_REFLECT)
+ CLOSURE_FLOAT3_PARAM(MicrofacetGGXIsotropicClosure, params.N),
+ CLOSURE_FLOAT_PARAM(MicrofacetGGXIsotropicClosure, params.alpha_x),
+ BSDF_CLOSURE_CLASS_END(MicrofacetGGXIsotropic, microfacet_ggx_isotropic)
+
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGX,
microfacet_ggx,
MicrofacetBsdf,
LABEL_GLOSSY | LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(MicrofacetGGXClosure, params.N),
+ CLOSURE_FLOAT3_PARAM(MicrofacetGGXClosure, params.T),
CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, params.alpha_x),
+ CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, params.alpha_y),
BSDF_CLOSURE_CLASS_END(MicrofacetGGX, microfacet_ggx)
- BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXAniso,
- microfacet_ggx_aniso,
+ BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannIsotropic,
+ microfacet_beckmann_isotropic,
MicrofacetBsdf,
LABEL_GLOSSY | LABEL_REFLECT)
- CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, params.N),
- CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, params.T),
- CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, params.alpha_x),
- CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, params.alpha_y),
- BSDF_CLOSURE_CLASS_END(MicrofacetGGXAniso, microfacet_ggx_aniso)
+ CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannIsotropicClosure, params.N),
+ CLOSURE_FLOAT_PARAM(MicrofacetBeckmannIsotropicClosure, params.alpha_x),
+ BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannIsotropic, microfacet_beckmann_isotropic)
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmann,
microfacet_beckmann,
MicrofacetBsdf,
LABEL_GLOSSY | LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannClosure, params.N),
+ CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannClosure, params.T),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, params.alpha_x),
+ CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, params.alpha_y),
BSDF_CLOSURE_CLASS_END(MicrofacetBeckmann, microfacet_beckmann)
- BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannAniso,
- microfacet_beckmann_aniso,
- MicrofacetBsdf,
- LABEL_GLOSSY | LABEL_REFLECT)
- CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, params.N),
- CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, params.T),
- CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, params.alpha_x),
- CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, params.alpha_y),
- BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannAniso, microfacet_beckmann_aniso)
-
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXRefraction,
microfacet_ggx_refraction,
MicrofacetBsdf,
@@ -362,13 +362,13 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
id++,
closure_bsdf_transparent_params(),
closure_bsdf_transparent_prepare);
- register_closure(
- ss, "microfacet_ggx", id++, bsdf_microfacet_ggx_params(), bsdf_microfacet_ggx_prepare);
register_closure(ss,
- "microfacet_ggx_aniso",
+ "microfacet_ggx",
id++,
- bsdf_microfacet_ggx_aniso_params(),
- bsdf_microfacet_ggx_aniso_prepare);
+ bsdf_microfacet_ggx_isotropic_params(),
+ bsdf_microfacet_ggx_isotropic_prepare);
+ register_closure(
+ ss, "microfacet_ggx_aniso", id++, bsdf_microfacet_ggx_params(), bsdf_microfacet_ggx_prepare);
register_closure(ss,
"microfacet_ggx_refraction",
id++,
@@ -417,13 +417,13 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
register_closure(ss,
"microfacet_beckmann",
id++,
- bsdf_microfacet_beckmann_params(),
- bsdf_microfacet_beckmann_prepare);
+ bsdf_microfacet_beckmann_isotropic_params(),
+ bsdf_microfacet_beckmann_isotropic_prepare);
register_closure(ss,
"microfacet_beckmann_aniso",
id++,
- bsdf_microfacet_beckmann_aniso_params(),
- bsdf_microfacet_beckmann_aniso_prepare);
+ bsdf_microfacet_beckmann_params(),
+ bsdf_microfacet_beckmann_prepare);
register_closure(ss,
"microfacet_beckmann_refraction",
id++,
@@ -432,8 +432,8 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
register_closure(ss,
"ashikhmin_shirley",
id++,
- bsdf_ashikhmin_shirley_aniso_params(),
- bsdf_ashikhmin_shirley_aniso_prepare);
+ bsdf_ashikhmin_shirley_params(),
+ bsdf_ashikhmin_shirley_prepare);
register_closure(
ss, "ashikhmin_velvet", id++, bsdf_ashikhmin_velvet_params(), bsdf_ashikhmin_velvet_prepare);
register_closure(
@@ -582,7 +582,7 @@ class MicrofacetGGXAnisoFresnelClosure : public MicrofacetFresnelClosure {
return;
}
- sd->flag |= bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf, sd);
+ sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
}
};
@@ -676,7 +676,7 @@ class MicrofacetMultiGGXAnisoClosure : public MicrofacetMultiClosure {
}
bsdf->ior = 0.0f;
- sd->flag |= bsdf_microfacet_multi_ggx_aniso_setup(bsdf);
+ sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
}
};
@@ -801,7 +801,7 @@ class MicrofacetMultiGGXAnisoFresnelClosure : public MicrofacetMultiFresnelClosu
return;
}
- sd->flag |= bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf, sd);
+ sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd);
}
};
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h
index cb1b521c585..2c57a142692 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -320,9 +320,9 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg,
/* setup bsdf */
if (distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID ||
roughness <= 0.075f) /* use single-scatter GGX */
- sd->flag |= bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf, sd);
+ sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
else /* use multi-scatter GGX */
- sd->flag |= bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf, sd);
+ sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd);
}
}
# ifdef __CAUSTICS_TRICKS__
@@ -515,12 +515,34 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg,
float roughness = sqr(param1);
bsdf->N = N;
- bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->alpha_x = roughness;
- bsdf->alpha_y = roughness;
bsdf->ior = 0.0f;
bsdf->extra = NULL;
+ if (data_node.y == SVM_STACK_INVALID) {
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->alpha_x = roughness;
+ bsdf->alpha_y = roughness;
+ }
+ else {
+ bsdf->T = stack_load_float3(stack, data_node.y);
+
+ /* rotate tangent */
+ float rotation = stack_load_float(stack, data_node.z);
+ if (rotation != 0.0f)
+ bsdf->T = rotate_around_axis(bsdf->T, bsdf->N, rotation * M_2PI_F);
+
+ /* compute roughness */
+ float anisotropy = clamp(param2, -0.99f, 0.99f);
+ if (anisotropy < 0.0f) {
+ bsdf->alpha_x = roughness / (1.0f + anisotropy);
+ bsdf->alpha_y = roughness * (1.0f + anisotropy);
+ }
+ else {
+ bsdf->alpha_x = roughness * (1.0f - anisotropy);
+ bsdf->alpha_y = roughness / (1.0f - anisotropy);
+ }
+ }
+
/* setup bsdf */
if (type == CLOSURE_BSDF_REFLECTION_ID)
sd->flag |= bsdf_reflection_setup(bsdf);
@@ -529,10 +551,10 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg,
else if (type == CLOSURE_BSDF_MICROFACET_GGX_ID)
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
else if (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID) {
- kernel_assert(stack_valid(data_node.z));
+ kernel_assert(stack_valid(data_node.w));
bsdf->extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if (bsdf->extra) {
- bsdf->extra->color = stack_load_float3(stack, data_node.z);
+ bsdf->extra->color = stack_load_float3(stack, data_node.w);
bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f);
bsdf->extra->clearcoat = 0.0f;
sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
@@ -675,64 +697,6 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg,
sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(bsdf);
break;
}
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID: {
-#ifdef __CAUSTICS_TRICKS__
- if (!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
- break;
-#endif
- float3 weight = sd->svm_closure_weight * mix_weight;
- MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
-
- if (bsdf) {
- bsdf->N = N;
- bsdf->extra = NULL;
- bsdf->T = stack_load_float3(stack, data_node.y);
-
- /* rotate tangent */
- float rotation = stack_load_float(stack, data_node.z);
-
- if (rotation != 0.0f)
- bsdf->T = rotate_around_axis(bsdf->T, bsdf->N, rotation * M_2PI_F);
-
- /* compute roughness */
- float roughness = sqr(param1);
- float anisotropy = clamp(param2, -0.99f, 0.99f);
-
- if (anisotropy < 0.0f) {
- bsdf->alpha_x = roughness / (1.0f + anisotropy);
- bsdf->alpha_y = roughness * (1.0f + anisotropy);
- }
- else {
- bsdf->alpha_x = roughness * (1.0f - anisotropy);
- bsdf->alpha_y = roughness / (1.0f - anisotropy);
- }
-
- bsdf->ior = 0.0f;
-
- if (type == CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID) {
- sd->flag |= bsdf_microfacet_beckmann_aniso_setup(bsdf);
- }
- else if (type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID) {
- sd->flag |= bsdf_microfacet_ggx_aniso_setup(bsdf);
- }
- else if (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID) {
- kernel_assert(stack_valid(data_node.w));
- bsdf->extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
- if (bsdf->extra) {
- bsdf->extra->color = stack_load_float3(stack, data_node.w);
- bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->extra->clearcoat = 0.0f;
- sd->flag |= bsdf_microfacet_multi_ggx_aniso_setup(bsdf);
- }
- }
- else
- sd->flag |= bsdf_ashikhmin_shirley_aniso_setup(bsdf);
- }
- break;
- }
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: {
float3 weight = sd->svm_closure_weight * mix_weight;
VelvetBsdf *bsdf = (VelvetBsdf *)bsdf_alloc(sd, sizeof(VelvetBsdf), weight);
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index 85ede7770e9..e913d9e0489 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -539,12 +539,6 @@ typedef enum ClosureType {
CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID,
CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID,
CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID,
- CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID,
- CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID,
- CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID,
- CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_FRESNEL_ID,
- CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID,
- CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID,
CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
CLOSURE_BSDF_PHONG_RAMP_ID,
CLOSURE_BSDF_GLOSSY_TOON_ID,
@@ -605,10 +599,9 @@ typedef enum ClosureType {
#define CLOSURE_IS_BSDF_TRANSPARENT(type) (type == CLOSURE_BSDF_TRANSPARENT_ID)
#define CLOSURE_IS_BSDF_MULTISCATTER(type) \
(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID || \
- type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID || \
type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
#define CLOSURE_IS_BSDF_MICROFACET(type) \
- ((type >= CLOSURE_BSDF_MICROFACET_GGX_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID) || \
+ ((type >= CLOSURE_BSDF_MICROFACET_GGX_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID) || \
(type >= CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID && \
type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) || \
(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID))
@@ -616,8 +609,7 @@ typedef enum ClosureType {
(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID || \
type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID || \
type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID || \
- type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID || \
- type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID)
+ type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID)
#define CLOSURE_IS_BSDF_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID)
#define CLOSURE_IS_BSSRDF(type) \
(type >= CLOSURE_BSSRDF_CUBIC_ID && type <= CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID)
diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp
index 35f942b3e9b..6044182a51a 100644
--- a/intern/cycles/render/bake.cpp
+++ b/intern/cycles/render/bake.cpp
@@ -15,6 +15,7 @@
*/
#include "render/bake.h"
+#include "render/buffers.h"
#include "render/integrator.h"
#include "render/mesh.h"
#include "render/object.h"
@@ -24,272 +25,130 @@
CCL_NAMESPACE_BEGIN
-BakeData::BakeData(const int object, const size_t tri_offset, const size_t num_pixels)
- : m_object(object), m_tri_offset(tri_offset), m_num_pixels(num_pixels)
+static int aa_samples(Scene *scene, Object *object, ShaderEvalType type)
{
- m_primitive.resize(num_pixels);
- m_u.resize(num_pixels);
- m_v.resize(num_pixels);
- m_dudx.resize(num_pixels);
- m_dudy.resize(num_pixels);
- m_dvdx.resize(num_pixels);
- m_dvdy.resize(num_pixels);
-}
-
-BakeData::~BakeData()
-{
- m_primitive.clear();
- m_u.clear();
- m_v.clear();
- m_dudx.clear();
- m_dudy.clear();
- m_dvdx.clear();
- m_dvdy.clear();
-}
-
-void BakeData::set(int i, int prim, float uv[2], float dudx, float dudy, float dvdx, float dvdy)
-{
- m_primitive[i] = (prim == -1 ? -1 : m_tri_offset + prim);
- m_u[i] = uv[0];
- m_v[i] = uv[1];
- m_dudx[i] = dudx;
- m_dudy[i] = dudy;
- m_dvdx[i] = dvdx;
- m_dvdy[i] = dvdy;
-}
-
-void BakeData::set_null(int i)
-{
- m_primitive[i] = -1;
-}
-
-int BakeData::object()
-{
- return m_object;
-}
-
-size_t BakeData::size()
-{
- return m_num_pixels;
-}
+ if (type == SHADER_EVAL_UV || type == SHADER_EVAL_ROUGHNESS) {
+ return 1;
+ }
+ 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 (shader->has_bump) {
+ return scene->integrator->aa_samples;
+ }
+ }
+ }
-bool BakeData::is_valid(int i)
-{
- return m_primitive[i] != -1;
+ return 1;
+ }
+ else {
+ return scene->integrator->aa_samples;
+ }
}
-uint4 BakeData::data(int i)
+/* Keep it synced with kernel_bake.h logic */
+static int shader_type_to_pass_filter(ShaderEvalType type, int pass_filter)
{
- return make_uint4(m_object, m_primitive[i], __float_as_int(m_u[i]), __float_as_int(m_v[i]));
-}
+ const int component_flags = pass_filter &
+ (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT | BAKE_FILTER_COLOR);
-uint4 BakeData::differentials(int i)
-{
- return make_uint4(__float_as_int(m_dudx[i]),
- __float_as_int(m_dudy[i]),
- __float_as_int(m_dvdx[i]),
- __float_as_int(m_dvdy[i]));
+ switch (type) {
+ case SHADER_EVAL_AO:
+ return BAKE_FILTER_AO;
+ case SHADER_EVAL_SHADOW:
+ return BAKE_FILTER_DIRECT;
+ case SHADER_EVAL_DIFFUSE:
+ return BAKE_FILTER_DIFFUSE | component_flags;
+ case SHADER_EVAL_GLOSSY:
+ return BAKE_FILTER_GLOSSY | component_flags;
+ case SHADER_EVAL_TRANSMISSION:
+ return BAKE_FILTER_TRANSMISSION | component_flags;
+ case SHADER_EVAL_COMBINED:
+ return pass_filter;
+ default:
+ return 0;
+ }
}
BakeManager::BakeManager()
{
- m_bake_data = NULL;
- m_is_baking = false;
+ type = SHADER_EVAL_BAKE;
+ pass_filter = 0;
+
need_update = true;
- m_shader_limit = 512 * 512;
}
BakeManager::~BakeManager()
{
- if (m_bake_data)
- delete m_bake_data;
}
bool BakeManager::get_baking()
{
- return m_is_baking;
-}
-
-void BakeManager::set_baking(const bool value)
-{
- m_is_baking = value;
+ return !object_name.empty();
}
-BakeData *BakeManager::init(const int object, const size_t tri_offset, const size_t num_pixels)
+void BakeManager::set(Scene *scene,
+ const std::string &object_name_,
+ ShaderEvalType type_,
+ int pass_filter_)
{
- m_bake_data = new BakeData(object, tri_offset, num_pixels);
- return m_bake_data;
-}
-
-void BakeManager::set_shader_limit(const size_t x, const size_t y)
-{
- m_shader_limit = x * y;
- m_shader_limit = (size_t)pow(2, std::ceil(log(m_shader_limit) / log(2)));
-}
+ object_name = object_name_;
+ type = type_;
+ pass_filter = shader_type_to_pass_filter(type_, pass_filter_);
-bool BakeManager::bake(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress &progress,
- ShaderEvalType shader_type,
- const int pass_filter,
- BakeData *bake_data,
- float result[])
-{
- size_t num_pixels = bake_data->size();
-
- int num_samples = aa_samples(scene, bake_data, shader_type);
+ Pass::add(PASS_BAKE_PRIMITIVE, scene->film->passes);
+ Pass::add(PASS_BAKE_DIFFERENTIAL, scene->film->passes);
- /* calculate the total pixel samples for the progress bar */
- total_pixel_samples = 0;
- for (size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
- size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
- total_pixel_samples += shader_size * num_samples;
+ if (type == SHADER_EVAL_UV) {
+ /* force UV to be available */
+ Pass::add(PASS_UV, scene->film->passes);
}
- progress.reset_sample();
- progress.set_total_pixel_samples(total_pixel_samples);
-
- /* needs to be up to date for baking specific AA samples */
- dscene->data.integrator.aa_samples = num_samples;
- device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
-
- for (size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
- size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
- /* setup input for device task */
- device_vector<uint4> d_input(device, "bake_input", MEM_READ_ONLY);
- uint4 *d_input_data = d_input.alloc(shader_size * 2);
- size_t d_input_size = 0;
-
- for (size_t i = shader_offset; i < (shader_offset + shader_size); i++) {
- d_input_data[d_input_size++] = bake_data->data(i);
- d_input_data[d_input_size++] = bake_data->differentials(i);
- }
-
- if (d_input_size == 0) {
- m_is_baking = false;
- return false;
- }
-
- /* run device task */
- device_vector<float4> d_output(device, "bake_output", MEM_READ_WRITE);
- d_output.alloc(shader_size);
- d_output.zero_to_device();
- d_input.copy_to_device();
-
- DeviceTask task(DeviceTask::SHADER);
- task.shader_input = d_input.device_pointer;
- task.shader_output = d_output.device_pointer;
- task.shader_eval_type = shader_type;
- task.shader_filter = pass_filter;
- task.shader_x = 0;
- task.offset = shader_offset;
- task.shader_w = d_output.size();
- task.num_samples = num_samples;
- task.get_cancel = function_bind(&Progress::get_cancel, &progress);
- task.update_progress_sample = function_bind(&Progress::add_samples_update, &progress, _1, _2);
-
- device->task_add(task);
- device->task_wait();
-
- if (progress.get_cancel()) {
- d_input.free();
- d_output.free();
- m_is_baking = false;
- return false;
- }
-
- d_output.copy_from_device(0, 1, d_output.size());
- d_input.free();
-
- /* read result */
- int k = 0;
-
- float4 *offset = d_output.data();
-
- size_t depth = 4;
- for (size_t i = shader_offset; i < (shader_offset + shader_size); i++) {
- size_t index = i * depth;
- float4 out = offset[k++];
-
- if (bake_data->is_valid(i)) {
- for (size_t j = 0; j < 4; j++) {
- result[index + j] = out[j];
- }
- }
- }
-
- d_output.free();
+ /* force use_light_pass to be true if we bake more than just colors */
+ if (pass_filter & ~BAKE_FILTER_COLOR) {
+ Pass::add(PASS_LIGHT, scene->film->passes);
}
- m_is_baking = false;
- return true;
+ /* create device and update scene */
+ scene->film->tag_update(scene);
+ scene->integrator->tag_update(scene);
+
+ need_update = true;
}
void BakeManager::device_update(Device * /*device*/,
- DeviceScene * /*dscene*/,
- Scene * /*scene*/,
- Progress &progress)
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress & /* progress */)
{
if (!need_update)
return;
- if (progress.get_cancel())
- return;
+ KernelIntegrator *kintegrator = &dscene->data.integrator;
+ KernelBake *kbake = &dscene->data.bake;
- need_update = false;
-}
-
-void BakeManager::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
-{
-}
-
-int BakeManager::aa_samples(Scene *scene, BakeData *bake_data, ShaderEvalType type)
-{
- if (type == SHADER_EVAL_UV || type == SHADER_EVAL_ROUGHNESS) {
- return 1;
- }
- else if (type == SHADER_EVAL_NORMAL) {
- /* Only antialias normal if mesh has bump mapping. */
- Object *object = scene->objects[bake_data->object()];
+ kbake->type = type;
+ kbake->pass_filter = pass_filter;
- if (object->geometry) {
- foreach (Shader *shader, object->geometry->used_shaders) {
- if (shader->has_bump) {
- return scene->integrator->aa_samples;
- }
- }
+ int object_index = 0;
+ foreach (Object *object, scene->objects) {
+ const Geometry *geom = object->geometry;
+ if (object->name == object_name && geom->type == Geometry::MESH) {
+ kbake->object_index = object_index;
+ kbake->tri_offset = geom->prim_offset;
+ kintegrator->aa_samples = aa_samples(scene, object, type);
+ break;
}
- return 1;
- }
- else {
- return scene->integrator->aa_samples;
+ object_index++;
}
+
+ need_update = false;
}
-/* Keep it synced with kernel_bake.h logic */
-int BakeManager::shader_type_to_pass_filter(ShaderEvalType type, const int pass_filter)
+void BakeManager::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
{
- const int component_flags = pass_filter &
- (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT | BAKE_FILTER_COLOR);
-
- switch (type) {
- case SHADER_EVAL_AO:
- return BAKE_FILTER_AO;
- case SHADER_EVAL_SHADOW:
- return BAKE_FILTER_DIRECT;
- case SHADER_EVAL_DIFFUSE:
- return BAKE_FILTER_DIFFUSE | component_flags;
- case SHADER_EVAL_GLOSSY:
- return BAKE_FILTER_GLOSSY | component_flags;
- case SHADER_EVAL_TRANSMISSION:
- return BAKE_FILTER_TRANSMISSION | component_flags;
- case SHADER_EVAL_COMBINED:
- return pass_filter;
- default:
- return 0;
- }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/bake.h b/intern/cycles/render/bake.h
index 88537623efb..93e664c2ab1 100644
--- a/intern/cycles/render/bake.h
+++ b/intern/cycles/render/bake.h
@@ -25,67 +25,23 @@
CCL_NAMESPACE_BEGIN
-class BakeData {
- public:
- BakeData(const int object, const size_t tri_offset, const size_t num_pixels);
- ~BakeData();
-
- void set(int i, int prim, float uv[2], float dudx, float dudy, float dvdx, float dvdy);
- void set_null(int i);
- int object();
- size_t size();
- uint4 data(int i);
- uint4 differentials(int i);
- bool is_valid(int i);
-
- private:
- int m_object;
- size_t m_tri_offset;
- size_t m_num_pixels;
- vector<int> m_primitive;
- vector<float> m_u;
- vector<float> m_v;
- vector<float> m_dudx;
- vector<float> m_dudy;
- vector<float> m_dvdx;
- vector<float> m_dvdy;
-};
-
class BakeManager {
public:
BakeManager();
~BakeManager();
+ void set(Scene *scene, const std::string &object_name, ShaderEvalType type, int pass_filter);
bool get_baking();
- void set_baking(const bool value);
-
- BakeData *init(const int object, const size_t tri_offset, const size_t num_pixels);
-
- void set_shader_limit(const size_t x, const size_t y);
-
- bool bake(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress &progress,
- ShaderEvalType shader_type,
- const int pass_filter,
- BakeData *bake_data,
- float result[]);
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
void device_free(Device *device, DeviceScene *dscene);
- static int shader_type_to_pass_filter(ShaderEvalType type, const int pass_filter);
- static int aa_samples(Scene *scene, BakeData *bake_data, ShaderEvalType type);
-
bool need_update;
- size_t total_pixel_samples;
-
private:
- BakeData *m_bake_data;
- bool m_is_baking;
- size_t m_shader_limit;
+ ShaderEvalType type;
+ int pass_filter;
+ std::string object_name;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp
index 2d89fb9ffba..b26366af852 100644
--- a/intern/cycles/render/buffers.cpp
+++ b/intern/cycles/render/buffers.cpp
@@ -459,6 +459,40 @@ bool RenderBuffers::get_pass_rect(
return false;
}
+bool RenderBuffers::set_pass_rect(PassType type, int components, float *pixels)
+{
+ if (buffer.data() == NULL) {
+ return false;
+ }
+
+ int pass_offset = 0;
+
+ for (size_t j = 0; j < params.passes.size(); j++) {
+ Pass &pass = params.passes[j];
+
+ if (pass.type != type) {
+ pass_offset += pass.components;
+ continue;
+ }
+
+ float *out = buffer.data() + pass_offset;
+ int pass_stride = params.get_passes_size();
+ int size = params.width * params.height;
+
+ assert(pass.components == components);
+
+ for (int i = 0; i < size; i++, out += pass_stride, pixels += components) {
+ for (int j = 0; j < components; j++) {
+ out[j] = pixels[j];
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
/* Display Buffer */
DisplayBuffer::DisplayBuffer(Device *device, bool linear)
diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h
index 42efb031843..975bae2239c 100644
--- a/intern/cycles/render/buffers.h
+++ b/intern/cycles/render/buffers.h
@@ -92,6 +92,7 @@ class RenderBuffers {
const string &name, float exposure, int sample, int components, float *pixels);
bool get_denoising_pass_rect(
int offset, float exposure, int sample, int components, float *pixels);
+ bool set_pass_rect(PassType type, int components, float *pixels);
};
/* Display Buffer
@@ -130,7 +131,7 @@ class DisplayBuffer {
class RenderTile {
public:
- typedef enum { PATH_TRACE = (1 << 0), DENOISE = (1 << 1) } Task;
+ typedef enum { PATH_TRACE = (1 << 0), BAKE = (1 << 1), DENOISE = (1 << 2) } Task;
Task task;
int x, y, w, h;
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index 26eda93fadd..d7cbf4a3581 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -196,6 +196,10 @@ void Pass::add(PassType type, vector<Pass> &passes, const char *name)
case PASS_AOV_VALUE:
pass.components = 1;
break;
+ case PASS_BAKE_PRIMITIVE:
+ case PASS_BAKE_DIFFERENTIAL:
+ pass.components = 4;
+ break;
default:
assert(false);
break;
@@ -386,11 +390,13 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
if (pass.type <= PASS_CATEGORY_MAIN_END) {
kfilm->pass_flag |= pass_flag;
}
- else {
- assert(pass.type <= PASS_CATEGORY_LIGHT_END);
+ else if (pass.type <= PASS_CATEGORY_LIGHT_END) {
kfilm->use_light_pass = 1;
kfilm->light_pass_flag |= pass_flag;
}
+ else {
+ assert(pass.type <= PASS_CATEGORY_BAKE_END);
+ }
switch (pass.type) {
case PASS_COMBINED:
@@ -471,6 +477,13 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
kfilm->pass_volume_direct = kfilm->pass_stride;
break;
+ case PASS_BAKE_PRIMITIVE:
+ kfilm->pass_bake_primitive = kfilm->pass_stride;
+ break;
+ case PASS_BAKE_DIFFERENTIAL:
+ kfilm->pass_bake_differential = kfilm->pass_stride;
+ break;
+
#ifdef WITH_CYCLES_DEBUG
case PASS_BVH_TRAVERSED_NODES:
kfilm->pass_bvh_traversed_nodes = kfilm->pass_stride;
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 4b4958fe3da..cdcaeb246dd 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -2166,12 +2166,11 @@ NODE_DEFINE(AnisotropicBsdfNode)
SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
static NodeEnum distribution_enum;
- distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID);
- distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID);
- distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID);
- distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID);
- SOCKET_ENUM(
- distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID);
+ distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
+ distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ID);
+ distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
+ distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
+ SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ID);
SOCKET_IN_VECTOR(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TANGENT);
@@ -2186,7 +2185,7 @@ NODE_DEFINE(AnisotropicBsdfNode)
AnisotropicBsdfNode::AnisotropicBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
+ closure = CLOSURE_BSDF_MICROFACET_GGX_ID;
}
void AnisotropicBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
@@ -2205,7 +2204,7 @@ void AnisotropicBsdfNode::compile(SVMCompiler &compiler)
{
closure = distribution;
- if (closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID)
+ if (closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID)
BsdfNode::compile(
compiler, input("Roughness"), input("Anisotropy"), input("Rotation"), input("Color"));
else
@@ -2299,7 +2298,7 @@ void GlossyBsdfNode::compile(SVMCompiler &compiler)
if (closure == CLOSURE_BSDF_REFLECTION_ID)
BsdfNode::compile(compiler, NULL, NULL);
else if (closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID)
- BsdfNode::compile(compiler, input("Roughness"), NULL, input("Color"));
+ BsdfNode::compile(compiler, input("Roughness"), NULL, NULL, input("Color"));
else
BsdfNode::compile(compiler, input("Roughness"), NULL);
}
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index f7df81a0601..361a1465aac 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -410,7 +410,16 @@ bool Session::acquire_tile(RenderTile &rtile, Device *tile_device, uint tile_typ
rtile.num_samples = tile_manager.state.num_samples;
rtile.resolution = tile_manager.state.resolution_divider;
rtile.tile_index = tile->index;
- rtile.task = tile->state == Tile::DENOISE ? RenderTile::DENOISE : RenderTile::PATH_TRACE;
+
+ 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;
+ }
tile_lock.unlock();
@@ -451,11 +460,20 @@ bool Session::acquire_tile(RenderTile &rtile, Device *tile_device, uint tile_typ
rtile.buffers = tile->buffers;
rtile.sample = tile_manager.state.sample;
- /* this will tag tile as IN PROGRESS in blender-side render pipeline,
- * which is needed to highlight currently rendering tile before first
- * sample was processed for it
- */
- update_tile_sample(rtile);
+ if (read_bake_tile_cb) {
+ /* This will read any passes needed as input for baking. */
+ {
+ thread_scoped_lock tile_lock(tile_mutex);
+ read_bake_tile_cb(rtile);
+ }
+ rtile.buffers->buffer.copy_to_device();
+ }
+ else {
+ /* This will tag tile as IN PROGRESS in blender-side render pipeline,
+ * which is needed to highlight currently rendering tile before first
+ * sample was processed for it. */
+ update_tile_sample(rtile);
+ }
return true;
}
@@ -484,6 +502,7 @@ void Session::release_tile(RenderTile &rtile, const bool need_denoise)
bool delete_tile;
if (tile_manager.finish_tile(rtile.tile_index, need_denoise, delete_tile)) {
+ /* Finished tile pixels write. */
if (write_render_tile_cb && params.progressive_refine == false) {
write_render_tile_cb(rtile);
}
@@ -494,6 +513,7 @@ void Session::release_tile(RenderTile &rtile, const bool need_denoise)
}
}
else {
+ /* In progress tile pixels update. */
if (update_render_tile_cb && params.progressive_refine == false) {
update_render_tile_cb(rtile, false);
}
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index f06952e8020..2707eed5531 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -148,6 +148,7 @@ class Session {
function<void(RenderTile &)> write_render_tile_cb;
function<void(RenderTile &, bool)> update_render_tile_cb;
+ function<void(RenderTile &)> read_bake_tile_cb;
explicit Session(const SessionParams &params);
~Session();
diff --git a/intern/cycles/util/util_avxb.h b/intern/cycles/util/util_avxb.h
index 5c03b1d88d7..34fafd188de 100644
--- a/intern/cycles/util/util_avxb.h
+++ b/intern/cycles/util/util_avxb.h
@@ -57,7 +57,7 @@ struct avxb {
: m256(_mm256_insertf128_ps(_mm256_castps128_ps256(a), b, 1))
{
}
- __forceinline operator const __m256 &(void) const
+ __forceinline operator const __m256 &(void)const
{
return m256;
}
diff --git a/intern/cycles/util/util_avxi.h b/intern/cycles/util/util_avxi.h
index 1b3810764b7..e658a4f848f 100644
--- a/intern/cycles/util/util_avxi.h
+++ b/intern/cycles/util/util_avxi.h
@@ -54,7 +54,7 @@ struct avxi {
__forceinline avxi(const __m256i a) : m256(a)
{
}
- __forceinline operator const __m256i &(void) const
+ __forceinline operator const __m256i &(void)const
{
return m256;
}
diff --git a/intern/cycles/util/util_sseb.h b/intern/cycles/util/util_sseb.h
index d817e23c47e..56f8f676ba1 100644
--- a/intern/cycles/util/util_sseb.h
+++ b/intern/cycles/util/util_sseb.h
@@ -57,7 +57,7 @@ struct sseb {
__forceinline sseb(const __m128 input) : m128(input)
{
}
- __forceinline operator const __m128 &(void) const
+ __forceinline operator const __m128 &(void)const
{
return m128;
}
diff --git a/intern/cycles/util/util_ssei.h b/intern/cycles/util/util_ssei.h
index a4db9193206..e2bf81310cc 100644
--- a/intern/cycles/util/util_ssei.h
+++ b/intern/cycles/util/util_ssei.h
@@ -57,7 +57,7 @@ struct ssei {
__forceinline ssei(const __m128i a) : m128(a)
{
}
- __forceinline operator const __m128i &(void) const
+ __forceinline operator const __m128i &(void)const
{
return m128;
}
diff --git a/intern/dualcon/dualcon.h b/intern/dualcon/dualcon.h
index e9bff72a1ce..60cec101545 100644
--- a/intern/dualcon/dualcon.h
+++ b/intern/dualcon/dualcon.h
@@ -29,7 +29,7 @@ typedef float (*DualConCo)[3];
typedef unsigned int (*DualConTri)[3];
-typedef unsigned int(*DualConLoop);
+typedef unsigned int *DualConLoop;
typedef struct DualConInput {
DualConLoop mloop;
diff --git a/intern/dualcon/intern/octree.cpp b/intern/dualcon/intern/octree.cpp
index 70b3b8bb457..c9d5639cb5d 100644
--- a/intern/dualcon/intern/octree.cpp
+++ b/intern/dualcon/intern/octree.cpp
@@ -480,7 +480,7 @@ void Octree::trace()
if (chdpath != NULL) {
dc_printf("there are incomplete rings.\n");
printPaths(chdpath);
- };
+ }
}
Node *Octree::trace(Node *newnode, int *st, int len, int depth, PathList *&paths)
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index 68fc9637e02..699ac4afe88 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -21,7 +21,6 @@
set(INC
.
../glew-mx
- ../string
../../source/blender/imbuf
../../source/blender/makesdna
)
@@ -86,7 +85,6 @@ set(SRC
set(LIB
bf_intern_glew_mx
- bf_intern_string
${GLEW_LIBRARY}
)
@@ -151,7 +149,7 @@ if(WITH_HEADLESS OR WITH_GHOST_SDL)
endif()
endif()
-elseif(APPLE AND NOT WITH_X11)
+elseif(APPLE AND NOT WITH_GHOST_X11)
list(APPEND SRC
intern/GHOST_DisplayManagerCocoa.mm
intern/GHOST_SystemCocoa.mm
@@ -179,73 +177,143 @@ elseif(APPLE AND NOT WITH_X11)
)
endif()
-elseif(WITH_X11)
- list(APPEND INC_SYS
- ${X11_X11_INCLUDE_PATH}
- )
-
- list(APPEND SRC
- intern/GHOST_DisplayManagerX11.cpp
- intern/GHOST_SystemX11.cpp
- intern/GHOST_TaskbarX11.cpp
- intern/GHOST_WindowX11.cpp
-
- intern/GHOST_DisplayManagerX11.h
- intern/GHOST_IconX11.h
- intern/GHOST_SystemX11.h
- intern/GHOST_TaskbarX11.h
- intern/GHOST_WindowX11.h
- )
+elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
+ if(WITH_GHOST_X11)
+ list(APPEND INC_SYS
+ ${X11_X11_INCLUDE_PATH}
+ )
- if(NOT WITH_GL_EGL)
list(APPEND SRC
- intern/GHOST_ContextGLX.cpp
-
- intern/GHOST_ContextGLX.h
+ intern/GHOST_DisplayManagerX11.cpp
+ intern/GHOST_SystemX11.cpp
+ intern/GHOST_TaskbarX11.cpp
+ intern/GHOST_WindowX11.cpp
+
+ intern/GHOST_DisplayManagerX11.h
+ intern/GHOST_IconX11.h
+ intern/GHOST_SystemX11.h
+ intern/GHOST_TaskbarX11.h
+ intern/GHOST_WindowX11.h
)
- endif()
- if(WITH_GHOST_XDND)
- add_definitions(-DWITH_XDND)
+ if(NOT WITH_GL_EGL)
+ list(APPEND SRC
+ intern/GHOST_ContextGLX.cpp
- list(APPEND LIB
- extern_xdnd
- )
+ intern/GHOST_ContextGLX.h
+ )
+ endif()
- list(APPEND INC
- ../../extern/xdnd
- )
+ if(WITH_GHOST_XDND)
+ add_definitions(-DWITH_XDND)
- list(APPEND SRC
- intern/GHOST_DropTargetX11.cpp
+ list(APPEND LIB
+ extern_xdnd
+ )
- intern/GHOST_DropTargetX11.h
- )
+ list(APPEND INC
+ ../../extern/xdnd
+ )
+
+ list(APPEND SRC
+ intern/GHOST_DropTargetX11.cpp
+
+ intern/GHOST_DropTargetX11.h
+ )
+ endif()
+
+ if(X11_XF86keysym_INCLUDE_PATH)
+ add_definitions(-DWITH_XF86KEYSYM)
+ list(APPEND INC_SYS
+ ${X11_XF86keysym_INCLUDE_PATH}
+ )
+ endif()
+
+ if(WITH_X11_XF86VMODE)
+ add_definitions(-DWITH_X11_XF86VMODE)
+ list(APPEND INC_SYS
+ ${X11_xf86vmode_INCLUDE_PATH}
+ )
+ endif()
+
+ if(WITH_X11_XFIXES)
+ add_definitions(-DWITH_X11_XFIXES)
+ list(APPEND INC_SYS
+ ${X11_Xfixes_INCLUDE_PATH}
+ )
+ endif()
+
+ if(WITH_X11_ALPHA)
+ add_definitions(-DWITH_X11_ALPHA)
+ endif()
+
+ if(WITH_X11_XINPUT)
+ add_definitions(-DWITH_X11_XINPUT)
+ list(APPEND INC_SYS
+ ${X11_Xinput_INCLUDE_PATH}
+ )
+ endif()
+
+ add_definitions(-DWITH_GHOST_X11)
endif()
- if(X11_XF86keysym_INCLUDE_PATH)
- add_definitions(-DWITH_XF86KEYSYM)
+ if(WITH_GHOST_WAYLAND)
list(APPEND INC_SYS
- ${X11_XF86keysym_INCLUDE_PATH}
+ ${wayland-client_INCLUDE_DIRS}
+ ${wayland-egl_INCLUDE_DIRS}
+ ${xkbcommon_INCLUDE_DIRS}
+ ${wayland-cursor_INCLUDE_DIRS}
)
- endif()
- if(WITH_X11_XF86VMODE)
- add_definitions(-DWITH_X11_XF86VMODE)
- list(APPEND INC_SYS
- ${X11_xf86vmode_INCLUDE_PATH}
+ list(APPEND SRC
+ intern/GHOST_SystemWayland.cpp
+ intern/GHOST_WindowWayland.cpp
+
+ intern/GHOST_SystemWayland.h
+ intern/GHOST_WindowWayland.h
)
- endif()
- if(WITH_X11_XFIXES)
- add_definitions(-DWITH_X11_XFIXES)
+ pkg_get_variable(WAYLAND_SCANNER wayland-scanner wayland_scanner)
+ pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
+
+ # Generate protocols bindings.
+ macro(generate_protocol_bindings NAME PROT_DEF)
+ add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.h
+ COMMAND ${WAYLAND_SCANNER} client-header ${PROT_DEF} ${NAME}-client-protocol.h
+ )
+ add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.c
+ COMMAND ${WAYLAND_SCANNER} private-code ${PROT_DEF} ${NAME}-client-protocol.c
+ DEPENDS ${NAME}-client-protocol.h
+ )
+ list(APPEND SRC
+ ${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.c
+ ${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.h
+ )
+ endmacro()
+
list(APPEND INC_SYS
- ${X11_Xfixes_INCLUDE_PATH}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ )
+
+ # xdg-shell.
+ generate_protocol_bindings(
+ xdg-shell
+ "${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml"
+ )
+ # Pointer-constraints.
+ generate_protocol_bindings(
+ pointer-constraints
+ "${WAYLAND_PROTOCOLS_DIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml"
+ )
+ # Relative-pointer.
+ generate_protocol_bindings(
+ relative-pointer
+ "${WAYLAND_PROTOCOLS_DIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml"
)
- endif()
- if(WITH_X11_ALPHA)
- add_definitions(-DWITH_X11_ALPHA)
+ add_definitions(-DWITH_GHOST_WAYLAND)
endif()
if(WITH_INPUT_NDOF)
@@ -260,14 +328,6 @@ elseif(WITH_X11)
add_definitions(-DPREFIX="${CMAKE_INSTALL_PREFIX}")
endif()
- if(WITH_X11_XINPUT)
- add_definitions(-DWITH_X11_XINPUT)
- list(APPEND INC_SYS
- ${X11_Xinput_INCLUDE_PATH}
- )
- endif()
-
- add_definitions(-DWITH_X11)
elseif(WIN32)
# # Warnings as errors, this is too strict!
diff --git a/intern/ghost/GHOST_IContext.h b/intern/ghost/GHOST_IContext.h
index 1225262a908..8c24261644a 100644
--- a/intern/ghost/GHOST_IContext.h
+++ b/intern/ghost/GHOST_IContext.h
@@ -26,7 +26,6 @@
#define __GHOST_IContext_H__
#include "GHOST_Types.h"
-#include "STR_String.h"
/**
* Interface for GHOST context.
diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h
index 58d1a08da74..9b619f5c684 100644
--- a/intern/ghost/GHOST_ISystem.h
+++ b/intern/ghost/GHOST_ISystem.h
@@ -27,6 +27,8 @@
#ifndef __GHOST_ISYSTEM_H__
#define __GHOST_ISYSTEM_H__
+#include <stdlib.h>
+
#include "GHOST_IContext.h"
#include "GHOST_ITimerTask.h"
#include "GHOST_IWindow.h"
@@ -240,7 +242,7 @@ class GHOST_ISystem {
* \param parentWindow: Parent (embedder) window
* \return The new window (or 0 if creation failed).
*/
- virtual GHOST_IWindow *createWindow(const STR_String &title,
+ virtual GHOST_IWindow *createWindow(const char *title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h
index daf07b81e01..62290d20f1c 100644
--- a/intern/ghost/GHOST_IWindow.h
+++ b/intern/ghost/GHOST_IWindow.h
@@ -27,7 +27,9 @@
#include "GHOST_Rect.h"
#include "GHOST_Types.h"
-#include "STR_String.h"
+
+#include <stdlib.h>
+#include <string>
/**
* Interface for GHOST windows.
@@ -81,13 +83,13 @@ class GHOST_IWindow {
* Sets the title displayed in the title bar.
* \param title The title to display in the title bar.
*/
- virtual void setTitle(const STR_String &title) = 0;
+ virtual void setTitle(const char *title) = 0;
/**
* Returns the title displayed in the title bar.
* \param title The title displayed in the title bar.
*/
- virtual void getTitle(STR_String &title) const = 0;
+ virtual std::string getTitle() const = 0;
/**
* Returns the window rectangle dimensions.
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index db9fd2e3bf9..843684b6d2e 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -24,6 +24,7 @@
*/
#include <stdlib.h>
+#include <string.h>
#include "GHOST_C-api.h"
#include "GHOST_IEvent.h"
@@ -527,17 +528,15 @@ void GHOST_SetTitle(GHOST_WindowHandle windowhandle, const char *title)
char *GHOST_GetTitle(GHOST_WindowHandle windowhandle)
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
- STR_String title;
+ std::string title = window->getTitle();
- window->getTitle(title);
-
- char *ctitle = (char *)malloc(title.Length() + 1);
+ char *ctitle = (char *)malloc(title.size() + 1);
if (ctitle == NULL) {
return NULL;
}
- strcpy(ctitle, title.Ptr());
+ strcpy(ctitle, title.c_str());
return ctitle;
}
@@ -678,7 +677,7 @@ GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle)
return context->activateDrawingContext();
}
else {
- GHOST_PRINT("GHOST_ActivateOpenGLContext: Context not valid");
+ GHOST_PRINTF("%s: Context not valid\n", __func__);
return GHOST_kFailure;
}
}
diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h
index 0163197e14a..5b5c2688297 100644
--- a/intern/ghost/intern/GHOST_Debug.h
+++ b/intern/ghost/intern/GHOST_Debug.h
@@ -33,15 +33,11 @@
#endif
#ifdef WITH_GHOST_DEBUG
-# define GHOST_DEBUG // spit ghost events to stdout
-#endif // WITH_GHOST_DEBUG
-
-#ifdef GHOST_DEBUG
# include <iostream>
# include <stdio.h> //for printf()
-#endif // GHOST_DEBUG
+#endif // WITH_GHOST_DEBUG
-#ifdef GHOST_DEBUG
+#ifdef WITH_GHOST_DEBUG
# define GHOST_PRINT(x) \
{ \
std::cout << x; \
@@ -52,10 +48,10 @@
printf(x, __VA_ARGS__); \
} \
(void)0
-#else // GHOST_DEBUG
+#else // WITH_GHOST_DEBUG
# define GHOST_PRINT(x)
# define GHOST_PRINTF(x, ...)
-#endif // GHOST_DEBUG
+#endif // WITH_GHOST_DEBUG
#ifdef WITH_ASSERT_ABORT
# include <stdio.h> //for fprintf()
@@ -70,7 +66,7 @@
} \
} \
(void)0
-#elif defined(GHOST_DEBUG)
+#elif defined(WITH_GHOST_DEBUG)
# define GHOST_ASSERT(x, info) \
{ \
if (!(x)) { \
@@ -80,8 +76,8 @@
} \
} \
(void)0
-#else // GHOST_DEBUG
+#else // WITH_GHOST_DEBUG
# define GHOST_ASSERT(x, info) ((void)0)
-#endif // GHOST_DEBUG
+#endif // WITH_GHOST_DEBUG
#endif // __GHOST_DEBUG_H__
diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
index aabaffc7732..3557c4cd0c5 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
+++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
@@ -80,13 +80,13 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(GHOST_TUns8 display,
GHOST_TSuccess success;
DEVMODE dm;
if (::EnumDisplaySettings(display_device.DeviceName, index, &dm)) {
-#ifdef GHOST_DEBUG
+#ifdef WITH_GHOST_DEBUG
printf("display mode: width=%d, height=%d, bpp=%d, frequency=%d\n",
dm.dmPelsWidth,
dm.dmPelsHeight,
dm.dmBitsPerPel,
dm.dmDisplayFrequency);
-#endif // GHOST_DEBUG
+#endif // WITH_GHOST_DEBUG
setting.xPixels = dm.dmPelsWidth;
setting.yPixels = dm.dmPelsHeight;
setting.bpp = dm.dmBitsPerPel;
@@ -142,16 +142,16 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting(
* dm.dmSize = sizeof(DEVMODE);
* dm.dmDriverExtra = 0;
*/
-#ifdef GHOST_DEBUG
+#ifdef WITH_GHOST_DEBUG
printf("display change: Requested settings:\n");
printf(" dmBitsPerPel=%d\n", dm.dmBitsPerPel);
printf(" dmPelsWidth=%d\n", dm.dmPelsWidth);
printf(" dmPelsHeight=%d\n", dm.dmPelsHeight);
printf(" dmDisplayFrequency=%d\n", dm.dmDisplayFrequency);
-#endif // GHOST_DEBUG
+#endif // WITH_GHOST_DEBUG
LONG status = ::ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
-#ifdef GHOST_DEBUG
+#ifdef WITH_GHOST_DEBUG
switch (status) {
case DISP_CHANGE_SUCCESSFUL:
printf("display change: The settings change was successful.\n");
@@ -182,6 +182,6 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting(
printf("display change: Return value invalid\n");
break;
}
-#endif // GHOST_DEBUG
+#endif // WITH_GHOST_DEBUG
return status == DISP_CHANGE_SUCCESSFUL ? GHOST_kSuccess : GHOST_kFailure;
}
diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.cpp b/intern/ghost/intern/GHOST_DropTargetWin32.cpp
index 9f8ce3b5095..fe11d9a28f2 100644
--- a/intern/ghost/intern/GHOST_DropTargetWin32.cpp
+++ b/intern/ghost/intern/GHOST_DropTargetWin32.cpp
@@ -28,10 +28,10 @@
#include "utf_winfunc.h"
#include "utfconv.h"
-#ifdef GHOST_DEBUG
+#ifdef WITH_GHOST_DEBUG
// utility
void printLastError(void);
-#endif // GHOST_DEBUG
+#endif // WITH_GHOST_DEBUG
GHOST_DropTargetWin32::GHOST_DropTargetWin32(GHOST_WindowWin32 *window, GHOST_SystemWin32 *system)
: m_window(window), m_system(system)
@@ -209,9 +209,9 @@ void *GHOST_DropTargetWin32::getGhostData(IDataObject *pDataObject)
// return getDropDataAsBitmap(pDataObject);
break;
default:
-#ifdef GHOST_DEBUG
+#ifdef WITH_GHOST_DEBUG
::printf("\nGHOST_kDragnDropTypeUnknown");
-#endif // GHOST_DEBUG
+#endif // WITH_GHOST_DEBUG
return NULL;
break;
}
@@ -284,10 +284,10 @@ void *GHOST_DropTargetWin32::getDropDataAsString(IDataObject *pDataObject)
// Free memory
::GlobalUnlock(stgmed.hGlobal);
::ReleaseStgMedium(&stgmed);
-#ifdef GHOST_DEBUG
+#ifdef WITH_GHOST_DEBUG
::printf("\n<converted droped unicode string>\n%s\n</droped converted unicode string>\n",
tmp_string);
-#endif // GHOST_DEBUG
+#endif // WITH_GHOST_DEBUG
return tmp_string;
}
}
@@ -336,9 +336,9 @@ int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char *&out)
NULL);
if (!size) {
-#ifdef GHOST_DEBUG
+#ifdef WITH_GHOST_DEBUG
::printLastError();
-#endif // GHOST_DEBUG
+#endif // WITH_GHOST_DEBUG
return 0;
}
@@ -351,16 +351,16 @@ int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char *&out)
size = ::WideCharToMultiByte(CP_ACP, 0x00000400, in, -1, (LPSTR)out, size, NULL, NULL);
if (!size) {
-#ifdef GHOST_DEBUG
+#ifdef WITH_GHOST_DEBUG
::printLastError();
-#endif // GHOST_DEBUG
+#endif // WITH_GHOST_DEBUG
::free(out);
out = NULL;
}
return size;
}
-#ifdef GHOST_DEBUG
+#ifdef WITH_GHOST_DEBUG
void printLastError(void)
{
LPTSTR s;
@@ -378,4 +378,4 @@ void printLastError(void)
LocalFree(s);
}
}
-#endif // GHOST_DEBUG
+#endif // WITH_GHOST_DEBUG
diff --git a/intern/ghost/intern/GHOST_EventKey.h b/intern/ghost/intern/GHOST_EventKey.h
index 24e20b20659..8f59c555914 100644
--- a/intern/ghost/intern/GHOST_EventKey.h
+++ b/intern/ghost/intern/GHOST_EventKey.h
@@ -25,6 +25,8 @@
#ifndef __GHOST_EVENTKEY_H__
#define __GHOST_EVENTKEY_H__
+#include <string.h>
+
#include "GHOST_Event.h"
/**
diff --git a/intern/ghost/intern/GHOST_EventPrinter.h b/intern/ghost/intern/GHOST_EventPrinter.h
index fad9ec3cc69..ead16525ec6 100644
--- a/intern/ghost/intern/GHOST_EventPrinter.h
+++ b/intern/ghost/intern/GHOST_EventPrinter.h
@@ -27,8 +27,6 @@
#include "GHOST_IEventConsumer.h"
-#include "STR_String.h"
-
/**
* An Event consumer that prints all the events to standard out.
* Really useful when debugging.
diff --git a/intern/ghost/intern/GHOST_ISystem.cpp b/intern/ghost/intern/GHOST_ISystem.cpp
index 914f6712676..7c12bfe0306 100644
--- a/intern/ghost/intern/GHOST_ISystem.cpp
+++ b/intern/ghost/intern/GHOST_ISystem.cpp
@@ -27,20 +27,22 @@
#include "GHOST_ISystem.h"
-#ifdef WITH_X11
+#if defined(WITH_HEADLESS)
+# include "GHOST_SystemNULL.h"
+#elif defined(WITH_GHOST_X11) && defined(WITH_GHOST_WAYLAND)
+# include "GHOST_SystemWayland.h"
# include "GHOST_SystemX11.h"
-#else
-# ifdef WITH_HEADLESS
-# include "GHOST_SystemNULL.h"
-# elif defined(WITH_GHOST_SDL)
-# include "GHOST_SystemSDL.h"
-# elif defined(WIN32)
-# include "GHOST_SystemWin32.h"
-# else
-# ifdef __APPLE__
-# include "GHOST_SystemCocoa.h"
-# endif
-# endif
+# include <stdexcept>
+#elif defined(WITH_GHOST_X11)
+# include "GHOST_SystemX11.h"
+#elif defined(WITH_GHOST_WAYLAND)
+# include "GHOST_SystemWayland.h"
+#elif defined(WITH_GHOST_SDL)
+# include "GHOST_SystemSDL.h"
+#elif defined(WIN32)
+# include "GHOST_SystemWin32.h"
+#elif defined(__APPLE__)
+# include "GHOST_SystemCocoa.h"
#endif
GHOST_ISystem *GHOST_ISystem::m_system = NULL;
@@ -49,20 +51,29 @@ GHOST_TSuccess GHOST_ISystem::createSystem()
{
GHOST_TSuccess success;
if (!m_system) {
-#ifdef WITH_X11
- m_system = new GHOST_SystemX11();
-#else
-# ifdef WITH_HEADLESS
+#if defined(WITH_HEADLESS)
m_system = new GHOST_SystemNULL();
-# elif defined(WITH_GHOST_SDL)
+#elif defined(WITH_GHOST_X11) && defined(WITH_GHOST_WAYLAND)
+ /* Special case, try Wayland, fall back to X11. */
+ try {
+ m_system = new GHOST_SystemWayland();
+ }
+ catch (const std::runtime_error &) {
+ /* fallback to X11. */
+ }
+ if (!m_system) {
+ m_system = new GHOST_SystemX11();
+ }
+#elif defined(WITH_GHOST_X11)
+ m_system = new GHOST_SystemX11();
+#elif defined(WITH_GHOST_WAYLAND)
+ m_system = new GHOST_SystemWayland();
+#elif defined(WITH_GHOST_SDL)
m_system = new GHOST_SystemSDL();
-# elif defined(WIN32)
+#elif defined(WIN32)
m_system = new GHOST_SystemWin32();
-# else
-# ifdef __APPLE__
+#elif defined(__APPLE__)
m_system = new GHOST_SystemCocoa();
-# endif
-# endif
#endif
success = m_system != NULL ? GHOST_kSuccess : GHOST_kFailure;
}
diff --git a/intern/ghost/intern/GHOST_IXrGraphicsBinding.h b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h
index cddb557d163..5794a682023 100644
--- a/intern/ghost/intern/GHOST_IXrGraphicsBinding.h
+++ b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h
@@ -33,7 +33,7 @@ class GHOST_IXrGraphicsBinding {
public:
union {
-#if defined(WITH_X11)
+#if defined(WITH_GHOST_X11)
XrGraphicsBindingOpenGLXlibKHR glx;
#elif defined(WIN32)
XrGraphicsBindingOpenGLWin32KHR wgl;
diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp
index a9fbadab37a..dda78c0ac5b 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManager.cpp
@@ -19,6 +19,8 @@
#include "GHOST_EventKey.h"
#include "GHOST_EventNDOF.h"
#include "GHOST_WindowManager.h"
+
+#include <limits.h>
#include <math.h>
#include <stdio.h> // for error/info reporting
#include <string.h> // for memory functions
diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp
index 85eb6d58679..b0d2adff4bc 100644
--- a/intern/ghost/intern/GHOST_System.cpp
+++ b/intern/ghost/intern/GHOST_System.cpp
@@ -23,8 +23,8 @@
#include "GHOST_System.h"
+#include <chrono>
#include <stdio.h> /* just for printf */
-#include <time.h>
#include "GHOST_DisplayManager.h"
#include "GHOST_EventManager.h"
@@ -58,12 +58,9 @@ GHOST_System::~GHOST_System()
GHOST_TUns64 GHOST_System::getMilliSeconds() const
{
- GHOST_TUns64 millis = ::clock();
- if (CLOCKS_PER_SEC != 1000) {
- millis *= 1000;
- millis /= CLOCKS_PER_SEC;
- }
- return millis;
+ return std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
}
GHOST_ITimerTask *GHOST_System::installTimer(GHOST_TUns64 delay,
@@ -309,12 +306,12 @@ GHOST_TSuccess GHOST_System::init()
m_windowManager = new GHOST_WindowManager();
m_eventManager = new GHOST_EventManager();
-#ifdef GHOST_DEBUG
+#ifdef WITH_GHOST_DEBUG
if (m_eventManager) {
m_eventPrinter = new GHOST_EventPrinter();
m_eventManager->addConsumer(m_eventPrinter);
}
-#endif // GHOST_DEBUG
+#endif // WITH_GHOST_DEBUG
if (m_timerManager && m_windowManager && m_eventManager) {
return GHOST_kSuccess;
@@ -367,7 +364,7 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window,
GHOST_ASSERT(m_displayManager,
"GHOST_System::createFullScreenWindow(): invalid display manager");
// GHOST_PRINT("GHOST_System::createFullScreenWindow(): creating full-screen window\n");
- *window = (GHOST_Window *)createWindow(STR_String(""),
+ *window = (GHOST_Window *)createWindow("",
0,
0,
settings.xPixels,
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
index eaaa2ff6ee6..0f58be49dff 100644
--- a/intern/ghost/intern/GHOST_System.h
+++ b/intern/ghost/intern/GHOST_System.h
@@ -31,9 +31,9 @@
#include "GHOST_Debug.h"
#include "GHOST_EventManager.h"
#include "GHOST_ModifierKeys.h"
-#ifdef GHOST_DEBUG
+#ifdef WITH_GHOST_DEBUG
# include "GHOST_EventPrinter.h"
-#endif // GHOST_DEBUG
+#endif // WITH_GHOST_DEBUG
class GHOST_DisplayManager;
class GHOST_Event;
@@ -390,9 +390,9 @@ class GHOST_System : public GHOST_ISystem {
#endif
/** Prints all the events. */
-#ifdef GHOST_DEBUG
+#ifdef WITH_GHOST_DEBUG
GHOST_EventPrinter *m_eventPrinter;
-#endif // GHOST_DEBUG
+#endif // WITH_GHOST_DEBUG
/** Settings of the display before the display went fullscreen. */
GHOST_DisplaySetting m_preFullScreenSetting;
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index 1e44c3e31d4..d058697470a 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -100,7 +100,7 @@ class GHOST_SystemCocoa : public GHOST_System {
* \param parentWindow Parent (embedder) window
* \return The new window (or 0 if creation failed).
*/
- GHOST_IWindow *createWindow(const STR_String &title,
+ GHOST_IWindow *createWindow(const char *title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 3d6d187587c..5592078e20e 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -698,7 +698,7 @@ void GHOST_SystemCocoa::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns3
getMainDisplayDimensions(width, height);
}
-GHOST_IWindow *GHOST_SystemCocoa::createWindow(const STR_String &title,
+GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
@@ -1063,14 +1063,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType,
}
switch (eventType) {
case GHOST_kEventWindowClose:
- // check for index of mainwindow as it would quit blender without dialog and discard
- if ([windowsList count] > 1 &&
- window->getCocoaWindow() != [windowsList objectAtIndex:[windowsList count] - 1]) {
- pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window));
- }
- else {
- handleQuitRequest(); // -> quit dialog
- }
+ pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window));
break;
case GHOST_kEventWindowActivate:
m_windowManager->setActiveWindow(window);
diff --git a/intern/ghost/intern/GHOST_SystemNULL.h b/intern/ghost/intern/GHOST_SystemNULL.h
index 68a726f2be8..186cb92d1aa 100644
--- a/intern/ghost/intern/GHOST_SystemNULL.h
+++ b/intern/ghost/intern/GHOST_SystemNULL.h
@@ -106,7 +106,7 @@ class GHOST_SystemNULL : public GHOST_System {
return GHOST_kFailure;
}
- GHOST_IWindow *createWindow(const STR_String &title,
+ GHOST_IWindow *createWindow(const char *title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp
index 97a75d7a0f5..b32ec4306e8 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.cpp
+++ b/intern/ghost/intern/GHOST_SystemSDL.cpp
@@ -49,7 +49,7 @@ GHOST_SystemSDL::~GHOST_SystemSDL()
SDL_Quit();
}
-GHOST_IWindow *GHOST_SystemSDL::createWindow(const STR_String &title,
+GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h
index 1994781530b..8feec9de61d 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.h
+++ b/intern/ghost/intern/GHOST_SystemSDL.h
@@ -80,7 +80,7 @@ class GHOST_SystemSDL : public GHOST_System {
private:
GHOST_TSuccess init();
- GHOST_IWindow *createWindow(const STR_String &title,
+ GHOST_IWindow *createWindow(const char *title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
new file mode 100644
index 00000000000..633451feb85
--- /dev/null
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -0,0 +1,1777 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ */
+
+#include "GHOST_SystemWayland.h"
+#include "GHOST_Event.h"
+#include "GHOST_EventButton.h"
+#include "GHOST_EventCursor.h"
+#include "GHOST_EventDragnDrop.h"
+#include "GHOST_EventKey.h"
+#include "GHOST_EventWheel.h"
+#include "GHOST_TimerManager.h"
+#include "GHOST_WindowManager.h"
+
+#include "GHOST_ContextEGL.h"
+
+#include <EGL/egl.h>
+#include <wayland-egl.h>
+
+#include <algorithm>
+#include <atomic>
+#include <stdexcept>
+#include <thread>
+#include <unordered_map>
+#include <unordered_set>
+
+#include <pointer-constraints-client-protocol.h>
+#include <relative-pointer-client-protocol.h>
+#include <wayland-cursor.h>
+#include <xkbcommon/xkbcommon.h>
+
+#include <fcntl.h>
+#include <linux/input-event-codes.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include <cstring>
+
+struct output_t {
+ struct wl_output *output;
+ int32_t width, height;
+ int transform;
+ int scale;
+ std::string make;
+ std::string model;
+};
+
+struct buffer_t {
+ void *data;
+ size_t size;
+};
+
+struct cursor_t {
+ bool visible;
+ struct wl_surface *surface = nullptr;
+ struct wl_buffer *buffer;
+ struct wl_cursor_image image;
+ struct buffer_t *file_buffer = nullptr;
+};
+
+struct data_offer_t {
+ std::unordered_set<std::string> types;
+ uint32_t source_actions;
+ uint32_t dnd_action;
+ struct wl_data_offer *id;
+ std::atomic<bool> in_use;
+ struct {
+ int x, y;
+ } dnd;
+};
+
+struct data_source_t {
+ struct wl_data_source *data_source;
+ /** Last device that was active. */
+ uint32_t source_serial;
+ char *buffer_out;
+};
+
+struct key_repeat_payload_t {
+ GHOST_SystemWayland *system;
+ GHOST_IWindow *window;
+ GHOST_TKey key;
+ GHOST_TEventKeyData key_data;
+};
+
+struct input_t {
+ GHOST_SystemWayland *system;
+
+ std::string name;
+ struct wl_seat *seat;
+ struct wl_pointer *pointer = nullptr;
+ struct wl_keyboard *keyboard = nullptr;
+
+ uint32_t pointer_serial;
+ int x, y;
+ GHOST_Buttons buttons;
+ struct cursor_t cursor;
+
+ struct zwp_relative_pointer_v1 *relative_pointer;
+ struct zwp_locked_pointer_v1 *locked_pointer;
+
+ struct xkb_context *xkb_context;
+ struct xkb_state *xkb_state;
+ struct {
+ /* Key repetition in character per second. */
+ int32_t rate;
+ /* Time (milliseconds) after which to start repeating keys. */
+ int32_t delay;
+ /* Timer for key repeats. */
+ GHOST_ITimerTask *timer = nullptr;
+ } key_repeat;
+
+ struct wl_surface *focus_pointer = nullptr;
+ struct wl_surface *focus_keyboard = nullptr;
+
+ struct wl_data_device *data_device = nullptr;
+ struct data_offer_t *data_offer_dnd; /* Drag & Drop. */
+ struct data_offer_t *data_offer_copy_paste; /* Copy & Paste. */
+
+ struct data_source_t *data_source;
+};
+
+struct display_t {
+ GHOST_SystemWayland *system;
+
+ struct wl_display *display;
+ struct wl_compositor *compositor = nullptr;
+ struct xdg_wm_base *xdg_shell = nullptr;
+ struct wl_shm *shm = nullptr;
+ std::vector<output_t *> outputs;
+ std::vector<input_t *> inputs;
+ struct wl_cursor_theme *cursor_theme = nullptr;
+ struct wl_data_device_manager *data_device_manager = nullptr;
+ struct zwp_relative_pointer_manager_v1 *relative_pointer_manager = nullptr;
+ struct zwp_pointer_constraints_v1 *pointer_constraints = nullptr;
+
+ std::vector<struct wl_surface *> os_surfaces;
+ std::vector<struct wl_egl_window *> os_egl_windows;
+};
+
+static void display_destroy(display_t *d)
+{
+ if (d->data_device_manager) {
+ wl_data_device_manager_destroy(d->data_device_manager);
+ }
+
+ for (output_t *output : d->outputs) {
+ wl_output_destroy(output->output);
+ delete output;
+ }
+
+ for (input_t *input : d->inputs) {
+ if (input->data_source) {
+ free(input->data_source->buffer_out);
+ if (input->data_source->data_source) {
+ wl_data_source_destroy(input->data_source->data_source);
+ }
+ delete input->data_source;
+ }
+ if (input->data_offer_copy_paste) {
+ wl_data_offer_destroy(input->data_offer_copy_paste->id);
+ delete input->data_offer_copy_paste;
+ }
+ if (input->data_device) {
+ wl_data_device_release(input->data_device);
+ }
+ if (input->pointer) {
+ if (input->cursor.file_buffer) {
+ munmap(input->cursor.file_buffer->data, input->cursor.file_buffer->size);
+ delete input->cursor.file_buffer;
+ }
+ if (input->cursor.surface) {
+ wl_surface_destroy(input->cursor.surface);
+ }
+ if (input->pointer) {
+ wl_pointer_destroy(input->pointer);
+ }
+ }
+ if (input->keyboard) {
+ if (input->key_repeat.timer) {
+ delete static_cast<key_repeat_payload_t *>(input->key_repeat.timer->getUserData());
+ input->system->removeTimer(input->key_repeat.timer);
+ input->key_repeat.timer = nullptr;
+ }
+ wl_keyboard_destroy(input->keyboard);
+ }
+ if (input->xkb_state) {
+ xkb_state_unref(input->xkb_state);
+ }
+ if (input->xkb_context) {
+ xkb_context_unref(input->xkb_context);
+ }
+ wl_seat_destroy(input->seat);
+ delete input;
+ }
+
+ if (d->cursor_theme) {
+ wl_cursor_theme_destroy(d->cursor_theme);
+ }
+
+ if (d->shm) {
+ wl_shm_destroy(d->shm);
+ }
+
+ if (d->relative_pointer_manager) {
+ zwp_relative_pointer_manager_v1_destroy(d->relative_pointer_manager);
+ }
+
+ if (d->pointer_constraints) {
+ zwp_pointer_constraints_v1_destroy(d->pointer_constraints);
+ }
+
+ for (wl_egl_window *os_egl_window : d->os_egl_windows) {
+ wl_egl_window_destroy(os_egl_window);
+ }
+
+ for (wl_surface *os_surface : d->os_surfaces) {
+ wl_surface_destroy(os_surface);
+ }
+
+ if (d->compositor) {
+ wl_compositor_destroy(d->compositor);
+ }
+
+ if (d->xdg_shell) {
+ xdg_wm_base_destroy(d->xdg_shell);
+ }
+
+ if (eglGetDisplay) {
+ ::eglTerminate(eglGetDisplay(EGLNativeDisplayType(d->display)));
+ }
+
+ if (d->display) {
+ wl_display_disconnect(d->display);
+ }
+
+ delete d;
+}
+
+static GHOST_TKey xkb_map_gkey(const xkb_keysym_t &sym)
+{
+
+ GHOST_TKey gkey;
+ if (sym >= XKB_KEY_0 && sym <= XKB_KEY_9) {
+ gkey = GHOST_TKey(sym);
+ }
+ else if (sym >= XKB_KEY_KP_0 && sym <= XKB_KEY_KP_9) {
+ gkey = GHOST_TKey(GHOST_kKeyNumpad0 + sym - XKB_KEY_KP_0);
+ }
+ else if (sym >= XKB_KEY_A && sym <= XKB_KEY_Z) {
+ gkey = GHOST_TKey(sym);
+ }
+ else if (sym >= XKB_KEY_a && sym <= XKB_KEY_z) {
+ gkey = GHOST_TKey(sym - XKB_KEY_a + XKB_KEY_A);
+ }
+ else if (sym >= XKB_KEY_F1 && sym <= XKB_KEY_F24) {
+ gkey = GHOST_TKey(GHOST_kKeyF1 + sym - XKB_KEY_F1);
+ }
+ else {
+
+#define GXMAP(k, x, y) \
+ case x: \
+ k = y; \
+ break
+
+ switch (sym) {
+ GXMAP(gkey, XKB_KEY_BackSpace, GHOST_kKeyBackSpace);
+ GXMAP(gkey, XKB_KEY_Tab, GHOST_kKeyTab);
+ GXMAP(gkey, XKB_KEY_Linefeed, GHOST_kKeyLinefeed);
+ GXMAP(gkey, XKB_KEY_Clear, GHOST_kKeyClear);
+ GXMAP(gkey, XKB_KEY_Return, GHOST_kKeyEnter);
+
+ GXMAP(gkey, XKB_KEY_Escape, GHOST_kKeyEsc);
+ GXMAP(gkey, XKB_KEY_space, GHOST_kKeySpace);
+ GXMAP(gkey, XKB_KEY_apostrophe, GHOST_kKeyQuote);
+ GXMAP(gkey, XKB_KEY_comma, GHOST_kKeyComma);
+ GXMAP(gkey, XKB_KEY_minus, GHOST_kKeyMinus);
+ GXMAP(gkey, XKB_KEY_plus, GHOST_kKeyPlus);
+ GXMAP(gkey, XKB_KEY_period, GHOST_kKeyPeriod);
+ GXMAP(gkey, XKB_KEY_slash, GHOST_kKeySlash);
+
+ GXMAP(gkey, XKB_KEY_semicolon, GHOST_kKeySemicolon);
+ GXMAP(gkey, XKB_KEY_equal, GHOST_kKeyEqual);
+
+ GXMAP(gkey, XKB_KEY_bracketleft, GHOST_kKeyLeftBracket);
+ GXMAP(gkey, XKB_KEY_bracketright, GHOST_kKeyRightBracket);
+ GXMAP(gkey, XKB_KEY_backslash, GHOST_kKeyBackslash);
+ GXMAP(gkey, XKB_KEY_grave, GHOST_kKeyAccentGrave);
+
+ GXMAP(gkey, XKB_KEY_Shift_L, GHOST_kKeyLeftShift);
+ GXMAP(gkey, XKB_KEY_Shift_R, GHOST_kKeyRightShift);
+ GXMAP(gkey, XKB_KEY_Control_L, GHOST_kKeyLeftControl);
+ GXMAP(gkey, XKB_KEY_Control_R, GHOST_kKeyRightControl);
+ GXMAP(gkey, XKB_KEY_Alt_L, GHOST_kKeyLeftAlt);
+ GXMAP(gkey, XKB_KEY_Alt_R, GHOST_kKeyRightAlt);
+ GXMAP(gkey, XKB_KEY_Super_L, GHOST_kKeyOS);
+ GXMAP(gkey, XKB_KEY_Super_R, GHOST_kKeyOS);
+ GXMAP(gkey, XKB_KEY_Menu, GHOST_kKeyApp);
+
+ GXMAP(gkey, XKB_KEY_Caps_Lock, GHOST_kKeyCapsLock);
+ GXMAP(gkey, XKB_KEY_Num_Lock, GHOST_kKeyNumLock);
+ GXMAP(gkey, XKB_KEY_Scroll_Lock, GHOST_kKeyScrollLock);
+
+ GXMAP(gkey, XKB_KEY_Left, GHOST_kKeyLeftArrow);
+ GXMAP(gkey, XKB_KEY_Right, GHOST_kKeyRightArrow);
+ GXMAP(gkey, XKB_KEY_Up, GHOST_kKeyUpArrow);
+ GXMAP(gkey, XKB_KEY_Down, GHOST_kKeyDownArrow);
+
+ GXMAP(gkey, XKB_KEY_Print, GHOST_kKeyPrintScreen);
+ GXMAP(gkey, XKB_KEY_Pause, GHOST_kKeyPause);
+
+ GXMAP(gkey, XKB_KEY_Insert, GHOST_kKeyInsert);
+ GXMAP(gkey, XKB_KEY_Delete, GHOST_kKeyDelete);
+ GXMAP(gkey, XKB_KEY_Home, GHOST_kKeyHome);
+ GXMAP(gkey, XKB_KEY_End, GHOST_kKeyEnd);
+ GXMAP(gkey, XKB_KEY_Page_Up, GHOST_kKeyUpPage);
+ GXMAP(gkey, XKB_KEY_Page_Down, GHOST_kKeyDownPage);
+
+ GXMAP(gkey, XKB_KEY_KP_Decimal, GHOST_kKeyNumpadPeriod);
+ GXMAP(gkey, XKB_KEY_KP_Enter, GHOST_kKeyNumpadEnter);
+ GXMAP(gkey, XKB_KEY_KP_Add, GHOST_kKeyNumpadPlus);
+ GXMAP(gkey, XKB_KEY_KP_Subtract, GHOST_kKeyNumpadMinus);
+ GXMAP(gkey, XKB_KEY_KP_Multiply, GHOST_kKeyNumpadAsterisk);
+ GXMAP(gkey, XKB_KEY_KP_Divide, GHOST_kKeyNumpadSlash);
+
+ GXMAP(gkey, XKB_KEY_XF86AudioPlay, GHOST_kKeyMediaPlay);
+ GXMAP(gkey, XKB_KEY_XF86AudioStop, GHOST_kKeyMediaStop);
+ GXMAP(gkey, XKB_KEY_XF86AudioPrev, GHOST_kKeyMediaFirst);
+ GXMAP(gkey, XKB_KEY_XF86AudioNext, GHOST_kKeyMediaLast);
+ default:
+ GHOST_PRINT("unhandled key: " << std::hex << std::showbase << sym << std::dec << " ("
+ << sym << ")" << std::endl);
+ gkey = GHOST_kKeyUnknown;
+ }
+#undef GXMAP
+ }
+
+ return gkey;
+}
+
+static const int default_cursor_size = 24;
+
+static const std::unordered_map<GHOST_TStandardCursor, std::string> cursors = {
+ {GHOST_kStandardCursorDefault, "left_ptr"},
+ {GHOST_kStandardCursorRightArrow, "right_ptr"},
+ {GHOST_kStandardCursorLeftArrow, "left_ptr"},
+ {GHOST_kStandardCursorInfo, ""},
+ {GHOST_kStandardCursorDestroy, ""},
+ {GHOST_kStandardCursorHelp, "question_arrow"},
+ {GHOST_kStandardCursorWait, "watch"},
+ {GHOST_kStandardCursorText, "xterm"},
+ {GHOST_kStandardCursorCrosshair, "crosshair"},
+ {GHOST_kStandardCursorCrosshairA, ""},
+ {GHOST_kStandardCursorCrosshairB, ""},
+ {GHOST_kStandardCursorCrosshairC, ""},
+ {GHOST_kStandardCursorPencil, ""},
+ {GHOST_kStandardCursorUpArrow, "sb_up_arrow"},
+ {GHOST_kStandardCursorDownArrow, "sb_down_arrow"},
+ {GHOST_kStandardCursorVerticalSplit, ""},
+ {GHOST_kStandardCursorHorizontalSplit, ""},
+ {GHOST_kStandardCursorEraser, ""},
+ {GHOST_kStandardCursorKnife, ""},
+ {GHOST_kStandardCursorEyedropper, ""},
+ {GHOST_kStandardCursorZoomIn, ""},
+ {GHOST_kStandardCursorZoomOut, ""},
+ {GHOST_kStandardCursorMove, "move"},
+ {GHOST_kStandardCursorNSEWScroll, ""},
+ {GHOST_kStandardCursorNSScroll, ""},
+ {GHOST_kStandardCursorEWScroll, ""},
+ {GHOST_kStandardCursorStop, ""},
+ {GHOST_kStandardCursorUpDown, "sb_v_double_arrow"},
+ {GHOST_kStandardCursorLeftRight, "sb_h_double_arrow"},
+ {GHOST_kStandardCursorTopSide, "top_side"},
+ {GHOST_kStandardCursorBottomSide, "bottom_side"},
+ {GHOST_kStandardCursorLeftSide, "left_side"},
+ {GHOST_kStandardCursorRightSide, "right_side"},
+ {GHOST_kStandardCursorTopLeftCorner, "top_left_corner"},
+ {GHOST_kStandardCursorTopRightCorner, "top_right_corner"},
+ {GHOST_kStandardCursorBottomRightCorner, "bottom_right_corner"},
+ {GHOST_kStandardCursorBottomLeftCorner, "bottom_left_corner"},
+ {GHOST_kStandardCursorCopy, "copy"},
+};
+
+static constexpr const char *mime_text_plain = "text/plain";
+static constexpr const char *mime_text_utf8 = "text/plain;charset=utf-8";
+static constexpr const char *mime_text_uri = "text/uri-list";
+
+static const std::unordered_map<std::string, GHOST_TDragnDropTypes> mime_dnd = {
+ {mime_text_plain, GHOST_kDragnDropTypeString},
+ {mime_text_utf8, GHOST_kDragnDropTypeString},
+ {mime_text_uri, GHOST_kDragnDropTypeFilenames},
+};
+
+static const std::vector<std::string> mime_preference_order = {
+ mime_text_uri,
+ mime_text_utf8,
+ mime_text_plain,
+};
+
+static const std::vector<std::string> mime_send = {
+ "UTF8_STRING",
+ "COMPOUND_TEXT",
+ "TEXT",
+ "STRING",
+ "text/plain;charset=utf-8",
+ "text/plain",
+};
+
+/* -------------------------------------------------------------------- */
+/** \name Interface Callbacks
+ *
+ * These callbacks are registered for Wayland interfaces and called when
+ * an event is received from the compositor.
+ * \{ */
+
+static void relative_pointer_relative_motion(
+ void *data,
+ struct zwp_relative_pointer_v1 * /*zwp_relative_pointer_v1*/,
+ uint32_t /*utime_hi*/,
+ uint32_t /*utime_lo*/,
+ wl_fixed_t dx,
+ wl_fixed_t dy,
+ wl_fixed_t /*dx_unaccel*/,
+ wl_fixed_t /*dy_unaccel*/)
+{
+ input_t *input = static_cast<input_t *>(data);
+
+ input->x += wl_fixed_to_int(dx);
+ input->y += wl_fixed_to_int(dy);
+
+ GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
+ wl_surface_get_user_data(input->focus_pointer));
+
+ input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(),
+ GHOST_kEventCursorMove,
+ win,
+ input->x,
+ input->y,
+ GHOST_TABLET_DATA_NONE));
+}
+
+static const zwp_relative_pointer_v1_listener relative_pointer_listener = {
+ relative_pointer_relative_motion,
+};
+
+static void dnd_events(const input_t *const input, const GHOST_TEventType event)
+{
+ const GHOST_TUns64 time = input->system->getMilliSeconds();
+ GHOST_IWindow *const window = static_cast<GHOST_WindowWayland *>(
+ wl_surface_get_user_data(input->focus_pointer));
+ for (const std::string &type : mime_preference_order) {
+ input->system->pushEvent(new GHOST_EventDragnDrop(time,
+ event,
+ mime_dnd.at(type),
+ window,
+ input->data_offer_dnd->dnd.x,
+ input->data_offer_dnd->dnd.y,
+ nullptr));
+ }
+}
+
+static std::string read_pipe(data_offer_t *data_offer, const std::string mime_receive)
+{
+ int pipefd[2];
+ pipe(pipefd);
+ wl_data_offer_receive(data_offer->id, mime_receive.c_str(), pipefd[1]);
+ close(pipefd[1]);
+
+ std::string data;
+ ssize_t len;
+ char buffer[4096];
+ while ((len = read(pipefd[0], buffer, sizeof(buffer))) > 0) {
+ data.insert(data.end(), buffer, buffer + len);
+ }
+ close(pipefd[0]);
+ data_offer->in_use.store(false);
+
+ return data;
+}
+
+/**
+ * A target accepts an offered mime type.
+ *
+ * Sent when a target accepts pointer_focus or motion events. If
+ * a target does not accept any of the offered types, type is NULL.
+ */
+static void data_source_target(void * /*data*/,
+ struct wl_data_source * /*wl_data_source*/,
+ const char * /*mime_type*/)
+{
+ /* pass */
+}
+
+static void data_source_send(void *data,
+ struct wl_data_source * /*wl_data_source*/,
+ const char * /*mime_type*/,
+ int32_t fd)
+{
+ const char *const buffer = static_cast<char *>(data);
+ write(fd, buffer, strlen(buffer) + 1);
+ close(fd);
+}
+
+static void data_source_cancelled(void * /*data*/, struct wl_data_source *wl_data_source)
+{
+ wl_data_source_destroy(wl_data_source);
+}
+
+/**
+ * The drag-and-drop operation physically finished.
+ *
+ * The user performed the drop action. This event does not
+ * indicate acceptance, #wl_data_source.cancelled may still be
+ * emitted afterwards if the drop destination does not accept any mime type.
+ */
+static void data_source_dnd_drop_performed(void * /*data*/,
+ struct wl_data_source * /*wl_data_source*/)
+{
+ /* pass */
+}
+
+/**
+ * The drag-and-drop operation concluded.
+ *
+ * The drop destination finished interoperating with this data
+ * source, so the client is now free to destroy this data source
+ * and free all associated data.
+ */
+static void data_source_dnd_finished(void * /*data*/, struct wl_data_source * /*wl_data_source*/)
+{
+ /* pass */
+}
+
+/**
+ * Notify the selected action.
+ *
+ * This event indicates the action selected by the compositor
+ * after matching the source/destination side actions. Only one
+ * action (or none) will be offered here.
+ */
+static void data_source_action(void * /*data*/,
+ struct wl_data_source * /*wl_data_source*/,
+ uint32_t /*dnd_action*/)
+{
+ /* pass */
+}
+
+static const struct wl_data_source_listener data_source_listener = {
+ data_source_target,
+ data_source_send,
+ data_source_cancelled,
+ data_source_dnd_drop_performed,
+ data_source_dnd_finished,
+ data_source_action,
+};
+
+static void data_offer_offer(void *data,
+ struct wl_data_offer * /*wl_data_offer*/,
+ const char *mime_type)
+{
+ static_cast<data_offer_t *>(data)->types.insert(mime_type);
+}
+
+static void data_offer_source_actions(void *data,
+ struct wl_data_offer * /*wl_data_offer*/,
+ uint32_t source_actions)
+{
+ static_cast<data_offer_t *>(data)->source_actions = source_actions;
+}
+
+static void data_offer_action(void *data,
+ struct wl_data_offer * /*wl_data_offer*/,
+ uint32_t dnd_action)
+{
+ static_cast<data_offer_t *>(data)->dnd_action = dnd_action;
+}
+
+static const struct wl_data_offer_listener data_offer_listener = {
+ data_offer_offer,
+ data_offer_source_actions,
+ data_offer_action,
+};
+
+static void data_device_data_offer(void * /*data*/,
+ struct wl_data_device * /*wl_data_device*/,
+ struct wl_data_offer *id)
+{
+ data_offer_t *data_offer = new data_offer_t;
+ data_offer->id = id;
+ wl_data_offer_add_listener(id, &data_offer_listener, data_offer);
+}
+
+static void data_device_enter(void *data,
+ struct wl_data_device * /*wl_data_device*/,
+ uint32_t serial,
+ struct wl_surface * /*surface*/,
+ wl_fixed_t x,
+ wl_fixed_t y,
+ struct wl_data_offer *id)
+{
+ input_t *input = static_cast<input_t *>(data);
+ input->data_offer_dnd = static_cast<data_offer_t *>(wl_data_offer_get_user_data(id));
+ data_offer_t *data_offer = input->data_offer_dnd;
+
+ data_offer->in_use.store(true);
+ data_offer->dnd.x = wl_fixed_to_int(x);
+ data_offer->dnd.y = wl_fixed_to_int(y);
+
+ wl_data_offer_set_actions(id,
+ WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY |
+ WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE,
+ WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY);
+
+ for (const std::string &type : mime_preference_order) {
+ wl_data_offer_accept(id, serial, type.c_str());
+ }
+
+ dnd_events(input, GHOST_kEventDraggingEntered);
+}
+
+static void data_device_leave(void *data, struct wl_data_device * /*wl_data_device*/)
+{
+ input_t *input = static_cast<input_t *>(data);
+
+ dnd_events(input, GHOST_kEventDraggingExited);
+
+ if (input->data_offer_dnd && !input->data_offer_dnd->in_use.load()) {
+ wl_data_offer_destroy(input->data_offer_dnd->id);
+ delete input->data_offer_dnd;
+ input->data_offer_dnd = nullptr;
+ }
+}
+
+static void data_device_motion(void *data,
+ struct wl_data_device * /*wl_data_device*/,
+ uint32_t /*time*/,
+ wl_fixed_t x,
+ wl_fixed_t y)
+{
+ input_t *input = static_cast<input_t *>(data);
+ input->data_offer_dnd->dnd.x = wl_fixed_to_int(x);
+ input->data_offer_dnd->dnd.y = wl_fixed_to_int(y);
+ dnd_events(input, GHOST_kEventDraggingUpdated);
+}
+
+static void data_device_drop(void *data, struct wl_data_device * /*wl_data_device*/)
+{
+ input_t *input = static_cast<input_t *>(data);
+ data_offer_t *data_offer = input->data_offer_dnd;
+
+ const std::string mime_receive = *std::find_first_of(mime_preference_order.begin(),
+ mime_preference_order.end(),
+ data_offer->types.begin(),
+ data_offer->types.end());
+
+ auto read_uris = [](input_t *const input,
+ data_offer_t *data_offer,
+ const std::string mime_receive) {
+ const int x = data_offer->dnd.x;
+ const int y = data_offer->dnd.y;
+
+ const std::string data = read_pipe(data_offer, mime_receive);
+
+ wl_data_offer_finish(data_offer->id);
+ wl_data_offer_destroy(data_offer->id);
+
+ delete data_offer;
+ data_offer = nullptr;
+
+ GHOST_SystemWayland *const system = input->system;
+
+ if (mime_receive == mime_text_uri) {
+ static constexpr const char *file_proto = "file://";
+ static constexpr const char *crlf = "\r\n";
+
+ std::vector<std::string> uris;
+
+ size_t pos = 0;
+ while (true) {
+ pos = data.find(file_proto, pos);
+ const size_t start = pos + sizeof(file_proto) - 1;
+ pos = data.find(crlf, pos);
+ const size_t end = pos;
+
+ if (pos == std::string::npos) {
+ break;
+ }
+ uris.push_back(data.substr(start, end - start));
+ }
+
+ GHOST_TStringArray *flist = static_cast<GHOST_TStringArray *>(
+ malloc(sizeof(GHOST_TStringArray)));
+ flist->count = int(uris.size());
+ flist->strings = static_cast<GHOST_TUns8 **>(malloc(uris.size() * sizeof(GHOST_TUns8 *)));
+ for (size_t i = 0; i < uris.size(); i++) {
+ flist->strings[i] = static_cast<GHOST_TUns8 *>(
+ malloc((uris[i].size() + 1) * sizeof(GHOST_TUns8)));
+ memcpy(flist->strings[i], uris[i].data(), uris[i].size() + 1);
+ }
+ GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
+ wl_surface_get_user_data(input->focus_pointer));
+ system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(),
+ GHOST_kEventDraggingDropDone,
+ GHOST_kDragnDropTypeFilenames,
+ win,
+ x,
+ y,
+ flist));
+ }
+ else if (mime_receive == mime_text_plain || mime_receive == mime_text_utf8) {
+ /* TODO: enable use of internal functions 'txt_insert_buf' and
+ * 'text_update_edited' to behave like dropped text was pasted. */
+ }
+ wl_display_roundtrip(system->display());
+ };
+
+ std::thread read_thread(read_uris, input, data_offer, mime_receive);
+ read_thread.detach();
+}
+
+static void data_device_selection(void *data,
+ struct wl_data_device * /*wl_data_device*/,
+ struct wl_data_offer *id)
+{
+ input_t *input = static_cast<input_t *>(data);
+ data_offer_t *data_offer = input->data_offer_copy_paste;
+
+ /* Delete old data offer. */
+ if (data_offer != nullptr) {
+ wl_data_offer_destroy(data_offer->id);
+ delete data_offer;
+ data_offer = nullptr;
+ }
+
+ if (id == nullptr) {
+ return;
+ }
+
+ /* Get new data offer. */
+ data_offer = static_cast<data_offer_t *>(wl_data_offer_get_user_data(id));
+ input->data_offer_copy_paste = data_offer;
+
+ std::string mime_receive;
+ for (const std::string &type : {mime_text_utf8, mime_text_plain}) {
+ if (data_offer->types.count(type)) {
+ mime_receive = type;
+ break;
+ }
+ }
+
+ auto read_selection = [](GHOST_SystemWayland *const system,
+ data_offer_t *data_offer,
+ const std::string mime_receive) {
+ const std::string data = read_pipe(data_offer, mime_receive);
+ system->setSelection(data);
+ };
+
+ std::thread read_thread(read_selection, input->system, data_offer, mime_receive);
+ read_thread.detach();
+}
+
+static const struct wl_data_device_listener data_device_listener = {
+ data_device_data_offer,
+ data_device_enter,
+ data_device_leave,
+ data_device_motion,
+ data_device_drop,
+ data_device_selection,
+};
+
+static void cursor_buffer_release(void *data, struct wl_buffer *wl_buffer)
+{
+ cursor_t *cursor = static_cast<cursor_t *>(data);
+
+ wl_buffer_destroy(wl_buffer);
+ cursor->buffer = nullptr;
+}
+
+const struct wl_buffer_listener cursor_buffer_listener = {
+ cursor_buffer_release,
+};
+
+static void pointer_enter(void *data,
+ struct wl_pointer * /*wl_pointer*/,
+ uint32_t serial,
+ struct wl_surface *surface,
+ wl_fixed_t surface_x,
+ wl_fixed_t surface_y)
+{
+ if (!surface) {
+ return;
+ }
+ input_t *input = static_cast<input_t *>(data);
+ input->pointer_serial = serial;
+ input->x = wl_fixed_to_int(surface_x);
+ input->y = wl_fixed_to_int(surface_y);
+ input->focus_pointer = surface;
+
+ input->system->pushEvent(
+ new GHOST_EventCursor(input->system->getMilliSeconds(),
+ GHOST_kEventCursorMove,
+ static_cast<GHOST_WindowWayland *>(wl_surface_get_user_data(surface)),
+ input->x,
+ input->y,
+ GHOST_TABLET_DATA_NONE));
+}
+
+static void pointer_leave(void *data,
+ struct wl_pointer * /*wl_pointer*/,
+ uint32_t /*serial*/,
+ struct wl_surface *surface)
+{
+ if (surface != nullptr) {
+ static_cast<input_t *>(data)->focus_pointer = nullptr;
+ }
+}
+
+static void pointer_motion(void *data,
+ struct wl_pointer * /*wl_pointer*/,
+ uint32_t /*time*/,
+ wl_fixed_t surface_x,
+ wl_fixed_t surface_y)
+{
+ input_t *input = static_cast<input_t *>(data);
+
+ GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
+ wl_surface_get_user_data(input->focus_pointer));
+
+ if (!win) {
+ return;
+ }
+
+ input->x = wl_fixed_to_int(surface_x);
+ input->y = wl_fixed_to_int(surface_y);
+
+ input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(),
+ GHOST_kEventCursorMove,
+ win,
+ wl_fixed_to_int(surface_x),
+ wl_fixed_to_int(surface_y),
+ GHOST_TABLET_DATA_NONE));
+}
+
+static void pointer_button(void *data,
+ struct wl_pointer * /*wl_pointer*/,
+ uint32_t serial,
+ uint32_t /*time*/,
+ uint32_t button,
+ uint32_t state)
+{
+ GHOST_TEventType etype = GHOST_kEventUnknown;
+ switch (state) {
+ case WL_POINTER_BUTTON_STATE_RELEASED:
+ etype = GHOST_kEventButtonUp;
+ break;
+ case WL_POINTER_BUTTON_STATE_PRESSED:
+ etype = GHOST_kEventButtonDown;
+ break;
+ }
+
+ GHOST_TButtonMask ebutton = GHOST_kButtonMaskLeft;
+ switch (button) {
+ case BTN_LEFT:
+ ebutton = GHOST_kButtonMaskLeft;
+ break;
+ case BTN_MIDDLE:
+ ebutton = GHOST_kButtonMaskMiddle;
+ break;
+ case BTN_RIGHT:
+ ebutton = GHOST_kButtonMaskRight;
+ break;
+ }
+
+ input_t *input = static_cast<input_t *>(data);
+ GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
+ wl_surface_get_user_data(input->focus_pointer));
+ input->data_source->source_serial = serial;
+ input->buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED);
+ input->system->pushEvent(new GHOST_EventButton(
+ input->system->getMilliSeconds(), etype, win, ebutton, GHOST_TABLET_DATA_NONE));
+}
+
+static void pointer_axis(void *data,
+ struct wl_pointer * /*wl_pointer*/,
+ uint32_t /*time*/,
+ uint32_t axis,
+ wl_fixed_t value)
+{
+ if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) {
+ return;
+ }
+ input_t *input = static_cast<input_t *>(data);
+ GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
+ wl_surface_get_user_data(input->focus_pointer));
+ input->system->pushEvent(
+ new GHOST_EventWheel(input->system->getMilliSeconds(), win, std::signbit(value) ? +1 : -1));
+}
+
+static const struct wl_pointer_listener pointer_listener = {
+ pointer_enter,
+ pointer_leave,
+ pointer_motion,
+ pointer_button,
+ pointer_axis,
+};
+
+static void keyboard_keymap(
+ void *data, struct wl_keyboard * /*wl_keyboard*/, uint32_t format, int32_t fd, uint32_t size)
+{
+ input_t *input = static_cast<input_t *>(data);
+
+ if ((!data) || (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)) {
+ close(fd);
+ return;
+ }
+
+ char *map_str = static_cast<char *>(mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0));
+ if (map_str == MAP_FAILED) {
+ close(fd);
+ throw std::runtime_error("keymap mmap failed: " + std::string(std::strerror(errno)));
+ }
+
+ struct xkb_keymap *keymap = xkb_keymap_new_from_string(
+ input->xkb_context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
+ munmap(map_str, size);
+ close(fd);
+
+ if (!keymap) {
+ return;
+ }
+
+ input->xkb_state = xkb_state_new(keymap);
+
+ xkb_keymap_unref(keymap);
+}
+
+/**
+ * Enter event.
+ *
+ * Notification that this seat's keyboard focus is on a certain
+ * surface.
+ */
+static void keyboard_enter(void *data,
+ struct wl_keyboard * /*wl_keyboard*/,
+ uint32_t /*serial*/,
+ struct wl_surface *surface,
+ struct wl_array * /*keys*/)
+{
+ if (surface != nullptr) {
+ static_cast<input_t *>(data)->focus_keyboard = surface;
+ }
+}
+
+/**
+ * Leave event.
+ *
+ * Notification that this seat's keyboard focus is no longer on a
+ * certain surface.
+ */
+static void keyboard_leave(void *data,
+ struct wl_keyboard * /*wl_keyboard*/,
+ uint32_t /*serial*/,
+ struct wl_surface *surface)
+{
+ if (surface != nullptr) {
+ static_cast<input_t *>(data)->focus_keyboard = nullptr;
+ }
+}
+
+/**
+ * A version of #xkb_state_key_get_one_sym which returns the key without any modifiers pressed.
+ * Needed because #GHOST_TKey uses these values as key-codes.
+ */
+static xkb_keysym_t xkb_state_key_get_one_sym_without_modifiers(struct xkb_state *xkb_state,
+ xkb_keycode_t key)
+{
+ /* Use an empty keyboard state to access key symbol without modifiers. */
+ xkb_state_get_keymap(xkb_state);
+ struct xkb_keymap *keymap = xkb_state_get_keymap(xkb_state);
+ struct xkb_state *xkb_state_empty = xkb_state_new(keymap);
+
+ /* Enable number-lock. */
+ {
+ const xkb_mod_index_t mod2 = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_NUM);
+ const xkb_mod_index_t num = xkb_keymap_mod_get_index(keymap, "NumLock");
+ if (num != XKB_MOD_INVALID && mod2 != XKB_MOD_INVALID) {
+ xkb_state_update_mask(xkb_state_empty, (1 << mod2), 0, (1 << num), 0, 0, 0);
+ }
+ }
+
+ const xkb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state_empty, key);
+ xkb_state_unref(xkb_state_empty);
+ return sym;
+}
+
+static void keyboard_key(void *data,
+ struct wl_keyboard * /*wl_keyboard*/,
+ uint32_t serial,
+ uint32_t /*time*/,
+ uint32_t key,
+ uint32_t state)
+{
+ input_t *input = static_cast<input_t *>(data);
+
+ GHOST_TEventType etype = GHOST_kEventUnknown;
+ switch (state) {
+ case WL_KEYBOARD_KEY_STATE_RELEASED:
+ etype = GHOST_kEventKeyUp;
+ break;
+ case WL_KEYBOARD_KEY_STATE_PRESSED:
+ etype = GHOST_kEventKeyDown;
+ break;
+ }
+
+ const xkb_keysym_t sym = xkb_state_key_get_one_sym_without_modifiers(input->xkb_state, key + 8);
+
+ if (sym == XKB_KEY_NoSymbol) {
+ return;
+ }
+ const GHOST_TKey gkey = xkb_map_gkey(sym);
+
+ /* Delete previous timer. */
+ if (xkb_keymap_key_repeats(xkb_state_get_keymap(input->xkb_state), key + 8) &&
+ input->key_repeat.timer) {
+ delete static_cast<key_repeat_payload_t *>(input->key_repeat.timer->getUserData());
+ input->system->removeTimer(input->key_repeat.timer);
+ input->key_repeat.timer = nullptr;
+ }
+
+ GHOST_TEventKeyData key_data;
+
+ if (etype == GHOST_kEventKeyDown) {
+ xkb_state_key_get_utf8(
+ input->xkb_state, key + 8, key_data.utf8_buf, sizeof(GHOST_TEventKeyData::utf8_buf));
+ }
+ else {
+ key_data.utf8_buf[0] = '\0';
+ }
+
+ input->data_source->source_serial = serial;
+
+ GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
+ wl_surface_get_user_data(input->focus_keyboard));
+ input->system->pushEvent(new GHOST_EventKey(
+ input->system->getMilliSeconds(), etype, win, gkey, '\0', key_data.utf8_buf, false));
+
+ /* Start timer for repeating key, if applicable. */
+ if (input->key_repeat.rate > 0 &&
+ xkb_keymap_key_repeats(xkb_state_get_keymap(input->xkb_state), key + 8) &&
+ etype == GHOST_kEventKeyDown) {
+
+ key_repeat_payload_t *payload = new key_repeat_payload_t({
+ .system = input->system,
+ .window = win,
+ .key = gkey,
+ .key_data = key_data,
+ });
+
+ auto cb = [](GHOST_ITimerTask *task, GHOST_TUns64 /*time*/) {
+ struct key_repeat_payload_t *payload = static_cast<key_repeat_payload_t *>(
+ task->getUserData());
+ payload->system->pushEvent(new GHOST_EventKey(payload->system->getMilliSeconds(),
+ GHOST_kEventKeyDown,
+ payload->window,
+ payload->key,
+ '\0',
+ payload->key_data.utf8_buf,
+ true));
+ };
+ input->key_repeat.timer = input->system->installTimer(
+ input->key_repeat.delay, 1000 / input->key_repeat.rate, cb, payload);
+ }
+}
+
+static void keyboard_modifiers(void *data,
+ struct wl_keyboard * /*wl_keyboard*/,
+ uint32_t /*serial*/,
+ uint32_t mods_depressed,
+ uint32_t mods_latched,
+ uint32_t mods_locked,
+ uint32_t group)
+{
+ xkb_state_update_mask(static_cast<input_t *>(data)->xkb_state,
+ mods_depressed,
+ mods_latched,
+ mods_locked,
+ 0,
+ 0,
+ group);
+}
+
+static void keyboard_repeat_info(void *data,
+ struct wl_keyboard * /*wl_keyboard*/,
+ int32_t rate,
+ int32_t delay)
+{
+ input_t *input = static_cast<input_t *>(data);
+
+ input->key_repeat.rate = rate;
+ input->key_repeat.delay = delay;
+}
+
+static const struct wl_keyboard_listener keyboard_listener = {
+ keyboard_keymap,
+ keyboard_enter,
+ keyboard_leave,
+ keyboard_key,
+ keyboard_modifiers,
+ keyboard_repeat_info,
+};
+
+static void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities)
+{
+ input_t *input = static_cast<input_t *>(data);
+ input->pointer = nullptr;
+ input->keyboard = nullptr;
+
+ if (capabilities & WL_SEAT_CAPABILITY_POINTER) {
+ input->pointer = wl_seat_get_pointer(wl_seat);
+ input->cursor.surface = wl_compositor_create_surface(input->system->compositor());
+ input->cursor.visible = true;
+ input->cursor.buffer = nullptr;
+ input->cursor.file_buffer = new buffer_t;
+ wl_pointer_add_listener(input->pointer, &pointer_listener, data);
+ }
+
+ if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
+ input->keyboard = wl_seat_get_keyboard(wl_seat);
+ wl_keyboard_add_listener(input->keyboard, &keyboard_listener, data);
+ }
+}
+
+static void seat_name(void *data, struct wl_seat * /*wl_seat*/, const char *name)
+{
+ static_cast<input_t *>(data)->name = std::string(name);
+}
+
+static const struct wl_seat_listener seat_listener = {
+ seat_capabilities,
+ seat_name,
+};
+
+static void output_geometry(void *data,
+ struct wl_output * /*wl_output*/,
+ int32_t /*x*/,
+ int32_t /*y*/,
+ int32_t /*physical_width*/,
+ int32_t /*physical_height*/,
+ int32_t /*subpixel*/,
+ const char *make,
+ const char *model,
+ int32_t transform)
+{
+ output_t *output = static_cast<output_t *>(data);
+ output->transform = transform;
+ output->make = std::string(make);
+ output->model = std::string(model);
+}
+
+static void output_mode(void *data,
+ struct wl_output * /*wl_output*/,
+ uint32_t /*flags*/,
+ int32_t width,
+ int32_t height,
+ int32_t /*refresh*/)
+{
+ output_t *output = static_cast<output_t *>(data);
+ output->width = width;
+ output->height = height;
+}
+
+/**
+ * Sent all information about output.
+ *
+ * This event is sent after all other properties have been sent
+ * after binding to the output object and after any other property
+ * changes done after that. This allows changes to the output
+ * properties to be seen as atomic, even if they happen via multiple events.
+ */
+static void output_done(void * /*data*/, struct wl_output * /*wl_output*/)
+{
+}
+
+static void output_scale(void *data, struct wl_output * /*wl_output*/, int32_t factor)
+{
+ static_cast<output_t *>(data)->scale = factor;
+}
+
+static const struct wl_output_listener output_listener = {
+ output_geometry,
+ output_mode,
+ output_done,
+ output_scale,
+};
+
+static void shell_ping(void * /*data*/, struct xdg_wm_base *xdg_wm_base, uint32_t serial)
+{
+ xdg_wm_base_pong(xdg_wm_base, serial);
+}
+
+static const struct xdg_wm_base_listener shell_listener = {
+ shell_ping,
+};
+
+static void global_add(void *data,
+ struct wl_registry *wl_registry,
+ uint32_t name,
+ const char *interface,
+ uint32_t /*version*/)
+{
+ struct display_t *display = static_cast<struct display_t *>(data);
+ if (!strcmp(interface, wl_compositor_interface.name)) {
+ display->compositor = static_cast<wl_compositor *>(
+ wl_registry_bind(wl_registry, name, &wl_compositor_interface, 1));
+ }
+ else if (!strcmp(interface, xdg_wm_base_interface.name)) {
+ display->xdg_shell = static_cast<xdg_wm_base *>(
+ wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1));
+ xdg_wm_base_add_listener(display->xdg_shell, &shell_listener, nullptr);
+ }
+ else if (!strcmp(interface, wl_output_interface.name)) {
+ output_t *output = new output_t;
+ output->scale = 1;
+ output->output = static_cast<wl_output *>(
+ wl_registry_bind(wl_registry, name, &wl_output_interface, 2));
+ display->outputs.push_back(output);
+ wl_output_add_listener(output->output, &output_listener, output);
+ }
+ else if (!strcmp(interface, wl_seat_interface.name)) {
+ input_t *input = new input_t;
+ input->system = display->system;
+ input->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
+ input->xkb_state = nullptr;
+ input->data_offer_dnd = nullptr;
+ input->data_offer_copy_paste = nullptr;
+ input->data_source = new data_source_t;
+ input->data_source->data_source = nullptr;
+ input->data_source->buffer_out = nullptr;
+ input->relative_pointer = nullptr;
+ input->locked_pointer = nullptr;
+ input->seat = static_cast<wl_seat *>(
+ wl_registry_bind(wl_registry, name, &wl_seat_interface, 4));
+ display->inputs.push_back(input);
+ wl_seat_add_listener(input->seat, &seat_listener, input);
+ }
+ else if (!strcmp(interface, wl_shm_interface.name)) {
+ display->shm = static_cast<wl_shm *>(
+ wl_registry_bind(wl_registry, name, &wl_shm_interface, 1));
+ }
+ else if (!strcmp(interface, wl_data_device_manager_interface.name)) {
+ display->data_device_manager = static_cast<wl_data_device_manager *>(
+ wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, 1));
+ }
+ else if (!strcmp(interface, zwp_relative_pointer_manager_v1_interface.name)) {
+ display->relative_pointer_manager = static_cast<zwp_relative_pointer_manager_v1 *>(
+ wl_registry_bind(wl_registry, name, &zwp_relative_pointer_manager_v1_interface, 1));
+ }
+ else if (!strcmp(interface, zwp_pointer_constraints_v1_interface.name)) {
+ display->pointer_constraints = static_cast<zwp_pointer_constraints_v1 *>(
+ wl_registry_bind(wl_registry, name, &zwp_pointer_constraints_v1_interface, 1));
+ }
+}
+
+/**
+ * Announce removal of global object.
+ *
+ * Notify the client of removed global objects.
+ *
+ * This event notifies the client that the global identified by
+ * name is no longer available. If the client bound to the global
+ * using the bind request, the client should now destroy that object.
+ */
+static void global_remove(void * /*data*/, struct wl_registry * /*wl_registry*/, uint32_t /*name*/)
+{
+}
+
+static const struct wl_registry_listener registry_listener = {
+ global_add,
+ global_remove,
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Ghost Implementation
+ *
+ * Wayland specific implementation of the GHOST_System interface.
+ * \{ */
+
+GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new display_t)
+{
+ d->system = this;
+ /* Connect to the Wayland server. */
+ d->display = wl_display_connect(nullptr);
+ if (!d->display) {
+ display_destroy(d);
+ throw std::runtime_error("Wayland: unable to connect to display!");
+ }
+
+ /* Register interfaces. */
+ struct wl_registry *registry = wl_display_get_registry(d->display);
+ wl_registry_add_listener(registry, &registry_listener, d);
+ /* Call callback for registry listener. */
+ wl_display_roundtrip(d->display);
+ /* Call callbacks for registered listeners. */
+ wl_display_roundtrip(d->display);
+ wl_registry_destroy(registry);
+
+ if (!d->xdg_shell) {
+ display_destroy(d);
+ throw std::runtime_error("Wayland: unable to access xdg_shell!");
+ }
+
+ /* Register data device per seat for IPC between Wayland clients. */
+ if (d->data_device_manager) {
+ for (input_t *input : d->inputs) {
+ input->data_device = wl_data_device_manager_get_data_device(d->data_device_manager,
+ input->seat);
+ wl_data_device_add_listener(input->data_device, &data_device_listener, input);
+ }
+ }
+
+ const char *theme = std::getenv("XCURSOR_THEME");
+ const char *size = std::getenv("XCURSOR_SIZE");
+ const int sizei = size ? std::stoi(size) : default_cursor_size;
+
+ d->cursor_theme = wl_cursor_theme_load(theme, sizei, d->shm);
+ if (!d->cursor_theme) {
+ display_destroy(d);
+ throw std::runtime_error("Wayland: unable to access cursor themes!");
+ }
+}
+
+GHOST_SystemWayland::~GHOST_SystemWayland()
+{
+ display_destroy(d);
+}
+
+bool GHOST_SystemWayland::processEvents(bool waitForEvent)
+{
+ const bool fired = getTimerManager()->fireTimers(getMilliSeconds());
+
+ if (waitForEvent) {
+ wl_display_dispatch(d->display);
+ }
+ else {
+ wl_display_roundtrip(d->display);
+ }
+
+ return fired || (getEventManager()->getNumEvents() > 0);
+}
+
+int GHOST_SystemWayland::toggleConsole(int /*action*/)
+{
+ return 0;
+}
+
+GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) const
+{
+ if (!d->inputs.empty()) {
+ static const xkb_state_component mods_all = xkb_state_component(
+ XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_LOCKED |
+ XKB_STATE_MODS_EFFECTIVE);
+
+ keys.set(GHOST_kModifierKeyLeftShift,
+ xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_SHIFT, mods_all) ==
+ 1);
+ keys.set(GHOST_kModifierKeyRightShift,
+ xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_SHIFT, mods_all) ==
+ 1);
+ keys.set(GHOST_kModifierKeyLeftAlt,
+ xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "LAlt", mods_all) == 1);
+ keys.set(GHOST_kModifierKeyRightAlt,
+ xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "RAlt", mods_all) == 1);
+ keys.set(GHOST_kModifierKeyLeftControl,
+ xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "LControl", mods_all) == 1);
+ keys.set(GHOST_kModifierKeyRightControl,
+ xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "RControl", mods_all) == 1);
+ keys.set(GHOST_kModifierKeyOS,
+ xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "Super", mods_all) == 1);
+ keys.set(GHOST_kModifierKeyNumMasks,
+ xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "NumLock", mods_all) == 1);
+
+ return GHOST_kSuccess;
+ }
+ return GHOST_kFailure;
+}
+
+GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const
+{
+ if (!d->inputs.empty()) {
+ buttons = d->inputs[0]->buttons;
+ return GHOST_kSuccess;
+ }
+ return GHOST_kFailure;
+}
+
+GHOST_TUns8 *GHOST_SystemWayland::getClipboard(bool /*selection*/) const
+{
+ GHOST_TUns8 *clipboard = static_cast<GHOST_TUns8 *>(malloc((selection.size() + 1)));
+ memcpy(clipboard, selection.data(), selection.size() + 1);
+ return clipboard;
+}
+
+void GHOST_SystemWayland::putClipboard(GHOST_TInt8 *buffer, bool /*selection*/) const
+{
+ if (!d->data_device_manager || d->inputs.empty()) {
+ return;
+ }
+
+ data_source_t *data_source = d->inputs[0]->data_source;
+
+ /* Copy buffer. */
+ data_source->buffer_out = static_cast<char *>(malloc(strlen(buffer) + 1));
+ std::strcpy(data_source->buffer_out, buffer);
+
+ data_source->data_source = wl_data_device_manager_create_data_source(d->data_device_manager);
+
+ wl_data_source_add_listener(
+ data_source->data_source, &data_source_listener, data_source->buffer_out);
+
+ for (const std::string &type : mime_send) {
+ wl_data_source_offer(data_source->data_source, type.c_str());
+ }
+
+ if (!d->inputs.empty() && d->inputs[0]->data_device) {
+ wl_data_device_set_selection(
+ d->inputs[0]->data_device, data_source->data_source, data_source->source_serial);
+ }
+}
+
+GHOST_TUns8 GHOST_SystemWayland::getNumDisplays() const
+{
+ return d ? GHOST_TUns8(d->outputs.size()) : 0;
+}
+
+GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const
+{
+ if (!d->inputs.empty() && (d->inputs[0]->focus_pointer != nullptr)) {
+ x = d->inputs[0]->x;
+ y = d->inputs[0]->y;
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+GHOST_TSuccess GHOST_SystemWayland::setCursorPosition(GHOST_TInt32 /*x*/, GHOST_TInt32 /*y*/)
+{
+ return GHOST_kFailure;
+}
+
+void GHOST_SystemWayland::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
+{
+ if (getNumDisplays() > 0) {
+ /* We assume first output as main. */
+ width = uint32_t(d->outputs[0]->width);
+ height = uint32_t(d->outputs[0]->height);
+ }
+}
+
+void GHOST_SystemWayland::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
+{
+ getMainDisplayDimensions(width, height);
+}
+
+GHOST_IContext *GHOST_SystemWayland::createOffscreenContext()
+{
+ /* Create new off-screen window. */
+ wl_surface *os_surface = wl_compositor_create_surface(compositor());
+ wl_egl_window *os_egl_window = wl_egl_window_create(os_surface, int(1), int(1));
+
+ d->os_surfaces.push_back(os_surface);
+ d->os_egl_windows.push_back(os_egl_window);
+
+ GHOST_Context *context = new GHOST_ContextEGL(false,
+ EGLNativeWindowType(os_egl_window),
+ EGLNativeDisplayType(d->display),
+ EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
+ 3,
+ 3,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_API);
+
+ if (context->initializeDrawingContext()) {
+ return context;
+ }
+ else {
+ delete context;
+ }
+
+ GHOST_PRINT("Cannot create off-screen EGL context" << std::endl);
+
+ return nullptr;
+}
+
+GHOST_TSuccess GHOST_SystemWayland::disposeContext(GHOST_IContext *context)
+{
+ delete context;
+ return GHOST_kSuccess;
+}
+
+GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
+ GHOST_TInt32 left,
+ GHOST_TInt32 top,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height,
+ GHOST_TWindowState state,
+ GHOST_TDrawingContextType type,
+ GHOST_GLSettings glSettings,
+ const bool exclusive,
+ const bool /*is_dialog*/,
+ const GHOST_IWindow *parentWindow)
+{
+ GHOST_WindowWayland *window = new GHOST_WindowWayland(
+ this,
+ title,
+ left,
+ top,
+ width,
+ height,
+ state,
+ parentWindow,
+ type,
+ ((glSettings.flags & GHOST_glStereoVisual) != 0),
+ exclusive);
+
+ if (window) {
+ if (window->getValid()) {
+ m_windowManager->addWindow(window);
+ m_windowManager->setActiveWindow(window);
+ pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window));
+ }
+ else {
+ delete window;
+ window = nullptr;
+ }
+ }
+
+ return window;
+}
+
+wl_display *GHOST_SystemWayland::display()
+{
+ return d->display;
+}
+
+wl_compositor *GHOST_SystemWayland::compositor()
+{
+ return d->compositor;
+}
+
+xdg_wm_base *GHOST_SystemWayland::shell()
+{
+ return d->xdg_shell;
+}
+
+void GHOST_SystemWayland::setSelection(const std::string &selection)
+{
+ this->selection = selection;
+}
+
+static void set_cursor_buffer(input_t *input, wl_buffer *buffer)
+{
+ input->cursor.visible = (buffer != nullptr);
+
+ wl_surface_attach(input->cursor.surface, buffer, 0, 0);
+ wl_surface_commit(input->cursor.surface);
+
+ if (input->cursor.visible) {
+ wl_surface_damage(input->cursor.surface,
+ 0,
+ 0,
+ int32_t(input->cursor.image.width),
+ int32_t(input->cursor.image.height));
+ wl_pointer_set_cursor(input->pointer,
+ input->pointer_serial,
+ input->cursor.surface,
+ int32_t(input->cursor.image.hotspot_x),
+ int32_t(input->cursor.image.hotspot_y));
+ }
+}
+
+GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape)
+{
+ if (d->inputs.empty()) {
+ return GHOST_kFailure;
+ }
+ const std::string cursor_name = cursors.count(shape) ? cursors.at(shape) :
+ cursors.at(GHOST_kStandardCursorDefault);
+
+ wl_cursor *cursor = wl_cursor_theme_get_cursor(d->cursor_theme, cursor_name.c_str());
+
+ if (!cursor) {
+ GHOST_PRINT("cursor '" << cursor_name << "' does not exist" << std::endl);
+ return GHOST_kFailure;
+ }
+
+ struct wl_cursor_image *image = cursor->images[0];
+ struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
+ if (!buffer) {
+ return GHOST_kFailure;
+ }
+ cursor_t *c = &d->inputs[0]->cursor;
+ c->buffer = buffer;
+ c->image = *image;
+
+ set_cursor_buffer(d->inputs[0], buffer);
+
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_SystemWayland::hasCursorShape(GHOST_TStandardCursor cursorShape)
+{
+ return GHOST_TSuccess(cursors.count(cursorShape) && !cursors.at(cursorShape).empty());
+}
+
+GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(GHOST_TUns8 *bitmap,
+ GHOST_TUns8 *mask,
+ int sizex,
+ int sizey,
+ int hotX,
+ int hotY,
+ bool /*canInvertColor*/)
+{
+ if (d->inputs.empty()) {
+ return GHOST_kFailure;
+ }
+
+ cursor_t *cursor = &d->inputs[0]->cursor;
+
+ static const int32_t stride = sizex * 4; /* ARGB */
+ cursor->file_buffer->size = size_t(stride * sizey);
+
+ const int fd = memfd_create("blender-cursor-custom", MFD_CLOEXEC | MFD_ALLOW_SEALING);
+ fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK);
+ posix_fallocate(fd, 0, int32_t(cursor->file_buffer->size));
+
+ cursor->file_buffer->data = mmap(
+ nullptr, cursor->file_buffer->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+
+ struct wl_shm_pool *pool = wl_shm_create_pool(d->shm, fd, int32_t(cursor->file_buffer->size));
+
+ wl_buffer *buffer = wl_shm_pool_create_buffer(
+ pool, 0, sizex, sizey, stride, WL_SHM_FORMAT_ARGB8888);
+
+ wl_shm_pool_destroy(pool);
+ close(fd);
+
+ wl_buffer_add_listener(buffer, &cursor_buffer_listener, cursor);
+
+ static constexpr uint32_t black = 0xFF000000;
+ static constexpr uint32_t white = 0xFFFFFFFF;
+ static constexpr uint32_t transparent = 0x00000000;
+
+ uint8_t datab = 0, maskb = 0;
+ uint32_t *pixel;
+
+ for (int y = 0; y < sizey; ++y) {
+ pixel = &static_cast<uint32_t *>(cursor->file_buffer->data)[y * sizex];
+ for (int x = 0; x < sizex; ++x) {
+ if ((x % 8) == 0) {
+ datab = *bitmap++;
+ maskb = *mask++;
+
+ /* Reverse bit order. */
+ datab = uint8_t((datab * 0x0202020202ULL & 0x010884422010ULL) % 1023);
+ maskb = uint8_t((maskb * 0x0202020202ULL & 0x010884422010ULL) % 1023);
+ }
+
+ if (maskb & 0x80) {
+ *pixel++ = (datab & 0x80) ? white : black;
+ }
+ else {
+ *pixel++ = (datab & 0x80) ? white : transparent;
+ }
+ datab <<= 1;
+ maskb <<= 1;
+ }
+ }
+
+ cursor->buffer = buffer;
+ cursor->image.width = uint32_t(sizex);
+ cursor->image.height = uint32_t(sizey);
+ cursor->image.hotspot_x = uint32_t(hotX);
+ cursor->image.hotspot_y = uint32_t(hotY);
+
+ set_cursor_buffer(d->inputs[0], buffer);
+
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_SystemWayland::setCursorVisibility(bool visible)
+{
+ if (d->inputs.empty()) {
+ return GHOST_kFailure;
+ }
+
+ input_t *input = d->inputs[0];
+
+ cursor_t *cursor = &input->cursor;
+ if (visible) {
+ if (!cursor->visible) {
+ set_cursor_buffer(input, cursor->buffer);
+ }
+ }
+ else {
+ if (cursor->visible) {
+ set_cursor_buffer(input, nullptr);
+ }
+ }
+
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mode,
+ wl_surface *surface)
+{
+ if (d->inputs.empty()) {
+ return GHOST_kFailure;
+ }
+
+ input_t *input = d->inputs[0];
+
+ switch (mode) {
+ case GHOST_kGrabDisable:
+ if (input->relative_pointer) {
+ zwp_relative_pointer_v1_destroy(input->relative_pointer);
+ input->relative_pointer = nullptr;
+ }
+ if (input->locked_pointer) {
+ zwp_locked_pointer_v1_destroy(input->locked_pointer);
+ input->locked_pointer = nullptr;
+ }
+ break;
+
+ case GHOST_kGrabNormal:
+ case GHOST_kGrabWrap:
+ input->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(
+ d->relative_pointer_manager, input->pointer);
+ zwp_relative_pointer_v1_add_listener(
+ input->relative_pointer, &relative_pointer_listener, input);
+ input->locked_pointer = zwp_pointer_constraints_v1_lock_pointer(
+ d->pointer_constraints,
+ surface,
+ input->pointer,
+ nullptr,
+ ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
+ break;
+
+ case GHOST_kGrabHide:
+ setCursorVisibility(false);
+ break;
+ }
+
+ return GHOST_kSuccess;
+}
+
+/** \} */
diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h
new file mode 100644
index 00000000000..89cd3406b69
--- /dev/null
+++ b/intern/ghost/intern/GHOST_SystemWayland.h
@@ -0,0 +1,111 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ * Declaration of GHOST_SystemWayland class.
+ */
+
+#ifndef __GHOST_SYSTEMWAYLAND_H__
+#define __GHOST_SYSTEMWAYLAND_H__
+
+#include "../GHOST_Types.h"
+#include "GHOST_System.h"
+#include "GHOST_WindowWayland.h"
+
+#include <wayland-client.h>
+#include <xdg-shell-client-protocol.h>
+
+#include <string>
+
+class GHOST_WindowWayland;
+
+struct display_t;
+
+class GHOST_SystemWayland : public GHOST_System {
+ public:
+ GHOST_SystemWayland();
+
+ ~GHOST_SystemWayland() override;
+
+ bool processEvents(bool waitForEvent) override;
+
+ int toggleConsole(int action) override;
+
+ GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const override;
+
+ GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const override;
+
+ GHOST_TUns8 *getClipboard(bool selection) const override;
+
+ void putClipboard(GHOST_TInt8 *buffer, bool selection) const override;
+
+ GHOST_TUns8 getNumDisplays() const override;
+
+ GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const override;
+
+ GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) override;
+
+ void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const override;
+
+ void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const override;
+
+ GHOST_IContext *createOffscreenContext() override;
+
+ GHOST_TSuccess disposeContext(GHOST_IContext *context) override;
+
+ GHOST_IWindow *createWindow(const char *title,
+ GHOST_TInt32 left,
+ GHOST_TInt32 top,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height,
+ GHOST_TWindowState state,
+ GHOST_TDrawingContextType type,
+ GHOST_GLSettings glSettings,
+ const bool exclusive,
+ const bool is_dialog,
+ const GHOST_IWindow *parentWindow) override;
+
+ wl_display *display();
+
+ wl_compositor *compositor();
+
+ xdg_wm_base *shell();
+
+ void setSelection(const std::string &selection);
+
+ GHOST_TSuccess setCursorShape(GHOST_TStandardCursor shape);
+
+ GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor cursorShape);
+
+ GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap,
+ GHOST_TUns8 *mask,
+ int sizex,
+ int sizey,
+ int hotX,
+ int hotY,
+ bool canInvertColor);
+
+ GHOST_TSuccess setCursorVisibility(bool visible);
+
+ GHOST_TSuccess setCursorGrab(const GHOST_TGrabCursorMode mode, wl_surface *surface);
+
+ private:
+ struct display_t *d;
+ std::string selection;
+};
+
+#endif /* __GHOST_SYSTEMWAYLAND_H__ */
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index fdd022e44ac..849aa5a96f5 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -282,7 +282,7 @@ void GHOST_SystemWin32::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns3
height = ::GetSystemMetrics(SM_CYVIRTUALSCREEN);
}
-GHOST_IWindow *GHOST_SystemWin32::createWindow(const STR_String &title,
+GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index c6d810d2a38..b23f907608c 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -126,7 +126,7 @@ class GHOST_SystemWin32 : public GHOST_System {
* \param parentWindow Parent window
* \return The new window (or 0 if creation failed).
*/
- GHOST_IWindow *createWindow(const STR_String &title,
+ GHOST_IWindow *createWindow(const char *title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index 9c7368355b4..5c1f34e3a63 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -338,7 +338,7 @@ void GHOST_SystemX11::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32
* \param parentWindow Parent window
* \return The new window (or 0 if creation failed).
*/
-GHOST_IWindow *GHOST_SystemX11::createWindow(const STR_String &title,
+GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
@@ -1881,7 +1881,7 @@ static GHOST_TKey ghost_key_from_keysym(const KeySym key)
# endif
#endif
default:
-#ifdef GHOST_DEBUG
+#ifdef WITH_GHOST_DEBUG
printf("%s: unknown key: %lu / 0x%lx\n", __func__, key, key);
#endif
type = GHOST_kKeyUnknown;
@@ -1905,7 +1905,7 @@ static GHOST_TKey ghost_key_from_keycode(const XkbDescPtr xkb_descr, const KeyCo
switch (id) {
case MAKE_ID('T', 'L', 'D', 'E'):
return GHOST_kKeyAccentGrave;
-#ifdef GHOST_DEBUG
+#ifdef WITH_GHOST_DEBUG
default:
printf("%s unhandled keycode: %.*s\n", __func__, XkbKeyNameLength, id_str);
break;
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index d0e0506e77b..bb01ef7e0cc 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -137,7 +137,7 @@ class GHOST_SystemX11 : public GHOST_System {
* \param parentWindow Parent (embedder) window
* \return The new window (or 0 if creation failed).
*/
- GHOST_IWindow *createWindow(const STR_String &title,
+ GHOST_IWindow *createWindow(const char *title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
index 553a7d89df4..472149148e6 100644
--- a/intern/ghost/intern/GHOST_Window.h
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -27,7 +27,6 @@
#include "GHOST_IWindow.h"
-class STR_String;
class GHOST_Context;
/**
@@ -61,8 +60,8 @@ class GHOST_Window : public GHOST_IWindow {
* \section Interface inherited from GHOST_IWindow left for derived class
* implementation.
* virtual bool getValid() const = 0;
- * virtual void setTitle(const STR_String& title) = 0;
- * virtual void getTitle(STR_String& title) const = 0;
+ * virtual void setTitle(const char * title) = 0;
+ * virtual std::string getTitle() const = 0;
* virtual void getWindowBounds(GHOST_Rect& bounds) const = 0;
* virtual void getClientBounds(GHOST_Rect& bounds) const = 0;
* virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width) = 0;
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h
index efa418deee2..15429eab5db 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.h
+++ b/intern/ghost/intern/GHOST_WindowCocoa.h
@@ -30,7 +30,6 @@
#endif // __APPLE__
#include "GHOST_Window.h"
-#include "STR_String.h"
@class CAMetalLayer;
@class CocoaMetalView;
@@ -58,7 +57,7 @@ class GHOST_WindowCocoa : public GHOST_Window {
* \param stereoVisual Stereo visual for quad buffered stereo.
*/
GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa,
- const STR_String &title,
+ const char *title,
GHOST_TInt32 left,
GHOST_TInt32 bottom,
GHOST_TUns32 width,
@@ -92,13 +91,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.
*/
- void setTitle(const STR_String &title);
-
+ void setTitle(const char *title);
/**
* Returns the title displayed in the title bar.
* \param title The title displayed in the title bar.
*/
- void getTitle(STR_String &title) const;
+ std::string getTitle() const;
/**
* Returns the window rectangle dimensions.
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index 10ab05a0de1..05adc41cb8e 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -291,7 +291,7 @@
/* clang-format on */
GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa,
- const STR_String &title,
+ const char *title,
GHOST_TInt32 left,
GHOST_TInt32 bottom,
GHOST_TUns32 width,
@@ -482,7 +482,7 @@ void *GHOST_WindowCocoa::getOSWindow() const
return (void *)m_window;
}
-void GHOST_WindowCocoa::setTitle(const STR_String &title)
+void GHOST_WindowCocoa::setTitle(const char *title)
{
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid");
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@@ -524,7 +524,7 @@ void GHOST_WindowCocoa::setTitle(const STR_String &title)
[pool drain];
}
-void GHOST_WindowCocoa::getTitle(STR_String &title) const
+std::string GHOST_WindowCocoa::getTitle() const
{
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid");
@@ -532,11 +532,14 @@ void GHOST_WindowCocoa::getTitle(STR_String &title) const
NSString *windowTitle = [m_window title];
+ std::string title;
if (windowTitle != nil) {
title = [windowTitle UTF8String];
}
[pool drain];
+
+ return title;
}
void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect &bounds) const
diff --git a/intern/ghost/intern/GHOST_WindowNULL.h b/intern/ghost/intern/GHOST_WindowNULL.h
index db40075e6ca..e1aa0cb7f13 100644
--- a/intern/ghost/intern/GHOST_WindowNULL.h
+++ b/intern/ghost/intern/GHOST_WindowNULL.h
@@ -26,7 +26,6 @@
#include <map>
-class STR_String;
class GHOST_SystemNULL;
class GHOST_WindowNULL : public GHOST_Window {
@@ -37,7 +36,7 @@ class GHOST_WindowNULL : public GHOST_Window {
}
GHOST_WindowNULL(GHOST_SystemNULL *system,
- const STR_String &title,
+ const char *title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
@@ -83,12 +82,12 @@ class GHOST_WindowNULL : public GHOST_Window {
{
return true;
}
- void setTitle(const STR_String &title)
+ void setTitle(const char *title)
{ /* nothing */
}
- void getTitle(STR_String &title) const
+ std::string getTitle() const
{
- title = "untitled";
+ return "untitled";
}
void getWindowBounds(GHOST_Rect &bounds) const
{
diff --git a/intern/ghost/intern/GHOST_WindowSDL.cpp b/intern/ghost/intern/GHOST_WindowSDL.cpp
index e8d129f45fe..dcb1ab8c78c 100644
--- a/intern/ghost/intern/GHOST_WindowSDL.cpp
+++ b/intern/ghost/intern/GHOST_WindowSDL.cpp
@@ -27,7 +27,7 @@
#include <assert.h>
GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system,
- const STR_String &title,
+ const char *title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
@@ -148,14 +148,14 @@ bool GHOST_WindowSDL::getValid() const
return GHOST_Window::getValid() && m_valid_setup;
}
-void GHOST_WindowSDL::setTitle(const STR_String &title)
+void GHOST_WindowSDL::setTitle(const char *title)
{
- SDL_SetWindowTitle(m_sdl_win, title.ReadPtr());
+ SDL_SetWindowTitle(m_sdl_win, title);
}
-void GHOST_WindowSDL::getTitle(STR_String &title) const
+std::string GHOST_WindowSDL::getTitle() const
{
- title = SDL_GetWindowTitle(m_sdl_win);
+ return SDL_GetWindowTitle(m_sdl_win);
}
void GHOST_WindowSDL::getWindowBounds(GHOST_Rect &bounds) const
diff --git a/intern/ghost/intern/GHOST_WindowSDL.h b/intern/ghost/intern/GHOST_WindowSDL.h
index eadd1b7df9d..5039c742c9d 100644
--- a/intern/ghost/intern/GHOST_WindowSDL.h
+++ b/intern/ghost/intern/GHOST_WindowSDL.h
@@ -35,7 +35,6 @@ extern "C" {
# error "SDL 2.0 or newer is needed to build with Ghost"
#endif
-class STR_String;
class GHOST_SystemSDL;
class GHOST_WindowSDL : public GHOST_Window {
@@ -49,7 +48,7 @@ class GHOST_WindowSDL : public GHOST_Window {
public:
GHOST_WindowSDL(GHOST_SystemSDL *system,
- const STR_String &title,
+ const char *title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
@@ -107,9 +106,9 @@ class GHOST_WindowSDL : public GHOST_Window {
GHOST_TSuccess setWindowCursorVisibility(bool visible);
- void setTitle(const STR_String &title);
+ void setTitle(const char *title);
- void getTitle(STR_String &title) const;
+ std::string getTitle() const;
GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp
new file mode 100644
index 00000000000..0ea6f5f8ecb
--- /dev/null
+++ b/intern/ghost/intern/GHOST_WindowWayland.cpp
@@ -0,0 +1,406 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ */
+
+#include "GHOST_WindowWayland.h"
+#include "GHOST_SystemWayland.h"
+#include "GHOST_WindowManager.h"
+
+#include "GHOST_Event.h"
+
+#include "GHOST_ContextEGL.h"
+#include "GHOST_ContextNone.h"
+
+#include <wayland-egl.h>
+
+struct window_t {
+ GHOST_WindowWayland *w;
+ wl_surface *surface;
+ struct xdg_surface *xdg_surface;
+ struct xdg_toplevel *xdg_toplevel;
+ wl_egl_window *egl_window;
+ int32_t pending_width, pending_height;
+ bool is_maximised;
+ bool is_fullscreen;
+ bool is_active;
+ int32_t width, height;
+};
+
+/* -------------------------------------------------------------------- */
+/** \name Wayland Interface Callbacks
+ *
+ * These callbacks are registered for Wayland interfaces and called when
+ * an event is received from the compositor.
+ * \{ */
+
+static void toplevel_configure(
+ void *data, xdg_toplevel * /*xdg_toplevel*/, int32_t width, int32_t height, wl_array *states)
+{
+ window_t *win = static_cast<window_t *>(data);
+ win->pending_width = width;
+ win->pending_height = height;
+
+ win->is_maximised = false;
+ win->is_fullscreen = false;
+ win->is_active = false;
+
+ /* Note that the macro 'wl_array_for_each' would typically be used to simplify this logic,
+ * however it's not compatible with C++, so perform casts instead.
+ * If this needs to be done more often we could define our own C++ compatible macro. */
+ for (enum xdg_toplevel_state *state = static_cast<xdg_toplevel_state *>(states->data);
+ reinterpret_cast<uint8_t *>(state) < (static_cast<uint8_t *>(states->data) + states->size);
+ state++) {
+ switch (*state) {
+ case XDG_TOPLEVEL_STATE_MAXIMIZED:
+ win->is_maximised = true;
+ break;
+ case XDG_TOPLEVEL_STATE_FULLSCREEN:
+ win->is_fullscreen = true;
+ break;
+ case XDG_TOPLEVEL_STATE_ACTIVATED:
+ win->is_active = true;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void toplevel_close(void *data, xdg_toplevel * /*xdg_toplevel*/)
+{
+ static_cast<window_t *>(data)->w->close();
+}
+
+static const xdg_toplevel_listener toplevel_listener = {
+ toplevel_configure,
+ toplevel_close,
+};
+
+static void surface_configure(void *data, xdg_surface *xdg_surface, uint32_t serial)
+{
+ window_t *win = static_cast<window_t *>(data);
+
+ int w, h;
+ wl_egl_window_get_attached_size(win->egl_window, &w, &h);
+ if (win->pending_width != 0 && win->pending_height != 0 && win->pending_width != w &&
+ win->pending_height != h) {
+ win->width = win->pending_width;
+ win->height = win->pending_height;
+ wl_egl_window_resize(win->egl_window, win->pending_width, win->pending_height, 0, 0);
+ win->pending_width = 0;
+ win->pending_height = 0;
+ win->w->notify_size();
+ }
+
+ if (win->is_active) {
+ win->w->activate();
+ }
+ else {
+ win->w->deactivate();
+ }
+
+ xdg_surface_ack_configure(xdg_surface, serial);
+}
+
+static const xdg_surface_listener surface_listener = {
+ surface_configure,
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Ghost Implementation
+ *
+ * Wayland specific implementation of the GHOST_Window interface.
+ * \{ */
+
+GHOST_TSuccess GHOST_WindowWayland::hasCursorShape(GHOST_TStandardCursor cursorShape)
+{
+ return m_system->hasCursorShape(cursorShape);
+}
+
+GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
+ const char *title,
+ GHOST_TInt32 /*left*/,
+ GHOST_TInt32 /*top*/,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height,
+ GHOST_TWindowState state,
+ const GHOST_IWindow *parentWindow,
+ GHOST_TDrawingContextType type,
+ const bool stereoVisual,
+ const bool exclusive)
+ : GHOST_Window(width, height, state, stereoVisual, exclusive),
+ m_system(system),
+ w(new window_t)
+{
+ w->w = this;
+
+ w->width = int32_t(width);
+ w->height = int32_t(height);
+
+ /* Window surfaces. */
+ w->surface = wl_compositor_create_surface(m_system->compositor());
+ w->egl_window = wl_egl_window_create(w->surface, int(width), int(height));
+
+ w->xdg_surface = xdg_wm_base_get_xdg_surface(m_system->shell(), w->surface);
+ w->xdg_toplevel = xdg_surface_get_toplevel(w->xdg_surface);
+
+ wl_surface_set_user_data(w->surface, this);
+
+ xdg_surface_add_listener(w->xdg_surface, &surface_listener, w);
+ xdg_toplevel_add_listener(w->xdg_toplevel, &toplevel_listener, w);
+
+ if (parentWindow) {
+ xdg_toplevel_set_parent(
+ w->xdg_toplevel, dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->xdg_toplevel);
+ }
+
+ /* Call top-level callbacks. */
+ wl_surface_commit(w->surface);
+ wl_display_roundtrip(m_system->display());
+
+ setState(state);
+
+ setTitle(title);
+
+ /* EGL context. */
+ if (setDrawingContextType(type) == GHOST_kFailure) {
+ GHOST_PRINT("Failed to create EGL context" << std::endl);
+ }
+}
+
+GHOST_TSuccess GHOST_WindowWayland::close()
+{
+ return m_system->pushEvent(
+ new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowClose, this));
+}
+
+GHOST_TSuccess GHOST_WindowWayland::activate()
+{
+ if (m_system->getWindowManager()->setActiveWindow(this) == GHOST_kFailure) {
+ return GHOST_kFailure;
+ }
+ return m_system->pushEvent(
+ new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowActivate, this));
+}
+
+GHOST_TSuccess GHOST_WindowWayland::deactivate()
+{
+ m_system->getWindowManager()->setWindowInactive(this);
+ return m_system->pushEvent(
+ new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowDeactivate, this));
+}
+
+GHOST_TSuccess GHOST_WindowWayland::notify_size()
+{
+ return m_system->pushEvent(
+ new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowSize, this));
+}
+
+GHOST_TSuccess GHOST_WindowWayland::setWindowCursorGrab(GHOST_TGrabCursorMode mode)
+{
+ return m_system->setCursorGrab(mode, w->surface);
+}
+
+GHOST_TSuccess GHOST_WindowWayland::setWindowCursorShape(GHOST_TStandardCursor shape)
+{
+ const GHOST_TSuccess ok = m_system->setCursorShape(shape);
+ m_cursorShape = (ok == GHOST_kSuccess) ? shape : GHOST_kStandardCursorDefault;
+ return ok;
+}
+
+GHOST_TSuccess GHOST_WindowWayland::setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
+ GHOST_TUns8 *mask,
+ int sizex,
+ int sizey,
+ int hotX,
+ int hotY,
+ bool canInvertColor)
+{
+ return m_system->setCustomCursorShape(bitmap, mask, sizex, sizey, hotX, hotY, canInvertColor);
+}
+
+void GHOST_WindowWayland::setTitle(const char *title)
+{
+ xdg_toplevel_set_title(w->xdg_toplevel, title);
+ xdg_toplevel_set_app_id(w->xdg_toplevel, title);
+ this->title = title;
+}
+
+std::string GHOST_WindowWayland::getTitle() const
+{
+ return this->title.empty() ? "untitled" : this->title;
+}
+
+void GHOST_WindowWayland::getWindowBounds(GHOST_Rect &bounds) const
+{
+ getClientBounds(bounds);
+}
+
+void GHOST_WindowWayland::getClientBounds(GHOST_Rect &bounds) const
+{
+ bounds.set(0, 0, w->width, w->height);
+}
+
+GHOST_TSuccess GHOST_WindowWayland::setClientWidth(GHOST_TUns32 width)
+{
+ return setClientSize(width, GHOST_TUns32(w->height));
+}
+
+GHOST_TSuccess GHOST_WindowWayland::setClientHeight(GHOST_TUns32 height)
+{
+ return setClientSize(GHOST_TUns32(w->width), height);
+}
+
+GHOST_TSuccess GHOST_WindowWayland::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
+{
+ wl_egl_window_resize(w->egl_window, int(width), int(height), 0, 0);
+ return GHOST_kSuccess;
+}
+
+void GHOST_WindowWayland::screenToClient(GHOST_TInt32 inX,
+ GHOST_TInt32 inY,
+ GHOST_TInt32 &outX,
+ GHOST_TInt32 &outY) const
+{
+ outX = inX;
+ outY = inY;
+}
+
+void GHOST_WindowWayland::clientToScreen(GHOST_TInt32 inX,
+ GHOST_TInt32 inY,
+ GHOST_TInt32 &outX,
+ GHOST_TInt32 &outY) const
+{
+ outX = inX;
+ outY = inY;
+}
+
+GHOST_WindowWayland::~GHOST_WindowWayland()
+{
+ releaseNativeHandles();
+
+ wl_egl_window_destroy(w->egl_window);
+ xdg_toplevel_destroy(w->xdg_toplevel);
+ xdg_surface_destroy(w->xdg_surface);
+ wl_surface_destroy(w->surface);
+
+ delete w;
+}
+
+GHOST_TSuccess GHOST_WindowWayland::setWindowCursorVisibility(bool visible)
+{
+ return m_system->setCursorVisibility(visible);
+}
+
+GHOST_TSuccess GHOST_WindowWayland::setState(GHOST_TWindowState state)
+{
+ switch (state) {
+ case GHOST_kWindowStateNormal:
+ /* Unset states. */
+ switch (getState()) {
+ case GHOST_kWindowStateMaximized:
+ xdg_toplevel_unset_maximized(w->xdg_toplevel);
+ break;
+ case GHOST_kWindowStateFullScreen:
+ xdg_toplevel_unset_fullscreen(w->xdg_toplevel);
+ break;
+ default:
+ break;
+ }
+ break;
+ case GHOST_kWindowStateMaximized:
+ xdg_toplevel_set_maximized(w->xdg_toplevel);
+ break;
+ case GHOST_kWindowStateMinimized:
+ xdg_toplevel_set_minimized(w->xdg_toplevel);
+ break;
+ case GHOST_kWindowStateFullScreen:
+ xdg_toplevel_set_fullscreen(w->xdg_toplevel, nullptr);
+ break;
+ case GHOST_kWindowStateEmbedded:
+ return GHOST_kFailure;
+ }
+ return GHOST_kSuccess;
+}
+
+GHOST_TWindowState GHOST_WindowWayland::getState() const
+{
+ if (w->is_fullscreen) {
+ return GHOST_kWindowStateFullScreen;
+ }
+ else if (w->is_maximised) {
+ return GHOST_kWindowStateMaximized;
+ }
+ else {
+ return GHOST_kWindowStateNormal;
+ }
+}
+
+GHOST_TSuccess GHOST_WindowWayland::invalidate()
+{
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_WindowWayland::setOrder(GHOST_TWindowOrder /*order*/)
+{
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_WindowWayland::beginFullScreen() const
+{
+ xdg_toplevel_set_fullscreen(w->xdg_toplevel, nullptr);
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_WindowWayland::endFullScreen() const
+{
+ xdg_toplevel_unset_fullscreen(w->xdg_toplevel);
+ return GHOST_kSuccess;
+}
+
+/**
+ * \param type The type of rendering context create.
+ * \return Indication of success.
+ */
+GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType type)
+{
+ GHOST_Context *context;
+ switch (type) {
+ case GHOST_kDrawingContextTypeNone:
+ context = new GHOST_ContextNone(m_wantStereoVisual);
+ break;
+ case GHOST_kDrawingContextTypeOpenGL:
+ context = new GHOST_ContextEGL(m_wantStereoVisual,
+ EGLNativeWindowType(w->egl_window),
+ EGLNativeDisplayType(m_system->display()),
+ EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
+ 3,
+ 3,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_API);
+ break;
+ }
+
+ return (context->initializeDrawingContext() == GHOST_kSuccess) ? context : nullptr;
+}
+
+/** \} */
diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h
new file mode 100644
index 00000000000..39c35f77d7d
--- /dev/null
+++ b/intern/ghost/intern/GHOST_WindowWayland.h
@@ -0,0 +1,121 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup GHOST
+ *
+ * Declaration of GHOST_WindowWayland class.
+ */
+
+#ifndef __GHOST_WINDOWWAYLAND_H__
+#define __GHOST_WINDOWWAYLAND_H__
+
+#include "GHOST_Window.h"
+
+class GHOST_SystemWayland;
+
+struct window_t;
+
+class GHOST_WindowWayland : public GHOST_Window {
+ public:
+ GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor cursorShape) override;
+
+ GHOST_WindowWayland(GHOST_SystemWayland *system,
+ const char *title,
+ GHOST_TInt32 left,
+ GHOST_TInt32 top,
+ GHOST_TUns32 width,
+ GHOST_TUns32 height,
+ GHOST_TWindowState state,
+ const GHOST_IWindow *parentWindow,
+ GHOST_TDrawingContextType type,
+ const bool stereoVisual,
+ const bool exclusive);
+
+ ~GHOST_WindowWayland() override;
+
+ GHOST_TSuccess close();
+
+ GHOST_TSuccess activate();
+
+ GHOST_TSuccess deactivate();
+
+ GHOST_TSuccess notify_size();
+
+ protected:
+ GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode) override;
+
+ GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape) override;
+
+ GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
+ GHOST_TUns8 *mask,
+ int sizex,
+ int sizey,
+ int hotX,
+ int hotY,
+ bool canInvertColor) override;
+
+ void setTitle(const char *title) override;
+
+ std::string getTitle() const override;
+
+ void getWindowBounds(GHOST_Rect &bounds) const override;
+
+ void getClientBounds(GHOST_Rect &bounds) const override;
+
+ GHOST_TSuccess setClientWidth(GHOST_TUns32 width) override;
+
+ GHOST_TSuccess setClientHeight(GHOST_TUns32 height) override;
+
+ GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) override;
+
+ void screenToClient(GHOST_TInt32 inX,
+ GHOST_TInt32 inY,
+ GHOST_TInt32 &outX,
+ GHOST_TInt32 &outY) const override;
+
+ void clientToScreen(GHOST_TInt32 inX,
+ GHOST_TInt32 inY,
+ GHOST_TInt32 &outX,
+ GHOST_TInt32 &outY) const override;
+
+ GHOST_TSuccess setWindowCursorVisibility(bool visible) override;
+
+ GHOST_TSuccess setState(GHOST_TWindowState state) override;
+
+ GHOST_TWindowState getState() const override;
+
+ GHOST_TSuccess invalidate() override;
+
+ GHOST_TSuccess setOrder(GHOST_TWindowOrder order) override;
+
+ GHOST_TSuccess beginFullScreen() const override;
+
+ GHOST_TSuccess endFullScreen() const override;
+
+ private:
+ GHOST_SystemWayland *m_system;
+ struct window_t *w;
+ std::string title;
+
+ /**
+ * \param type The type of rendering context create.
+ * \return Indication of success.
+ */
+ GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type) override;
+};
+
+#endif // __GHOST_WINDOWWAYLAND_H__
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index 8b95cdd6351..55525157753 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -59,7 +59,7 @@ __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
}
GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
- const STR_String &title,
+ const char *title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
@@ -158,7 +158,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
height = rect.bottom - rect.top;
}
- wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0);
+ wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0);
m_hWnd = ::CreateWindowW(s_windowClassName, // pointer to registered class name
title_16, // pointer to window name
wintype, // window style
@@ -173,7 +173,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
free(title_16);
}
else {
- wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0);
+ wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0);
m_hWnd = ::CreateWindowW(s_windowClassName, // pointer to registered class name
title_16, // pointer to window name
WS_MAXIMIZE, // window style
@@ -430,19 +430,18 @@ HWND GHOST_WindowWin32::getHWND() const
return m_hWnd;
}
-void GHOST_WindowWin32::setTitle(const STR_String &title)
+void GHOST_WindowWin32::setTitle(const char *title)
{
- wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0);
+ wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0);
::SetWindowTextW(m_hWnd, (wchar_t *)title_16);
free(title_16);
}
-void GHOST_WindowWin32::getTitle(STR_String &title) const
+std::string GHOST_WindowWin32::getTitle() const
{
char buf[s_maxTitleLength]; /*CHANGE + never used yet*/
::GetWindowText(m_hWnd, buf, s_maxTitleLength);
- STR_String temp(buf);
- title = buf;
+ return std::string(buf);
}
void GHOST_WindowWin32::getWindowBounds(GHOST_Rect &bounds) const
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
index 489d3032552..dbed7c5ee5f 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.h
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -261,7 +261,7 @@ class GHOST_WindowWin32 : public GHOST_Window {
* \param parentWindowHwnd
*/
GHOST_WindowWin32(GHOST_SystemWin32 *system,
- const STR_String &title,
+ const char *title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
@@ -296,13 +296,13 @@ class GHOST_WindowWin32 : public GHOST_Window {
* Sets the title displayed in the title bar.
* \param title The title to display in the title bar.
*/
- void setTitle(const STR_String &title);
+ void setTitle(const char *title);
/**
* Returns the title displayed in the title bar.
- * \param title The title displayed in the title bar.
+ * \return The title displayed in the title bar.
*/
- void getTitle(STR_String &title) const;
+ std::string getTitle() const;
/**
* Returns the window rectangle dimensions.
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
index db9f6846b11..691f1790a2d 100644
--- a/intern/ghost/intern/GHOST_WindowX11.cpp
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -33,7 +33,6 @@
#include "GHOST_IconX11.h"
#include "GHOST_SystemX11.h"
#include "GHOST_WindowX11.h"
-#include "STR_String.h"
#ifdef WITH_XDND
# include "GHOST_DropTargetX11.h"
@@ -61,6 +60,7 @@
#include <unistd.h>
#include <algorithm>
+#include <limits.h>
#include <math.h>
#include <string>
@@ -212,7 +212,7 @@ static XVisualInfo *x11_visualinfo_from_glx(Display *display,
GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system,
Display *display,
- const STR_String &title,
+ const char *title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
@@ -414,9 +414,9 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system,
/* XClassHint, title */
{
XClassHint *xclasshint = XAllocClassHint();
- const int len = title.Length() + 1;
+ const int len = strlen(title) + 1;
char *wmclass = (char *)malloc(sizeof(char) * len);
- memcpy(wmclass, title.ReadPtr(), len * sizeof(char));
+ memcpy(wmclass, title, len * sizeof(char));
xclasshint->res_name = wmclass;
xclasshint->res_class = wmclass;
XSetClassHint(m_display, m_window, xclasshint);
@@ -617,7 +617,7 @@ bool GHOST_WindowX11::getValid() const
return GHOST_Window::getValid() && m_valid_setup;
}
-void GHOST_WindowX11::setTitle(const STR_String &title)
+void GHOST_WindowX11::setTitle(const char *title)
{
Atom name = XInternAtom(m_display, "_NET_WM_NAME", 0);
Atom utf8str = XInternAtom(m_display, "UTF8_STRING", 0);
@@ -627,8 +627,8 @@ void GHOST_WindowX11::setTitle(const STR_String &title)
utf8str,
8,
PropModeReplace,
- (const unsigned char *)title.ReadPtr(),
- title.Length());
+ (const unsigned char *)title,
+ strlen(title));
/* This should convert to valid x11 string
* and getTitle would need matching change */
@@ -637,13 +637,14 @@ void GHOST_WindowX11::setTitle(const STR_String &title)
XFlush(m_display);
}
-void GHOST_WindowX11::getTitle(STR_String &title) const
+std::string GHOST_WindowX11::getTitle() const
{
char *name = NULL;
XFetchName(m_display, m_window, &name);
- title = name ? name : "untitled";
+ std::string title = name ? name : "untitled";
XFree(name);
+ return title;
}
void GHOST_WindowX11::getWindowBounds(GHOST_Rect &bounds) const
diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h
index 4704cb45e58..4232ff40b52 100644
--- a/intern/ghost/intern/GHOST_WindowX11.h
+++ b/intern/ghost/intern/GHOST_WindowX11.h
@@ -37,7 +37,6 @@
#include <map>
-class STR_String;
class GHOST_SystemX11;
#ifdef WITH_XDND
@@ -69,7 +68,7 @@ class GHOST_WindowX11 : public GHOST_Window {
*/
GHOST_WindowX11(GHOST_SystemX11 *system,
Display *display,
- const STR_String &title,
+ const char *title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
@@ -85,9 +84,9 @@ class GHOST_WindowX11 : public GHOST_Window {
bool getValid() const;
- void setTitle(const STR_String &title);
+ void setTitle(const char *title);
- void getTitle(STR_String &title) const;
+ std::string getTitle() const;
void getWindowBounds(GHOST_Rect &bounds) const;
diff --git a/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp b/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp
index 60b3b06f6a8..5e30502f7ff 100644
--- a/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp
+++ b/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp
@@ -22,7 +22,7 @@
#include <list>
#include <sstream>
-#if defined(WITH_X11)
+#if defined(WITH_GHOST_X11)
# include "GHOST_ContextGLX.h"
#elif defined(WIN32)
# include "GHOST_ContextD3D.h"
@@ -68,7 +68,7 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding {
XrSystemId system_id,
std::string *r_requirement_info) const override
{
-#if defined(WITH_X11)
+#if defined(WITH_GHOST_X11)
GHOST_ContextGLX *ctx_gl = static_cast<GHOST_ContextGLX *>(ghost_ctx);
#else
GHOST_ContextWGL *ctx_gl = static_cast<GHOST_ContextWGL *>(ghost_ctx);
@@ -107,7 +107,7 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding {
void initFromGhostContext(GHOST_Context *ghost_ctx) override
{
-#if defined(WITH_X11)
+#if defined(WITH_GHOST_X11)
GHOST_ContextGLX *ctx_glx = static_cast<GHOST_ContextGLX *>(ghost_ctx);
XVisualInfo *visual_info = glXGetVisualFromFBConfig(ctx_glx->m_display, ctx_glx->m_fbconfig);
diff --git a/intern/ghost/intern/GHOST_Xr_openxr_includes.h b/intern/ghost/intern/GHOST_Xr_openxr_includes.h
index 925d6037750..9cac43b1549 100644
--- a/intern/ghost/intern/GHOST_Xr_openxr_includes.h
+++ b/intern/ghost/intern/GHOST_Xr_openxr_includes.h
@@ -42,7 +42,7 @@
#ifdef XR_USE_GRAPHICS_API_D3D12
# include <d3d12.h>
#endif
-#ifdef WITH_X11
+#ifdef WITH_GHOST_X11
# include <GL/glxew.h>
#endif
diff --git a/intern/ghost/test/CMakeLists.txt b/intern/ghost/test/CMakeLists.txt
index eda41eb9c1a..b6e3c0ecf5f 100644
--- a/intern/ghost/test/CMakeLists.txt
+++ b/intern/ghost/test/CMakeLists.txt
@@ -85,8 +85,9 @@ endif()
# Libraries
if(UNIX AND NOT APPLE)
- set(WITH_X11 ON)
+ set(WITH_GHOST_X11 ON)
endif()
+
# for now... default to this
add_definitions(-DWITH_GL_PROFILE_COMPAT)
# BLF needs this to ignore GPU library
diff --git a/intern/ghost/test/gears/GHOST_Test.cpp b/intern/ghost/test/gears/GHOST_Test.cpp
index a554bfeebef..c9c497aacb4 100644
--- a/intern/ghost/test/gears/GHOST_Test.cpp
+++ b/intern/ghost/test/gears/GHOST_Test.cpp
@@ -27,6 +27,7 @@
#include <iostream>
#include <math.h>
+#include <string>
#if defined(WIN32) || defined(__APPLE__)
# ifdef WIN32
@@ -43,7 +44,6 @@
#endif // defined(WIN32) || defined(__APPLE__)
#include "GHOST_Rect.h"
-#include "STR_String.h"
#include "GHOST_IEvent.h"
#include "GHOST_IEventConsumer.h"
@@ -427,8 +427,7 @@ Application::Application(GHOST_ISystem *system)
fApp = this;
// Create the main window
- STR_String title1("gears - main window");
- m_mainWindow = system->createWindow(title1,
+ m_mainWindow = system->createWindow("gears - main window",
10,
64,
320,
@@ -443,8 +442,7 @@ Application::Application(GHOST_ISystem *system)
}
// Create a secondary window
- STR_String title2("gears - secondary window");
- m_secondaryWindow = system->createWindow(title2,
+ m_secondaryWindow = system->createWindow("gears - secondary window",
340,
64,
320,
@@ -598,8 +596,7 @@ bool Application::processEvent(GHOST_IEvent *event)
case GHOST_kKeyW:
if (m_mainWindow) {
- STR_String title;
- m_mainWindow->getTitle(title);
+ std::string title = m_mainWindow->getTitle();
title += "-";
m_mainWindow->setTitle(title);
}
diff --git a/intern/guardedalloc/CMakeLists.txt b/intern/guardedalloc/CMakeLists.txt
index 1d4f846623c..cb24df65ba0 100644
--- a/intern/guardedalloc/CMakeLists.txt
+++ b/intern/guardedalloc/CMakeLists.txt
@@ -53,6 +53,14 @@ if(WIN32 AND NOT UNIX)
mmap_win.h
)
+
+ list(APPEND INC_SYS
+ ${PTHREADS_INC}
+ )
+
+ list(APPEND LIB
+ ${PTHREADS_LIBRARIES}
+ )
endif()
# Jemalloc 5.0.0+ needs extra configuration.
diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h
index d5b109ee59f..602297576c8 100644
--- a/intern/guardedalloc/MEM_guardedalloc.h
+++ b/intern/guardedalloc/MEM_guardedalloc.h
@@ -145,14 +145,6 @@ extern void *(*MEM_mallocN_aligned)(size_t len,
const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
ATTR_ALLOC_SIZE(1) ATTR_NONNULL(3);
-/**
- * Same as callocN, clears memory and uses mmap (disk cached) if supported.
- * Can be free'd with MEM_freeN as usual.
- * */
-extern void *(*MEM_mapallocN)(size_t len,
- const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
- ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
-
/** Print a list of the names and sizes of all allocated memory
* blocks. as a python dict for easy investigation */
extern void (*MEM_printmemlist_pydict)(void);
@@ -176,20 +168,11 @@ extern void (*MEM_set_error_callback)(void (*func)(const char *));
* @retval true for correct memory, false for corrupted memory. */
extern bool (*MEM_consistency_check)(void);
-/** Set thread locking functions for safe memory allocation from multiple
- * threads, pass NULL pointers to disable thread locking again. */
-extern void (*MEM_set_lock_callback)(void (*lock)(void), void (*unlock)(void));
-
/** Attempt to enforce OSX (or other OS's) to have malloc and stack nonzero */
extern void (*MEM_set_memory_debug)(void);
-/**
- * Memory usage stats
- * - MEM_get_memory_in_use is all memory
- * - MEM_get_mapped_memory_in_use is a subset of all memory */
+/** Memory usage stats. */
extern size_t (*MEM_get_memory_in_use)(void);
-/** Get mapped memory usage. */
-extern size_t (*MEM_get_mapped_memory_in_use)(void);
/** Get amount of memory blocks in use. */
extern unsigned int (*MEM_get_memory_blocks_in_use)(void);
diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c
index d24437c85f2..e85f8eb03ed 100644
--- a/intern/guardedalloc/intern/mallocn.c
+++ b/intern/guardedalloc/intern/mallocn.c
@@ -48,18 +48,14 @@ void *(*MEM_malloc_arrayN)(size_t len, size_t size, const char *str) = MEM_lockf
void *(*MEM_mallocN_aligned)(size_t len,
size_t alignment,
const char *str) = MEM_lockfree_mallocN_aligned;
-void *(*MEM_mapallocN)(size_t len, const char *str) = MEM_lockfree_mapallocN;
void (*MEM_printmemlist_pydict)(void) = MEM_lockfree_printmemlist_pydict;
void (*MEM_printmemlist)(void) = MEM_lockfree_printmemlist;
void (*MEM_callbackmemlist)(void (*func)(void *)) = MEM_lockfree_callbackmemlist;
void (*MEM_printmemlist_stats)(void) = MEM_lockfree_printmemlist_stats;
void (*MEM_set_error_callback)(void (*func)(const char *)) = MEM_lockfree_set_error_callback;
bool (*MEM_consistency_check)(void) = MEM_lockfree_consistency_check;
-void (*MEM_set_lock_callback)(void (*lock)(void),
- void (*unlock)(void)) = MEM_lockfree_set_lock_callback;
void (*MEM_set_memory_debug)(void) = MEM_lockfree_set_memory_debug;
size_t (*MEM_get_memory_in_use)(void) = MEM_lockfree_get_memory_in_use;
-size_t (*MEM_get_mapped_memory_in_use)(void) = MEM_lockfree_get_mapped_memory_in_use;
unsigned int (*MEM_get_memory_blocks_in_use)(void) = MEM_lockfree_get_memory_blocks_in_use;
void (*MEM_reset_peak_memory)(void) = MEM_lockfree_reset_peak_memory;
size_t (*MEM_get_peak_memory)(void) = MEM_lockfree_get_peak_memory;
@@ -111,17 +107,14 @@ void MEM_use_guarded_allocator(void)
MEM_mallocN = MEM_guarded_mallocN;
MEM_malloc_arrayN = MEM_guarded_malloc_arrayN;
MEM_mallocN_aligned = MEM_guarded_mallocN_aligned;
- MEM_mapallocN = MEM_guarded_mapallocN;
MEM_printmemlist_pydict = MEM_guarded_printmemlist_pydict;
MEM_printmemlist = MEM_guarded_printmemlist;
MEM_callbackmemlist = MEM_guarded_callbackmemlist;
MEM_printmemlist_stats = MEM_guarded_printmemlist_stats;
MEM_set_error_callback = MEM_guarded_set_error_callback;
MEM_consistency_check = MEM_guarded_consistency_check;
- MEM_set_lock_callback = MEM_guarded_set_lock_callback;
MEM_set_memory_debug = MEM_guarded_set_memory_debug;
MEM_get_memory_in_use = MEM_guarded_get_memory_in_use;
- MEM_get_mapped_memory_in_use = MEM_guarded_get_mapped_memory_in_use;
MEM_get_memory_blocks_in_use = MEM_guarded_get_memory_blocks_in_use;
MEM_reset_peak_memory = MEM_guarded_reset_peak_memory;
MEM_get_peak_memory = MEM_guarded_get_peak_memory;
diff --git a/intern/guardedalloc/intern/mallocn_guarded_impl.c b/intern/guardedalloc/intern/mallocn_guarded_impl.c
index f601609c6e0..20dcbed7235 100644
--- a/intern/guardedalloc/intern/mallocn_guarded_impl.c
+++ b/intern/guardedalloc/intern/mallocn_guarded_impl.c
@@ -28,6 +28,8 @@
#include <string.h> /* memcpy */
#include <sys/types.h>
+#include <pthread.h>
+
#include "MEM_guardedalloc.h"
/* to ensure strict conversions */
@@ -51,17 +53,6 @@
//#define DEBUG_MEMCOUNTER
/* Only for debugging:
- * defining DEBUG_THREADS will enable check whether memory manager
- * is locked with a mutex when allocation is called from non-main
- * thread.
- *
- * This helps troubleshooting memory issues caused by the fact
- * guarded allocator is not thread-safe, however this check will
- * fail to check allocations from openmp threads.
- */
-//#define DEBUG_THREADS
-
-/* Only for debugging:
* Defining DEBUG_BACKTRACE will store a backtrace from where
* memory block was allocated and print this trace for all
* unfreed blocks.
@@ -104,7 +95,7 @@ typedef struct MemHead {
const char *name;
const char *nextname;
int tag2;
- short mmap; /* if true, memory was mmapped */
+ short pad1;
short alignment; /* if non-zero aligned alloc was used
* and alignment is stored here.
*/
@@ -124,24 +115,6 @@ typedef struct MemHead {
typedef MemHead MemHeadAligned;
-/* for openmp threading asserts, saves time troubleshooting
- * we may need to extend this if blender code starts using MEM_
- * functions inside OpenMP correctly with omp_set_lock() */
-
-#if 0 /* disable for now, only use to debug openmp code which doesn lock threads for malloc */
-# if defined(_OPENMP) && defined(DEBUG)
-# include <assert.h>
-# include <omp.h>
-# define DEBUG_OMP_MALLOC
-# endif
-#endif
-
-#ifdef DEBUG_THREADS
-# include <assert.h>
-# include <pthread.h>
-static pthread_t mainid;
-#endif
-
#ifdef DEBUG_BACKTRACE
# if defined(__linux__) || defined(__APPLE__)
# include <execinfo.h>
@@ -187,13 +160,11 @@ static const char *check_memlist(MemHead *memh);
/* --------------------------------------------------------------------- */
static unsigned int totblock = 0;
-static size_t mem_in_use = 0, mmap_in_use = 0, peak_mem = 0;
+static size_t mem_in_use = 0, peak_mem = 0;
static volatile struct localListBase _membase;
static volatile struct localListBase *membase = &_membase;
static void (*error_callback)(const char *) = NULL;
-static void (*thread_lock_callback)(void) = NULL;
-static void (*thread_unlock_callback)(void) = NULL;
static bool malloc_debug_memset = false;
@@ -233,40 +204,16 @@ print_error(const char *str, ...)
fputs(buf, stderr);
}
+static pthread_mutex_t thread_lock = PTHREAD_MUTEX_INITIALIZER;
+
static void mem_lock_thread(void)
{
-#ifdef DEBUG_THREADS
- static int initialized = 0;
-
- if (initialized == 0) {
- /* assume first allocation happens from main thread */
- mainid = pthread_self();
- initialized = 1;
- }
-
- if (!pthread_equal(pthread_self(), mainid) && thread_lock_callback == NULL) {
- assert(!"Memory function is called from non-main thread without lock");
- }
-#endif
-
-#ifdef DEBUG_OMP_MALLOC
- assert(omp_in_parallel() == 0);
-#endif
-
- if (thread_lock_callback)
- thread_lock_callback();
+ pthread_mutex_lock(&thread_lock);
}
static void mem_unlock_thread(void)
{
-#ifdef DEBUG_THREADS
- if (!pthread_equal(pthread_self(), mainid) && thread_lock_callback == NULL) {
- assert(!"Thread lock was removed while allocation from thread is in progress");
- }
-#endif
-
- if (thread_unlock_callback)
- thread_unlock_callback();
+ pthread_mutex_unlock(&thread_lock);
}
bool MEM_guarded_consistency_check(void)
@@ -287,12 +234,6 @@ void MEM_guarded_set_error_callback(void (*func)(const char *))
error_callback = func;
}
-void MEM_guarded_set_lock_callback(void (*lock)(void), void (*unlock)(void))
-{
- thread_lock_callback = lock;
- thread_unlock_callback = unlock;
-}
-
void MEM_guarded_set_memory_debug(void)
{
malloc_debug_memset = true;
@@ -320,10 +261,8 @@ void *MEM_guarded_dupallocN(const void *vmemh)
memh--;
#ifndef DEBUG_MEMDUPLINAME
- if (UNLIKELY(memh->mmap))
- newp = MEM_guarded_mapallocN(memh->len, "dupli_mapalloc");
- else if (LIKELY(memh->alignment == 0))
- newp = MEM_guarded_mapallocN(memh->len, "dupli_mapalloc");
+ if (LIKELY(memh->alignment == 0))
+ newp = MEM_guarded_mallocN(memh->len, "dupli_alloc");
else
newp = MEM_guarded_mallocN_aligned(memh->len, (size_t)memh->alignment, "dupli_alloc");
@@ -334,11 +273,7 @@ void *MEM_guarded_dupallocN(const void *vmemh)
MemHead *nmemh;
char *name = malloc(strlen(memh->name) + 24);
- if (UNLIKELY(memh->mmap)) {
- sprintf(name, "%s %s", "dupli_mapalloc", memh->name);
- newp = MEM_guarded_mapallocN(memh->len, name);
- }
- else if (LIKELY(memh->alignment == 0)) {
+ if (LIKELY(memh->alignment == 0)) {
sprintf(name, "%s %s", "dupli_alloc", memh->name);
newp = MEM_guarded_mallocN(memh->len, name);
}
@@ -478,7 +413,7 @@ static void make_memhead_header(MemHead *memh, size_t len, const char *str)
memh->name = str;
memh->nextname = NULL;
memh->len = len;
- memh->mmap = 0;
+ memh->pad1 = 0;
memh->alignment = 0;
memh->tag2 = MEMTAG2;
@@ -646,58 +581,6 @@ void *MEM_guarded_calloc_arrayN(size_t len, size_t size, const char *str)
return MEM_guarded_callocN(total_size, str);
}
-/* note; mmap returns zero'd memory */
-void *MEM_guarded_mapallocN(size_t len, const char *str)
-{
- MemHead *memh;
-
- /* on 64 bit, simply use calloc instead, as mmap does not support
- * allocating > 4 GB on Windows. the only reason mapalloc exists
- * is to get around address space limitations in 32 bit OSes. */
- if (sizeof(void *) >= 8)
- return MEM_guarded_callocN(len, str);
-
- len = SIZET_ALIGN_4(len);
-
-#if defined(WIN32)
- /* our windows mmap implementation is not thread safe */
- mem_lock_thread();
-#endif
- memh = mmap(NULL,
- len + sizeof(MemHead) + sizeof(MemTail),
- PROT_READ | PROT_WRITE,
- MAP_SHARED | MAP_ANON,
- -1,
- 0);
-#if defined(WIN32)
- mem_unlock_thread();
-#endif
-
- if (memh != (MemHead *)-1) {
- make_memhead_header(memh, len, str);
- memh->mmap = 1;
- atomic_add_and_fetch_z(&mmap_in_use, len);
- mem_lock_thread();
- peak_mem = mmap_in_use > peak_mem ? mmap_in_use : peak_mem;
- mem_unlock_thread();
-#ifdef DEBUG_MEMCOUNTER
- if (_mallocn_count == DEBUG_MEMCOUNTER_ERROR_VAL)
- memcount_raise(__func__);
- memh->_count = _mallocn_count++;
-#endif
- return (++memh);
- }
- else {
- print_error(
- "Mapalloc returns null, fallback to regular malloc: "
- "len=" SIZET_FORMAT " in %s, total %u\n",
- SIZET_ARG(len),
- str,
- (unsigned int)mmap_in_use);
- return MEM_guarded_callocN(len, str);
- }
-}
-
/* Memory statistics print */
typedef struct MemPrintBlock {
const char *name;
@@ -765,7 +648,7 @@ void MEM_guarded_printmemlist_stats(void)
pb++;
#ifdef USE_MALLOC_USABLE_SIZE
- if (!membl->mmap && membl->alignment == 0) {
+ if (membl->alignment == 0) {
mem_in_use_slop += (sizeof(MemHead) + sizeof(MemTail) + malloc_usable_size((void *)membl)) -
membl->len;
}
@@ -1098,27 +981,13 @@ static void rem_memblock(MemHead *memh)
free((char *)memh->name);
#endif
- if (memh->mmap) {
- atomic_sub_and_fetch_z(&mmap_in_use, memh->len);
-#if defined(WIN32)
- /* our windows mmap implementation is not thread safe */
- mem_lock_thread();
-#endif
- if (munmap(memh, memh->len + sizeof(MemHead) + sizeof(MemTail)))
- printf("Couldn't unmap memory %s\n", memh->name);
-#if defined(WIN32)
- mem_unlock_thread();
-#endif
+ if (UNLIKELY(malloc_debug_memset && memh->len))
+ memset(memh + 1, 255, memh->len);
+ if (LIKELY(memh->alignment == 0)) {
+ free(memh);
}
else {
- if (UNLIKELY(malloc_debug_memset && memh->len))
- memset(memh + 1, 255, memh->len);
- if (LIKELY(memh->alignment == 0)) {
- free(memh);
- }
- else {
- aligned_free(MEMHEAD_REAL_PTR(memh));
- }
+ aligned_free(MEMHEAD_REAL_PTR(memh));
}
}
@@ -1270,17 +1139,6 @@ size_t MEM_guarded_get_memory_in_use(void)
return _mem_in_use;
}
-size_t MEM_guarded_get_mapped_memory_in_use(void)
-{
- size_t _mmap_in_use;
-
- mem_lock_thread();
- _mmap_in_use = mmap_in_use;
- mem_unlock_thread();
-
- return _mmap_in_use;
-}
-
unsigned int MEM_guarded_get_memory_blocks_in_use(void)
{
unsigned int _totblock;
diff --git a/intern/guardedalloc/intern/mallocn_intern.h b/intern/guardedalloc/intern/mallocn_intern.h
index 876607fdb77..ef8845a66b3 100644
--- a/intern/guardedalloc/intern/mallocn_intern.h
+++ b/intern/guardedalloc/intern/mallocn_intern.h
@@ -24,13 +24,6 @@
#ifndef __MALLOCN_INTERN_H__
#define __MALLOCN_INTERN_H__
-/* mmap exception */
-#if defined(WIN32)
-# include "mmap_win.h"
-#else
-# include <sys/mman.h>
-#endif
-
#ifdef __GNUC__
# define UNUSED(x) UNUSED_##x __attribute__((__unused__))
#else
@@ -140,19 +133,14 @@ void *MEM_lockfree_mallocN_aligned(size_t len,
size_t alignment,
const char *UNUSED(str)) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
ATTR_ALLOC_SIZE(1) ATTR_NONNULL(3);
-void *MEM_lockfree_mapallocN(size_t len,
- const char *UNUSED(str)) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
- ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
void MEM_lockfree_printmemlist_pydict(void);
void MEM_lockfree_printmemlist(void);
void MEM_lockfree_callbackmemlist(void (*func)(void *));
void MEM_lockfree_printmemlist_stats(void);
void MEM_lockfree_set_error_callback(void (*func)(const char *));
bool MEM_lockfree_consistency_check(void);
-void MEM_lockfree_set_lock_callback(void (*lock)(void), void (*unlock)(void));
void MEM_lockfree_set_memory_debug(void);
size_t MEM_lockfree_get_memory_in_use(void);
-size_t MEM_lockfree_get_mapped_memory_in_use(void);
unsigned int MEM_lockfree_get_memory_blocks_in_use(void);
void MEM_lockfree_reset_peak_memory(void);
size_t MEM_lockfree_get_peak_memory(void) ATTR_WARN_UNUSED_RESULT;
@@ -188,19 +176,14 @@ void *MEM_guarded_mallocN_aligned(size_t len,
size_t alignment,
const char *UNUSED(str)) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
ATTR_ALLOC_SIZE(1) ATTR_NONNULL(3);
-void *MEM_guarded_mapallocN(size_t len,
- const char *UNUSED(str)) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
- ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
void MEM_guarded_printmemlist_pydict(void);
void MEM_guarded_printmemlist(void);
void MEM_guarded_callbackmemlist(void (*func)(void *));
void MEM_guarded_printmemlist_stats(void);
void MEM_guarded_set_error_callback(void (*func)(const char *));
bool MEM_guarded_consistency_check(void);
-void MEM_guarded_set_lock_callback(void (*lock)(void), void (*unlock)(void));
void MEM_guarded_set_memory_debug(void);
size_t MEM_guarded_get_memory_in_use(void);
-size_t MEM_guarded_get_mapped_memory_in_use(void);
unsigned int MEM_guarded_get_memory_blocks_in_use(void);
void MEM_guarded_reset_peak_memory(void);
size_t MEM_guarded_get_peak_memory(void) ATTR_WARN_UNUSED_RESULT;
diff --git a/intern/guardedalloc/intern/mallocn_lockfree_impl.c b/intern/guardedalloc/intern/mallocn_lockfree_impl.c
index ab7d9097669..205cc688d72 100644
--- a/intern/guardedalloc/intern/mallocn_lockfree_impl.c
+++ b/intern/guardedalloc/intern/mallocn_lockfree_impl.c
@@ -44,22 +44,18 @@ typedef struct MemHeadAligned {
} MemHeadAligned;
static unsigned int totblock = 0;
-static size_t mem_in_use = 0, mmap_in_use = 0, peak_mem = 0;
+static size_t mem_in_use = 0, peak_mem = 0;
static bool malloc_debug_memset = false;
static void (*error_callback)(const char *) = NULL;
-static void (*thread_lock_callback)(void) = NULL;
-static void (*thread_unlock_callback)(void) = NULL;
enum {
- MEMHEAD_MMAP_FLAG = 1,
- MEMHEAD_ALIGN_FLAG = 2,
+ MEMHEAD_ALIGN_FLAG = 1,
};
#define MEMHEAD_FROM_PTR(ptr) (((MemHead *)ptr) - 1)
#define PTR_FROM_MEMHEAD(memhead) (memhead + 1)
#define MEMHEAD_ALIGNED_FROM_PTR(ptr) (((MemHeadAligned *)ptr) - 1)
-#define MEMHEAD_IS_MMAP(memhead) ((memhead)->len & (size_t)MEMHEAD_MMAP_FLAG)
#define MEMHEAD_IS_ALIGNED(memhead) ((memhead)->len & (size_t)MEMHEAD_ALIGN_FLAG)
/* Uncomment this to have proper peak counter. */
@@ -93,24 +89,10 @@ print_error(const char *str, ...)
}
}
-#if defined(WIN32)
-static void mem_lock_thread(void)
-{
- if (thread_lock_callback)
- thread_lock_callback();
-}
-
-static void mem_unlock_thread(void)
-{
- if (thread_unlock_callback)
- thread_unlock_callback();
-}
-#endif
-
size_t MEM_lockfree_allocN_len(const void *vmemh)
{
if (vmemh) {
- return MEMHEAD_FROM_PTR(vmemh)->len & ~((size_t)(MEMHEAD_MMAP_FLAG | MEMHEAD_ALIGN_FLAG));
+ return MEMHEAD_FROM_PTR(vmemh)->len & ~((size_t)(MEMHEAD_ALIGN_FLAG));
}
else {
return 0;
@@ -133,29 +115,15 @@ void MEM_lockfree_freeN(void *vmemh)
atomic_sub_and_fetch_u(&totblock, 1);
atomic_sub_and_fetch_z(&mem_in_use, len);
- if (MEMHEAD_IS_MMAP(memh)) {
- atomic_sub_and_fetch_z(&mmap_in_use, len);
-#if defined(WIN32)
- /* our windows mmap implementation is not thread safe */
- mem_lock_thread();
-#endif
- if (munmap(memh, len + sizeof(MemHead)))
- printf("Couldn't unmap memory\n");
-#if defined(WIN32)
- mem_unlock_thread();
-#endif
+ if (UNLIKELY(malloc_debug_memset && len)) {
+ memset(memh + 1, 255, len);
+ }
+ if (UNLIKELY(MEMHEAD_IS_ALIGNED(memh))) {
+ MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
+ aligned_free(MEMHEAD_REAL_PTR(memh_aligned));
}
else {
- if (UNLIKELY(malloc_debug_memset && len)) {
- memset(memh + 1, 255, len);
- }
- if (UNLIKELY(MEMHEAD_IS_ALIGNED(memh))) {
- MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
- aligned_free(MEMHEAD_REAL_PTR(memh_aligned));
- }
- else {
- free(memh);
- }
+ free(memh);
}
}
@@ -165,10 +133,7 @@ void *MEM_lockfree_dupallocN(const void *vmemh)
if (vmemh) {
MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
const size_t prev_size = MEM_lockfree_allocN_len(vmemh);
- if (UNLIKELY(MEMHEAD_IS_MMAP(memh))) {
- newp = MEM_lockfree_mapallocN(prev_size, "dupli_mapalloc");
- }
- else if (UNLIKELY(MEMHEAD_IS_ALIGNED(memh))) {
+ if (UNLIKELY(MEMHEAD_IS_ALIGNED(memh))) {
MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
newp = MEM_lockfree_mallocN_aligned(
prev_size, (size_t)memh_aligned->alignment, "dupli_malloc");
@@ -397,47 +362,6 @@ void *MEM_lockfree_mallocN_aligned(size_t len, size_t alignment, const char *str
return NULL;
}
-void *MEM_lockfree_mapallocN(size_t len, const char *str)
-{
- MemHead *memh;
-
- /* on 64 bit, simply use calloc instead, as mmap does not support
- * allocating > 4 GB on Windows. the only reason mapalloc exists
- * is to get around address space limitations in 32 bit OSes. */
- if (sizeof(void *) >= 8)
- return MEM_lockfree_callocN(len, str);
-
- len = SIZET_ALIGN_4(len);
-
-#if defined(WIN32)
- /* our windows mmap implementation is not thread safe */
- mem_lock_thread();
-#endif
- memh = mmap(NULL, len + sizeof(MemHead), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
-#if defined(WIN32)
- mem_unlock_thread();
-#endif
-
- if (memh != (MemHead *)-1) {
- memh->len = len | (size_t)MEMHEAD_MMAP_FLAG;
- atomic_add_and_fetch_u(&totblock, 1);
- atomic_add_and_fetch_z(&mem_in_use, len);
- atomic_add_and_fetch_z(&mmap_in_use, len);
-
- update_maximum(&peak_mem, mem_in_use);
- update_maximum(&peak_mem, mmap_in_use);
-
- return PTR_FROM_MEMHEAD(memh);
- }
- print_error(
- "Mapalloc returns null, fallback to regular malloc: "
- "len=" SIZET_FORMAT " in %s, total %u\n",
- SIZET_ARG(len),
- str,
- (unsigned int)mmap_in_use);
- return MEM_lockfree_callocN(len, str);
-}
-
void MEM_lockfree_printmemlist_pydict(void)
{
}
@@ -476,12 +400,6 @@ bool MEM_lockfree_consistency_check(void)
return true;
}
-void MEM_lockfree_set_lock_callback(void (*lock)(void), void (*unlock)(void))
-{
- thread_lock_callback = lock;
- thread_unlock_callback = unlock;
-}
-
void MEM_lockfree_set_memory_debug(void)
{
malloc_debug_memset = true;
@@ -492,11 +410,6 @@ size_t MEM_lockfree_get_memory_in_use(void)
return mem_in_use;
}
-size_t MEM_lockfree_get_mapped_memory_in_use(void)
-{
- return mmap_in_use;
-}
-
unsigned int MEM_lockfree_get_memory_blocks_in_use(void)
{
return totblock;
diff --git a/intern/libmv/CMakeLists.txt b/intern/libmv/CMakeLists.txt
index 1801751523a..c6078268512 100644
--- a/intern/libmv/CMakeLists.txt
+++ b/intern/libmv/CMakeLists.txt
@@ -150,6 +150,7 @@ if(WITH_LIBMV)
libmv/autotrack/tracks.h
libmv/base/aligned_malloc.h
libmv/base/id_generator.h
+ libmv/base/map.h
libmv/base/scoped_ptr.h
libmv/base/vector.h
libmv/base/vector_utils.h
diff --git a/intern/libmv/files.txt b/intern/libmv/files.txt
index 223066bb02f..0ec90ec041f 100644
--- a/intern/libmv/files.txt
+++ b/intern/libmv/files.txt
@@ -16,6 +16,7 @@ libmv/autotrack/tracks_test.cc
libmv/base/aligned_malloc.cc
libmv/base/aligned_malloc.h
libmv/base/id_generator.h
+libmv/base/map.h
libmv/base/scoped_ptr.h
libmv/base/scoped_ptr_test.cc
libmv/base/vector.h
diff --git a/intern/libmv/intern/camera_intrinsics.cc b/intern/libmv/intern/camera_intrinsics.cc
index 89e3d0d1178..554c4350b0a 100644
--- a/intern/libmv/intern/camera_intrinsics.cc
+++ b/intern/libmv/intern/camera_intrinsics.cc
@@ -24,6 +24,7 @@
using libmv::CameraIntrinsics;
using libmv::DivisionCameraIntrinsics;
using libmv::PolynomialCameraIntrinsics;
+using libmv::NukeCameraIntrinsics;
libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew(
const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options) {
@@ -55,6 +56,14 @@ libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy(
*division_intrinsics);
break;
}
+ case libmv::DISTORTION_MODEL_NUKE:
+ {
+ const NukeCameraIntrinsics *nuke_intrinsics =
+ static_cast<const NukeCameraIntrinsics*>(orig_intrinsics);
+ new_intrinsics = LIBMV_OBJECT_NEW(NukeCameraIntrinsics,
+ *nuke_intrinsics);
+ break;
+ }
default:
assert(!"Unknown distortion model");
}
@@ -136,6 +145,25 @@ void libmv_cameraIntrinsicsUpdate(
break;
}
+ case LIBMV_DISTORTION_MODEL_NUKE:
+ {
+ assert(camera_intrinsics->GetDistortionModelType() ==
+ libmv::DISTORTION_MODEL_NUKE);
+
+ NukeCameraIntrinsics *nuke_intrinsics =
+ (NukeCameraIntrinsics *) camera_intrinsics;
+
+ double k1 = libmv_camera_intrinsics_options->nuke_k1;
+ double k2 = libmv_camera_intrinsics_options->nuke_k2;
+
+ if (nuke_intrinsics->k1() != k1 ||
+ nuke_intrinsics->k2() != k2) {
+ nuke_intrinsics->SetDistortion(k1, k2);
+ }
+
+ break;
+ }
+
default:
assert(!"Unknown distortion model");
}
@@ -189,6 +217,17 @@ void libmv_cameraIntrinsicsExtractOptions(
break;
}
+ case libmv::DISTORTION_MODEL_NUKE:
+ {
+ const NukeCameraIntrinsics *nuke_intrinsics =
+ static_cast<const NukeCameraIntrinsics *>(camera_intrinsics);
+ camera_intrinsics_options->distortion_model =
+ LIBMV_DISTORTION_MODEL_NUKE;
+ camera_intrinsics_options->nuke_k1 = nuke_intrinsics->k1();
+ camera_intrinsics_options->nuke_k2 = nuke_intrinsics->k2();
+ break;
+ }
+
default:
assert(!"Unknown distortion model");
}
@@ -316,6 +355,17 @@ static void libmv_cameraIntrinsicsFillFromOptions(
break;
}
+ case LIBMV_DISTORTION_MODEL_NUKE:
+ {
+ NukeCameraIntrinsics *nuke_intrinsics =
+ static_cast<NukeCameraIntrinsics*>(camera_intrinsics);
+
+ nuke_intrinsics->SetDistortion(
+ camera_intrinsics_options->nuke_k1,
+ camera_intrinsics_options->nuke_k2);
+ break;
+ }
+
default:
assert(!"Unknown distortion model");
}
@@ -331,6 +381,9 @@ CameraIntrinsics* libmv_cameraIntrinsicsCreateFromOptions(
case LIBMV_DISTORTION_MODEL_DIVISION:
camera_intrinsics = LIBMV_OBJECT_NEW(DivisionCameraIntrinsics);
break;
+ case LIBMV_DISTORTION_MODEL_NUKE:
+ camera_intrinsics = LIBMV_OBJECT_NEW(NukeCameraIntrinsics);
+ break;
default:
assert(!"Unknown distortion model");
}
diff --git a/intern/libmv/intern/camera_intrinsics.h b/intern/libmv/intern/camera_intrinsics.h
index 40a5826a9c4..b3d259893bd 100644
--- a/intern/libmv/intern/camera_intrinsics.h
+++ b/intern/libmv/intern/camera_intrinsics.h
@@ -29,6 +29,7 @@ typedef struct libmv_CameraIntrinsics libmv_CameraIntrinsics;
enum {
LIBMV_DISTORTION_MODEL_POLYNOMIAL = 0,
LIBMV_DISTORTION_MODEL_DIVISION = 1,
+ LIBMV_DISTORTION_MODEL_NUKE = 2,
};
typedef struct libmv_CameraIntrinsicsOptions {
@@ -45,6 +46,9 @@ typedef struct libmv_CameraIntrinsicsOptions {
// Division distortion model.
double division_k1, division_k2;
+
+ // Nuke distortion model.
+ double nuke_k1, nuke_k2;
} libmv_CameraIntrinsicsOptions;
libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew(
diff --git a/intern/libmv/libmv/autotrack/reconstruction.h b/intern/libmv/libmv/autotrack/reconstruction.h
index e1d4e882cbd..732e74063f1 100644
--- a/intern/libmv/libmv/autotrack/reconstruction.h
+++ b/intern/libmv/libmv/autotrack/reconstruction.h
@@ -23,6 +23,7 @@
#ifndef LIBMV_AUTOTRACK_RECONSTRUCTION_H_
#define LIBMV_AUTOTRACK_RECONSTRUCTION_H_
+#include "libmv/base/map.h"
#include "libmv/base/vector.h"
#include "libmv/numeric/numeric.h"
#include "libmv/simple_pipeline/camera_intrinsics.h"
@@ -51,7 +52,7 @@ class Point {
};
// A reconstruction for a set of tracks. The indexing for clip, frame, and
-// track should match that of a Tracs object, stored elsewhere.
+// track should match that of a Tracks object, stored elsewhere.
class Reconstruction {
public:
// All methods copy their input reference or take ownership of the pointer.
@@ -75,7 +76,7 @@ class Reconstruction {
vector<CameraIntrinsics*> camera_intrinsics_;
// Indexed by Marker::clip then by Marker::frame.
- vector<vector<CameraPose> > camera_poses_;
+ vector<map<int, CameraPose>> camera_poses_;
// Indexed by Marker::track.
vector<Point> points_;
diff --git a/intern/libmv/libmv/base/map.h b/intern/libmv/libmv/base/map.h
new file mode 100644
index 00000000000..88b720f17fe
--- /dev/null
+++ b/intern/libmv/libmv/base/map.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2020 libmv authors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+
+#ifndef LIBMV_BASE_MAP_H
+#define LIBMV_BASE_MAP_H
+
+#include <map>
+#include <utility>
+
+namespace libmv {
+
+using std::map;
+using std::make_pair;
+
+} // namespace libmv
+
+#endif // LIBMV_BASE_MAP_H
diff --git a/intern/libmv/libmv/simple_pipeline/bundle.cc b/intern/libmv/libmv/simple_pipeline/bundle.cc
index e61650fb371..2ecc0505e1f 100644
--- a/intern/libmv/libmv/simple_pipeline/bundle.cc
+++ b/intern/libmv/libmv/simple_pipeline/bundle.cc
@@ -24,6 +24,7 @@
#include "ceres/ceres.h"
#include "ceres/rotation.h"
+#include "libmv/base/map.h"
#include "libmv/base/vector.h"
#include "libmv/logging/logging.h"
#include "libmv/multiview/fundamental.h"
@@ -66,18 +67,221 @@ enum {
namespace {
-// Cost functor which computes reprojection error of 3D point X
-// on camera defined by angle-axis rotation and it's translation
-// (which are in the same block due to optimization reasons).
+bool NeedUseInvertIntrinsicsPipeline(const CameraIntrinsics *intrinsics) {
+ const DistortionModelType distortion_model =
+ intrinsics->GetDistortionModelType();
+ return (distortion_model == DISTORTION_MODEL_NUKE);
+}
+
+// Apply distortion model (distort the input) on the input point in the
+// normalized space to get distorted coordinate in the image space.
+//
+// Using intrinsics values from the parameter block, which makes this function
+// suitable for use from a cost functor.
+//
+// Only use for distortion models which are analytically defined for their
+// Apply() function.
+//
+// The invariant_intrinsics are used to access intrinsics which are never
+// packed into parameter block: for example, distortion model type and image
+// dimension.
+template<typename T>
+void ApplyDistortionModelUsingIntrinsicsBlock(
+ const CameraIntrinsics *invariant_intrinsics,
+ const T* const intrinsics_block,
+ const T& normalized_x, const T& normalized_y,
+ T* distorted_x, T* distorted_y) {
+ // Unpack the intrinsics.
+ const T& focal_length = intrinsics_block[OFFSET_FOCAL_LENGTH];
+ const T& principal_point_x = intrinsics_block[OFFSET_PRINCIPAL_POINT_X];
+ const T& principal_point_y = intrinsics_block[OFFSET_PRINCIPAL_POINT_Y];
+
+ // TODO(keir): Do early bailouts for zero distortion; these are expensive
+ // jet operations.
+ switch (invariant_intrinsics->GetDistortionModelType()) {
+ case DISTORTION_MODEL_POLYNOMIAL:
+ {
+ const T& k1 = intrinsics_block[OFFSET_K1];
+ const T& k2 = intrinsics_block[OFFSET_K2];
+ const T& k3 = intrinsics_block[OFFSET_K3];
+ const T& p1 = intrinsics_block[OFFSET_P1];
+ const T& p2 = intrinsics_block[OFFSET_P2];
+
+ ApplyPolynomialDistortionModel(focal_length,
+ focal_length,
+ principal_point_x,
+ principal_point_y,
+ k1, k2, k3,
+ p1, p2,
+ normalized_x, normalized_y,
+ distorted_x, distorted_y);
+ return;
+ }
+
+ case DISTORTION_MODEL_DIVISION:
+ {
+ const T& k1 = intrinsics_block[OFFSET_K1];
+ const T& k2 = intrinsics_block[OFFSET_K2];
+
+ ApplyDivisionDistortionModel(focal_length,
+ focal_length,
+ principal_point_x,
+ principal_point_y,
+ k1, k2,
+ normalized_x, normalized_y,
+ distorted_x, distorted_y);
+ return;
+ }
+
+ case DISTORTION_MODEL_NUKE:
+ {
+ LOG(FATAL) << "Unsupported distortion model.";
+ return;
+ }
+ }
+
+ LOG(FATAL) << "Unknown distortion model.";
+}
+
+// Invert distortion model (undistort the input) on the input point in the
+// image space to get undistorted coordinate in the normalized space.
+//
+// Using intrinsics values from the parameter block, which makes this function
+// suitable for use from a cost functor.
+//
+// Only use for distortion models which are analytically defined for their
+// Invert() function.
+//
+// The invariant_intrinsics are used to access intrinsics which are never
+// packed into parameter block: for example, distortion model type and image
+// dimension.
+template<typename T>
+void InvertDistortionModelUsingIntrinsicsBlock(
+ const CameraIntrinsics *invariant_intrinsics,
+ const T* const intrinsics_block,
+ const T& image_x, const T& image_y,
+ T* normalized_x, T* normalized_y) {
+ // Unpack the intrinsics.
+ const T& focal_length = intrinsics_block[OFFSET_FOCAL_LENGTH];
+ const T& principal_point_x = intrinsics_block[OFFSET_PRINCIPAL_POINT_X];
+ const T& principal_point_y = intrinsics_block[OFFSET_PRINCIPAL_POINT_Y];
+
+ // TODO(keir): Do early bailouts for zero distortion; these are expensive
+ // jet operations.
+ switch (invariant_intrinsics->GetDistortionModelType()) {
+ case DISTORTION_MODEL_POLYNOMIAL:
+ case DISTORTION_MODEL_DIVISION:
+ LOG(FATAL) << "Unsupported distortion model.";
+ return;
+
+ case DISTORTION_MODEL_NUKE:
+ {
+ const T& k1 = intrinsics_block[OFFSET_K1];
+ const T& k2 = intrinsics_block[OFFSET_K2];
+
+ InvertNukeDistortionModel(focal_length,
+ focal_length,
+ principal_point_x,
+ principal_point_y,
+ invariant_intrinsics->image_width(),
+ invariant_intrinsics->image_height(),
+ k1, k2,
+ image_x, image_y,
+ normalized_x, normalized_y);
+ return;
+ }
+ }
+
+ LOG(FATAL) << "Unknown distortion model.";
+}
+
+template<typename T>
+void NormalizedToImageSpace(const T* const intrinsics_block,
+ const T& normalized_x, const T& normalized_y,
+ T* image_x, T* image_y) {
+ // Unpack the intrinsics.
+ const T& focal_length = intrinsics_block[OFFSET_FOCAL_LENGTH];
+ const T& principal_point_x = intrinsics_block[OFFSET_PRINCIPAL_POINT_X];
+ const T& principal_point_y = intrinsics_block[OFFSET_PRINCIPAL_POINT_Y];
+
+ *image_x = normalized_x * focal_length + principal_point_x;
+ *image_y = normalized_y * focal_length + principal_point_y;
+}
+
+// Cost functor which computes reprojection error of 3D point X on camera
+// defined by angle-axis rotation and it's translation (which are in the same
+// block due to optimization reasons).
+//
+// This functor can only be used for distortion models which have analytically
+// defined Apply() function.
+struct ReprojectionErrorApplyIntrinsics {
+ ReprojectionErrorApplyIntrinsics(
+ const CameraIntrinsics *invariant_intrinsics,
+ const double observed_distorted_x,
+ const double observed_distorted_y,
+ const double weight)
+ : invariant_intrinsics_(invariant_intrinsics),
+ observed_distorted_x_(observed_distorted_x),
+ observed_distorted_y_(observed_distorted_y),
+ weight_(weight) {}
+
+ template <typename T>
+ bool operator()(const T* const intrinsics,
+ const T* const R_t, // Rotation denoted by angle axis
+ // followed with translation
+ const T* const X, // Point coordinates 3x1.
+ T* residuals) const {
+ // Compute projective coordinates: x = RX + t.
+ T x[3];
+
+ ceres::AngleAxisRotatePoint(R_t, X, x);
+ x[0] += R_t[3];
+ x[1] += R_t[4];
+ x[2] += R_t[5];
+
+ // Prevent points from going behind the camera.
+ if (x[2] < T(0)) {
+ return false;
+ }
+
+ // Compute normalized coordinates: x /= x[2].
+ T xn = x[0] / x[2];
+ T yn = x[1] / x[2];
+
+ T predicted_distorted_x, predicted_distorted_y;
+ ApplyDistortionModelUsingIntrinsicsBlock(
+ invariant_intrinsics_,
+ intrinsics,
+ xn, yn,
+ &predicted_distorted_x, &predicted_distorted_y);
+
+ // The error is the difference between the predicted and observed position.
+ residuals[0] = (predicted_distorted_x - T(observed_distorted_x_)) * weight_;
+ residuals[1] = (predicted_distorted_y - T(observed_distorted_y_)) * weight_;
+ return true;
+ }
+
+ const CameraIntrinsics *invariant_intrinsics_;
+ const double observed_distorted_x_;
+ const double observed_distorted_y_;
+ const double weight_;
+};
+
+// Cost functor which computes reprojection error of 3D point X on camera
+// defined by angle-axis rotation and it's translation (which are in the same
+// block due to optimization reasons).
//
-// This functor uses a radial distortion model.
-struct OpenCVReprojectionError {
- OpenCVReprojectionError(const DistortionModelType distortion_model,
- const double observed_x,
- const double observed_y,
- const double weight)
- : distortion_model_(distortion_model),
- observed_x_(observed_x), observed_y_(observed_y),
+// This functor can only be used for distortion models which have analytically
+// defined Invert() function.
+struct ReprojectionErrorInvertIntrinsics {
+ ReprojectionErrorInvertIntrinsics(
+ const CameraIntrinsics *invariant_intrinsics,
+ const double observed_distorted_x,
+ const double observed_distorted_y,
+ const double weight)
+ : invariant_intrinsics_(invariant_intrinsics),
+ observed_distorted_x_(observed_distorted_x),
+ observed_distorted_y_(observed_distorted_y),
weight_(weight) {}
template <typename T>
@@ -108,63 +312,37 @@ struct OpenCVReprojectionError {
T xn = x[0] / x[2];
T yn = x[1] / x[2];
- T predicted_x, predicted_y;
-
- // Apply distortion to the normalized points to get (xd, yd).
- // TODO(keir): Do early bailouts for zero distortion; these are expensive
- // jet operations.
- switch (distortion_model_) {
- case DISTORTION_MODEL_POLYNOMIAL:
- {
- const T& k1 = intrinsics[OFFSET_K1];
- const T& k2 = intrinsics[OFFSET_K2];
- const T& k3 = intrinsics[OFFSET_K3];
- const T& p1 = intrinsics[OFFSET_P1];
- const T& p2 = intrinsics[OFFSET_P2];
-
- ApplyPolynomialDistortionModel(focal_length,
- focal_length,
- principal_point_x,
- principal_point_y,
- k1, k2, k3,
- p1, p2,
- xn, yn,
- &predicted_x,
- &predicted_y);
- break;
- }
- case DISTORTION_MODEL_DIVISION:
- {
- const T& k1 = intrinsics[OFFSET_K1];
- const T& k2 = intrinsics[OFFSET_K2];
+ // Compute image space coordinate from normalized.
+ T predicted_x = focal_length * xn + principal_point_x;
+ T predicted_y = focal_length * yn + principal_point_y;
- ApplyDivisionDistortionModel(focal_length,
- focal_length,
- principal_point_x,
- principal_point_y,
- k1, k2,
- xn, yn,
- &predicted_x,
- &predicted_y);
- break;
- }
- default:
- LOG(FATAL) << "Unknown distortion model";
- }
+ T observed_undistorted_normalized_x, observed_undistorted_normalized_y;
+ InvertDistortionModelUsingIntrinsicsBlock(
+ invariant_intrinsics_,
+ intrinsics,
+ T(observed_distorted_x_), T(observed_distorted_y_),
+ &observed_undistorted_normalized_x, &observed_undistorted_normalized_y);
+
+ T observed_undistorted_image_x, observed_undistorted_image_y;
+ NormalizedToImageSpace(
+ intrinsics,
+ observed_undistorted_normalized_x, observed_undistorted_normalized_y,
+ &observed_undistorted_image_x, &observed_undistorted_image_y);
// The error is the difference between the predicted and observed position.
- residuals[0] = (predicted_x - T(observed_x_)) * weight_;
- residuals[1] = (predicted_y - T(observed_y_)) * weight_;
+ residuals[0] = (predicted_x - observed_undistorted_image_x) * weight_;
+ residuals[1] = (predicted_y - observed_undistorted_image_y) * weight_;
+
return true;
}
- const DistortionModelType distortion_model_;
- const double observed_x_;
- const double observed_y_;
+ const CameraIntrinsics *invariant_intrinsics_;
+ const double observed_distorted_x_;
+ const double observed_distorted_y_;
const double weight_;
};
-// Print a message to the log which camera intrinsics are gonna to be optimixed.
+// Print a message to the log which camera intrinsics are gonna to be optimized.
void BundleIntrinsicsLogMessage(const int bundle_intrinsics) {
if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) {
LOG(INFO) << "Bundling only camera positions.";
@@ -193,29 +371,29 @@ void BundleIntrinsicsLogMessage(const int bundle_intrinsics) {
// Pack intrinsics from object to an array for easier
// and faster minimization.
void PackIntrinisicsIntoArray(const CameraIntrinsics &intrinsics,
- double ceres_intrinsics[OFFSET_MAX]) {
- ceres_intrinsics[OFFSET_FOCAL_LENGTH] = intrinsics.focal_length();
- ceres_intrinsics[OFFSET_PRINCIPAL_POINT_X] = intrinsics.principal_point_x();
- ceres_intrinsics[OFFSET_PRINCIPAL_POINT_Y] = intrinsics.principal_point_y();
+ double intrinsics_block[OFFSET_MAX]) {
+ intrinsics_block[OFFSET_FOCAL_LENGTH] = intrinsics.focal_length();
+ intrinsics_block[OFFSET_PRINCIPAL_POINT_X] = intrinsics.principal_point_x();
+ intrinsics_block[OFFSET_PRINCIPAL_POINT_Y] = intrinsics.principal_point_y();
int num_distortion_parameters = intrinsics.num_distortion_parameters();
assert(num_distortion_parameters <= NUM_DISTORTION_COEFFICIENTS);
const double *distortion_parameters = intrinsics.distortion_parameters();
for (int i = 0; i < num_distortion_parameters; ++i) {
- ceres_intrinsics[FIRST_DISTORTION_COEFFICIENT + i] =
+ intrinsics_block[FIRST_DISTORTION_COEFFICIENT + i] =
distortion_parameters[i];
}
}
// Unpack intrinsics back from an array to an object.
-void UnpackIntrinsicsFromArray(const double ceres_intrinsics[OFFSET_MAX],
+void UnpackIntrinsicsFromArray(const double intrinsics_block[OFFSET_MAX],
CameraIntrinsics *intrinsics) {
- intrinsics->SetFocalLength(ceres_intrinsics[OFFSET_FOCAL_LENGTH],
- ceres_intrinsics[OFFSET_FOCAL_LENGTH]);
+ intrinsics->SetFocalLength(intrinsics_block[OFFSET_FOCAL_LENGTH],
+ intrinsics_block[OFFSET_FOCAL_LENGTH]);
- intrinsics->SetPrincipalPoint(ceres_intrinsics[OFFSET_PRINCIPAL_POINT_X],
- ceres_intrinsics[OFFSET_PRINCIPAL_POINT_Y]);
+ intrinsics->SetPrincipalPoint(intrinsics_block[OFFSET_PRINCIPAL_POINT_X],
+ intrinsics_block[OFFSET_PRINCIPAL_POINT_Y]);
int num_distortion_parameters = intrinsics->num_distortion_parameters();
assert(num_distortion_parameters <= NUM_DISTORTION_COEFFICIENTS);
@@ -223,54 +401,46 @@ void UnpackIntrinsicsFromArray(const double ceres_intrinsics[OFFSET_MAX],
double *distortion_parameters = intrinsics->distortion_parameters();
for (int i = 0; i < num_distortion_parameters; ++i) {
distortion_parameters[i] =
- ceres_intrinsics[FIRST_DISTORTION_COEFFICIENT + i];
+ intrinsics_block[FIRST_DISTORTION_COEFFICIENT + i];
}
}
// Get a vector of camera's rotations denoted by angle axis
// conjuncted with translations into single block
//
-// Element with index i matches to a rotation+translation for
+// Element with key i matches to a rotation+translation for
// camera at image i.
-vector<Vec6> PackCamerasRotationAndTranslation(
- const Tracks &tracks,
+map<int, Vec6> PackCamerasRotationAndTranslation(
const EuclideanReconstruction &reconstruction) {
- vector<Vec6> all_cameras_R_t;
- int max_image = tracks.MaxImage();
-
- all_cameras_R_t.resize(max_image + 1);
-
- for (int i = 0; i <= max_image; i++) {
- const EuclideanCamera *camera = reconstruction.CameraForImage(i);
-
- if (!camera) {
- continue;
- }
-
- ceres::RotationMatrixToAngleAxis(&camera->R(0, 0),
- &all_cameras_R_t[i](0));
- all_cameras_R_t[i].tail<3>() = camera->t;
+ map<int, Vec6> all_cameras_R_t;
+
+ vector<EuclideanCamera> all_cameras = reconstruction.AllCameras();
+ for (const EuclideanCamera& camera : all_cameras) {
+ Vec6 camera_R_t;
+ ceres::RotationMatrixToAngleAxis(&camera.R(0, 0), &camera_R_t(0));
+ camera_R_t.tail<3>() = camera.t;
+ all_cameras_R_t.insert(make_pair(camera.image, camera_R_t));
}
+
return all_cameras_R_t;
}
// Convert cameras rotations fro mangle axis back to rotation matrix.
void UnpackCamerasRotationAndTranslation(
- const Tracks &tracks,
- const vector<Vec6> &all_cameras_R_t,
+ const map<int, Vec6> &all_cameras_R_t,
EuclideanReconstruction *reconstruction) {
- int max_image = tracks.MaxImage();
- for (int i = 0; i <= max_image; i++) {
- EuclideanCamera *camera = reconstruction->CameraForImage(i);
+ for (map<int, Vec6>::value_type image_and_camera_R_T : all_cameras_R_t) {
+ const int image = image_and_camera_R_T.first;
+ const Vec6& camera_R_t = image_and_camera_R_T.second;
+ EuclideanCamera *camera = reconstruction->CameraForImage(image);
if (!camera) {
continue;
}
- ceres::AngleAxisToRotationMatrix(&all_cameras_R_t[i](0),
- &camera->R(0, 0));
- camera->t = all_cameras_R_t[i].tail<3>();
+ ceres::AngleAxisToRotationMatrix(&camera_R_t(0), &camera->R(0, 0));
+ camera->t = camera_R_t.tail<3>();
}
}
@@ -299,71 +469,120 @@ void CRSMatrixToEigenMatrix(const ceres::CRSMatrix &crs_matrix,
void EuclideanBundlerPerformEvaluation(const Tracks &tracks,
EuclideanReconstruction *reconstruction,
- vector<Vec6> *all_cameras_R_t,
+ map<int, Vec6> *all_cameras_R_t,
ceres::Problem *problem,
BundleEvaluation *evaluation) {
- int max_track = tracks.MaxTrack();
- // Number of camera rotations equals to number of translation,
- int num_cameras = all_cameras_R_t->size();
- int num_points = 0;
-
- vector<EuclideanPoint*> minimized_points;
- for (int i = 0; i <= max_track; i++) {
- EuclideanPoint *point = reconstruction->PointForTrack(i);
- if (point) {
- // We need to know whether the track is constant zero weight,
- // and it so it wouldn't have parameter block in the problem.
- //
- // Getting all markers for track is not so bac currently since
- // this code is only used by keyframe selection when there are
- // not so much tracks and only 2 frames anyway.
- vector<Marker> markera_of_track = tracks.MarkersForTrack(i);
- for (int j = 0; j < markera_of_track.size(); j++) {
- if (markera_of_track.at(j).weight != 0.0) {
- minimized_points.push_back(point);
- num_points++;
- break;
- }
+ int max_track = tracks.MaxTrack();
+ // Number of camera rotations equals to number of translation,
+ int num_cameras = all_cameras_R_t->size();
+ int num_points = 0;
+
+ vector<EuclideanPoint*> minimized_points;
+ for (int i = 0; i <= max_track; i++) {
+ EuclideanPoint *point = reconstruction->PointForTrack(i);
+ if (point) {
+ // We need to know whether the track is a constant zero weight.
+ // If it is so it wouldn't have a parameter block in the problem.
+ //
+ // Usually getting all markers of a track is considered slow, but this
+ // code is only used by the keyframe selection code where there aren't
+ // that many tracks in the storage and there are only 2 frames for each
+ // of the tracks.
+ vector<Marker> markera_of_track = tracks.MarkersForTrack(i);
+ for (int j = 0; j < markera_of_track.size(); j++) {
+ if (markera_of_track.at(j).weight != 0.0) {
+ minimized_points.push_back(point);
+ num_points++;
+ break;
}
}
}
+ }
- LG << "Number of cameras " << num_cameras;
- LG << "Number of points " << num_points;
+ LG << "Number of cameras " << num_cameras;
+ LG << "Number of points " << num_points;
- evaluation->num_cameras = num_cameras;
- evaluation->num_points = num_points;
+ evaluation->num_cameras = num_cameras;
+ evaluation->num_points = num_points;
- if (evaluation->evaluate_jacobian) { // Evaluate jacobian matrix.
- ceres::CRSMatrix evaluated_jacobian;
- ceres::Problem::EvaluateOptions eval_options;
+ if (evaluation->evaluate_jacobian) { // Evaluate jacobian matrix.
+ ceres::CRSMatrix evaluated_jacobian;
+ ceres::Problem::EvaluateOptions eval_options;
- // Cameras goes first in the ordering.
- int max_image = tracks.MaxImage();
- for (int i = 0; i <= max_image; i++) {
- const EuclideanCamera *camera = reconstruction->CameraForImage(i);
- if (camera) {
- double *current_camera_R_t = &(*all_cameras_R_t)[i](0);
+ // Cameras goes first in the ordering.
+ int max_image = tracks.MaxImage();
+ for (int i = 0; i <= max_image; i++) {
+ const EuclideanCamera *camera = reconstruction->CameraForImage(i);
+ if (camera) {
+ double *current_camera_R_t = &(*all_cameras_R_t)[i](0);
- // All cameras are variable now.
- problem->SetParameterBlockVariable(current_camera_R_t);
+ // All cameras are variable now.
+ problem->SetParameterBlockVariable(current_camera_R_t);
- eval_options.parameter_blocks.push_back(current_camera_R_t);
- }
+ eval_options.parameter_blocks.push_back(current_camera_R_t);
}
+ }
- // Points goes at the end of ordering,
- for (int i = 0; i < minimized_points.size(); i++) {
- EuclideanPoint *point = minimized_points.at(i);
- eval_options.parameter_blocks.push_back(&point->X(0));
- }
+ // Points goes at the end of ordering,
+ for (int i = 0; i < minimized_points.size(); i++) {
+ EuclideanPoint *point = minimized_points.at(i);
+ eval_options.parameter_blocks.push_back(&point->X(0));
+ }
- problem->Evaluate(eval_options,
- NULL, NULL, NULL,
- &evaluated_jacobian);
+ problem->Evaluate(eval_options,
+ NULL, NULL, NULL,
+ &evaluated_jacobian);
- CRSMatrixToEigenMatrix(evaluated_jacobian, &evaluation->jacobian);
- }
+ CRSMatrixToEigenMatrix(evaluated_jacobian, &evaluation->jacobian);
+ }
+}
+
+template<typename CostFunction>
+void AddResidualBlockToProblemImpl(const CameraIntrinsics *invariant_intrinsics,
+ double observed_x, double observed_y,
+ double weight,
+ double intrinsics_block[OFFSET_MAX],
+ double *camera_R_t,
+ EuclideanPoint *point,
+ ceres::Problem* problem) {
+ problem->AddResidualBlock(new ceres::AutoDiffCostFunction<
+ CostFunction, 2, OFFSET_MAX, 6, 3>(
+ new CostFunction(
+ invariant_intrinsics,
+ observed_x, observed_y,
+ weight)),
+ NULL,
+ intrinsics_block,
+ camera_R_t,
+ &point->X(0));
+}
+
+void AddResidualBlockToProblem(const CameraIntrinsics *invariant_intrinsics,
+ const Marker &marker,
+ double marker_weight,
+ double intrinsics_block[OFFSET_MAX],
+ double *camera_R_t,
+ EuclideanPoint *point,
+ ceres::Problem* problem) {
+ if (NeedUseInvertIntrinsicsPipeline(invariant_intrinsics)) {
+ AddResidualBlockToProblemImpl<ReprojectionErrorInvertIntrinsics>(
+ invariant_intrinsics,
+ marker.x, marker.y,
+ marker_weight,
+ intrinsics_block,
+ camera_R_t,
+ point,
+ problem);
+ } else {
+ AddResidualBlockToProblemImpl<ReprojectionErrorApplyIntrinsics>(
+ invariant_intrinsics,
+ marker.x, marker.y,
+ marker_weight,
+ intrinsics_block,
+ camera_R_t,
+ point,
+ problem);
+ }
}
// This is an utility function to only bundle 3D position of
@@ -375,10 +594,10 @@ void EuclideanBundlerPerformEvaluation(const Tracks &tracks,
//
// At this point we only need to bundle points positions, cameras
// are to be totally still here.
-void EuclideanBundlePointsOnly(const DistortionModelType distortion_model,
+void EuclideanBundlePointsOnly(const CameraIntrinsics *invariant_intrinsics,
const vector<Marker> &markers,
- vector<Vec6> &all_cameras_R_t,
- double ceres_intrinsics[OFFSET_MAX],
+ map<int, Vec6> &all_cameras_R_t,
+ double intrinsics_block[OFFSET_MAX],
EuclideanReconstruction *reconstruction) {
ceres::Problem::Options problem_options;
ceres::Problem problem(problem_options);
@@ -392,20 +611,16 @@ void EuclideanBundlePointsOnly(const DistortionModelType distortion_model,
}
// Rotation of camera denoted in angle axis followed with
- // camera translaiton.
+ // camera translation.
double *current_camera_R_t = &all_cameras_R_t[camera->image](0);
- problem.AddResidualBlock(new ceres::AutoDiffCostFunction<
- OpenCVReprojectionError, 2, OFFSET_MAX, 6, 3>(
- new OpenCVReprojectionError(
- distortion_model,
- marker.x,
- marker.y,
- 1.0)),
- NULL,
- ceres_intrinsics,
- current_camera_R_t,
- &point->X(0));
+ AddResidualBlockToProblem(invariant_intrinsics,
+ marker,
+ 1.0,
+ intrinsics_block,
+ current_camera_R_t,
+ point,
+ &problem);
problem.SetParameterBlockConstant(current_camera_R_t);
num_residuals++;
@@ -417,7 +632,7 @@ void EuclideanBundlePointsOnly(const DistortionModelType distortion_model,
return;
}
- problem.SetParameterBlockConstant(ceres_intrinsics);
+ problem.SetParameterBlockConstant(intrinsics_block);
// Configure the solver.
ceres::Solver::Options options;
@@ -438,7 +653,6 @@ void EuclideanBundlePointsOnly(const DistortionModelType distortion_model,
ceres::Solve(options, &problem, &summary);
LG << "Final report:\n" << summary.FullReport();
-
}
} // namespace
@@ -464,22 +678,22 @@ void EuclideanBundleCommonIntrinsics(
LG << "Original intrinsics: " << *intrinsics;
vector<Marker> markers = tracks.AllMarkers();
- // N-th element denotes whether track N is a constant zero-weigthed track.
+ // N-th element denotes whether track N is a constant zero-weighted track.
vector<bool> zero_weight_tracks_flags(tracks.MaxTrack() + 1, true);
// Residual blocks with 10 parameters are unwieldly with Ceres, so pack the
// intrinsics into a single block and rely on local parameterizations to
// control which intrinsics are allowed to vary.
- double ceres_intrinsics[OFFSET_MAX];
- PackIntrinisicsIntoArray(*intrinsics, ceres_intrinsics);
+ double intrinsics_block[OFFSET_MAX];
+ PackIntrinisicsIntoArray(*intrinsics, intrinsics_block);
// Convert cameras rotations to angle axis and merge with translation
// into single parameter block for maximal minimization speed.
//
// Block for minimization has got the following structure:
// <3 elements for angle-axis> <3 elements for translation>
- vector<Vec6> all_cameras_R_t =
- PackCamerasRotationAndTranslation(tracks, *reconstruction);
+ map<int, Vec6> all_cameras_R_t =
+ PackCamerasRotationAndTranslation(*reconstruction);
// Parameterization used to restrict camera motion for modal solvers.
ceres::SubsetParameterization *constant_translation_parameterization = NULL;
@@ -509,24 +723,20 @@ void EuclideanBundleCommonIntrinsics(
}
// Rotation of camera denoted in angle axis followed with
- // camera translaiton.
+ // camera translation.
double *current_camera_R_t = &all_cameras_R_t[camera->image](0);
// Skip residual block for markers which does have absolutely
// no affect on the final solution.
// This way ceres is not gonna to go crazy.
if (marker.weight != 0.0) {
- problem.AddResidualBlock(new ceres::AutoDiffCostFunction<
- OpenCVReprojectionError, 2, OFFSET_MAX, 6, 3>(
- new OpenCVReprojectionError(
- intrinsics->GetDistortionModelType(),
- marker.x,
- marker.y,
- marker.weight)),
- NULL,
- ceres_intrinsics,
- current_camera_R_t,
- &point->X(0));
+ AddResidualBlockToProblem(intrinsics,
+ marker,
+ marker.weight,
+ intrinsics_block,
+ current_camera_R_t,
+ point,
+ &problem);
// We lock the first camera to better deal with scene orientation ambiguity.
if (!have_locked_camera) {
@@ -561,7 +771,7 @@ void EuclideanBundleCommonIntrinsics(
if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) {
// No camera intrinsics are being refined,
// set the whole parameter block as constant for best performance.
- problem.SetParameterBlockConstant(ceres_intrinsics);
+ problem.SetParameterBlockConstant(intrinsics_block);
} else {
// Set the camera intrinsics that are not to be bundled as
// constant using some macro trickery.
@@ -586,7 +796,7 @@ void EuclideanBundleCommonIntrinsics(
ceres::SubsetParameterization *subset_parameterization =
new ceres::SubsetParameterization(OFFSET_MAX, constant_intrinsics);
- problem.SetParameterization(ceres_intrinsics, subset_parameterization);
+ problem.SetParameterization(intrinsics_block, subset_parameterization);
}
// Configure the solver.
@@ -610,13 +820,11 @@ void EuclideanBundleCommonIntrinsics(
LG << "Final report:\n" << summary.FullReport();
// Copy rotations and translations back.
- UnpackCamerasRotationAndTranslation(tracks,
- all_cameras_R_t,
- reconstruction);
+ UnpackCamerasRotationAndTranslation(all_cameras_R_t, reconstruction);
// Copy intrinsics back.
if (bundle_intrinsics != BUNDLE_NO_INTRINSICS)
- UnpackIntrinsicsFromArray(ceres_intrinsics, intrinsics);
+ UnpackIntrinsicsFromArray(intrinsics_block, intrinsics);
LG << "Final intrinsics: " << *intrinsics;
@@ -641,10 +849,10 @@ void EuclideanBundleCommonIntrinsics(
if (zero_weight_markers.size()) {
LG << "Refining position of constant zero-weighted tracks";
- EuclideanBundlePointsOnly(intrinsics->GetDistortionModelType(),
+ EuclideanBundlePointsOnly(intrinsics,
zero_weight_markers,
all_cameras_R_t,
- ceres_intrinsics,
+ intrinsics_block,
reconstruction);
}
}
diff --git a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc
index 5e4e07b3c4c..a95b394ad06 100644
--- a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc
+++ b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc
@@ -131,6 +131,8 @@ void CameraIntrinsics::ResetLookupGrids() {
undistort_.Reset();
}
+// Polynomial model.
+
PolynomialCameraIntrinsics::PolynomialCameraIntrinsics()
: CameraIntrinsics() {
SetRadialDistortion(0.0, 0.0, 0.0);
@@ -193,6 +195,8 @@ void PolynomialCameraIntrinsics::InvertIntrinsics(
normalized_y);
}
+// Division model.
+
DivisionCameraIntrinsics::DivisionCameraIntrinsics()
: CameraIntrinsics() {
SetDistortion(0.0, 0.0);
@@ -241,6 +245,57 @@ void DivisionCameraIntrinsics::InvertIntrinsics(double image_x,
normalized_y);
}
+// Nuke model.
+
+NukeCameraIntrinsics::NukeCameraIntrinsics()
+ : CameraIntrinsics() {
+ SetDistortion(0.0, 0.0);
+}
+
+NukeCameraIntrinsics::NukeCameraIntrinsics(
+ const NukeCameraIntrinsics &from)
+ : CameraIntrinsics(from) {
+ SetDistortion(from.k1(), from.k1());
+}
+
+void NukeCameraIntrinsics::SetDistortion(double k1, double k2) {
+ parameters_[OFFSET_K1] = k1;
+ parameters_[OFFSET_K2] = k2;
+ ResetLookupGrids();
+}
+
+void NukeCameraIntrinsics::ApplyIntrinsics(double normalized_x,
+ double normalized_y,
+ double *image_x,
+ double *image_y) const {
+ ApplyNukeDistortionModel(focal_length_x(),
+ focal_length_y(),
+ principal_point_x(),
+ principal_point_y(),
+ image_width(), image_height(),
+ k1(), k2(),
+ normalized_x,
+ normalized_y,
+ image_x,
+ image_y);
+}
+
+void NukeCameraIntrinsics::InvertIntrinsics(double image_x,
+ double image_y,
+ double *normalized_x,
+ double *normalized_y) const {
+ InvertNukeDistortionModel(focal_length_x(),
+ focal_length_y(),
+ principal_point_x(),
+ principal_point_y(),
+ image_width(), image_height(),
+ k1(), k2(),
+ image_x,
+ image_y,
+ normalized_x,
+ normalized_y);
+}
+
std::ostream& operator <<(std::ostream &os,
const CameraIntrinsics &intrinsics) {
if (intrinsics.focal_length_x() == intrinsics.focal_length_x()) {
@@ -281,6 +336,14 @@ std::ostream& operator <<(std::ostream &os,
PRINT_NONZERO_COEFFICIENT(division_intrinsics, k2);
break;
}
+ case DISTORTION_MODEL_NUKE:
+ {
+ const NukeCameraIntrinsics *nuke_intrinsics =
+ static_cast<const NukeCameraIntrinsics *>(&intrinsics);
+ PRINT_NONZERO_COEFFICIENT(nuke_intrinsics, k1);
+ PRINT_NONZERO_COEFFICIENT(nuke_intrinsics, k2);
+ break;
+ }
default:
LOG(FATAL) << "Unknown distortion model.";
}
diff --git a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h
index 6a3ade81089..782fd56c54c 100644
--- a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h
+++ b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h
@@ -276,7 +276,7 @@ class CameraIntrinsics {
class PolynomialCameraIntrinsics : public CameraIntrinsics {
public:
// This constants defines an offset of corresponding coefficients
- // in the arameters_ array.
+ // in the parameters_ array.
enum {
OFFSET_K1,
OFFSET_K2,
@@ -342,7 +342,7 @@ class PolynomialCameraIntrinsics : public CameraIntrinsics {
class DivisionCameraIntrinsics : public CameraIntrinsics {
public:
// This constants defines an offset of corresponding coefficients
- // in the arameters_ array.
+ // in the parameters_ array.
enum {
OFFSET_K1,
OFFSET_K2,
@@ -393,6 +393,60 @@ class DivisionCameraIntrinsics : public CameraIntrinsics {
double parameters_[NUM_PARAMETERS];
};
+class NukeCameraIntrinsics : public CameraIntrinsics {
+ public:
+ // This constants defines an offset of corresponding coefficients
+ // in the parameters_ array.
+ enum {
+ OFFSET_K1,
+ OFFSET_K2,
+
+ // This defines the size of array which we need to have in order
+ // to store all the coefficients.
+ NUM_PARAMETERS,
+ };
+
+ NukeCameraIntrinsics();
+ NukeCameraIntrinsics(const NukeCameraIntrinsics &from);
+
+ DistortionModelType GetDistortionModelType() const {
+ return DISTORTION_MODEL_NUKE;
+ }
+
+ int num_distortion_parameters() const { return NUM_PARAMETERS; }
+ double *distortion_parameters() { return parameters_; };
+ const double *distortion_parameters() const { return parameters_; };
+
+ double k1() const { return parameters_[OFFSET_K1]; }
+ double k2() const { return parameters_[OFFSET_K2]; }
+
+ // Set radial distortion coeffcients.
+ void SetDistortion(double k1, double k2);
+
+ // Apply camera intrinsics to the normalized point to get image coordinates.
+ //
+ // This applies the lens distortion to a point which is in normalized
+ // camera coordinates (i.e. the principal point is at (0, 0)) to get image
+ // coordinates in pixels.
+ void ApplyIntrinsics(double normalized_x,
+ double normalized_y,
+ double *image_x,
+ double *image_y) const;
+
+ // Invert camera intrinsics on the image point to get normalized coordinates.
+ //
+ // This reverses the effect of lens distortion on a point which is in image
+ // coordinates to get normalized camera coordinates.
+ void InvertIntrinsics(double image_x,
+ double image_y,
+ double *normalized_x,
+ double *normalized_y) const;
+
+ private:
+ // Double-parameter division distortion model.
+ double parameters_[NUM_PARAMETERS];
+};
+
/// A human-readable representation of the camera intrinsic parameters.
std::ostream& operator <<(std::ostream &os,
const CameraIntrinsics &intrinsics);
diff --git a/intern/libmv/libmv/simple_pipeline/distortion_models.cc b/intern/libmv/libmv/simple_pipeline/distortion_models.cc
index 9b6dca2678a..c069fc6f623 100644
--- a/intern/libmv/libmv/simple_pipeline/distortion_models.cc
+++ b/intern/libmv/libmv/simple_pipeline/distortion_models.cc
@@ -194,4 +194,96 @@ void InvertDivisionDistortionModel(const double focal_length_x,
*normalized_y = normalized(1);
}
+struct ApplyNukeIntrinsicsCostFunction {
+ public:
+ typedef Vec2 FMatrixType;
+ typedef Vec2 XMatrixType;
+
+ ApplyNukeIntrinsicsCostFunction(const double focal_length_x,
+ const double focal_length_y,
+ const double principal_point_x,
+ const double principal_point_y,
+ const int image_width,
+ const int image_height,
+ const double k1,
+ const double k2,
+ const double expected_normalized_x,
+ const double expected_normalized_y)
+ : focal_length_x_(focal_length_x),
+ focal_length_y_(focal_length_y),
+ principal_point_x_(principal_point_x),
+ principal_point_y_(principal_point_y),
+ image_width_(image_width),
+ image_height_(image_height),
+ k1_(k1), k2_(k2),
+ expected_normalized_x_(expected_normalized_x),
+ expected_normalized_y_(expected_normalized_y) {}
+
+ Vec2 operator()(const Vec2 &image_coordinate) const {
+ double actual_normalized_x, actual_normalized_y;
+
+ InvertNukeDistortionModel(focal_length_x_,
+ focal_length_y_,
+ principal_point_x_,
+ principal_point_y_,
+ image_width_, image_height_,
+ k1_, k2_,
+ image_coordinate(0), image_coordinate(1),
+ &actual_normalized_x, &actual_normalized_y);
+
+ Vec2 fx;
+ fx << (actual_normalized_x - expected_normalized_x_),
+ (actual_normalized_y - expected_normalized_y_);
+ return fx;
+ }
+ double focal_length_x_;
+ double focal_length_y_;
+ double principal_point_x_;
+ double principal_point_y_;
+ int image_width_;
+ int image_height_;
+ double k1_, k2_;
+ double expected_normalized_x_, expected_normalized_y_;
+};
+
+void ApplyNukeDistortionModel(const double focal_length_x,
+ const double focal_length_y,
+ const double principal_point_x,
+ const double principal_point_y,
+ const int image_width,
+ const int image_height,
+ const double k1,
+ const double k2,
+ const double normalized_x,
+ const double normalized_y,
+ double *image_x,
+ double *image_y) {
+ // Compute the initial guess. For a camera with no distortion, this will also
+ // be the final answer; the LM iteration will terminate immediately.
+ Vec2 image;
+ image(0) = normalized_x * focal_length_x + principal_point_x;
+ image(1) = normalized_y * focal_length_y + principal_point_y;
+
+ // TODO(sergey): Use Ceres minimizer instead.
+ typedef LevenbergMarquardt<ApplyNukeIntrinsicsCostFunction> Solver;
+
+ ApplyNukeIntrinsicsCostFunction intrinsics_cost(focal_length_x,
+ focal_length_y,
+ principal_point_x,
+ principal_point_y,
+ image_width,
+ image_height,
+ k1, k2,
+ normalized_x, normalized_y);
+ Solver::SolverParameters params;
+ Solver solver(intrinsics_cost);
+
+ /*Solver::Results results =*/ solver.minimize(params, &image);
+
+ // TODO(keir): Better error handling.
+
+ *image_x = image(0);
+ *image_y = image(1);
+}
+
} // namespace libmv
diff --git a/intern/libmv/libmv/simple_pipeline/distortion_models.h b/intern/libmv/libmv/simple_pipeline/distortion_models.h
index 4f8e2295a0e..6ba351d729d 100644
--- a/intern/libmv/libmv/simple_pipeline/distortion_models.h
+++ b/intern/libmv/libmv/simple_pipeline/distortion_models.h
@@ -21,11 +21,14 @@
#ifndef LIBMV_SIMPLE_PIPELINE_DISTORTION_MODELS_H_
#define LIBMV_SIMPLE_PIPELINE_DISTORTION_MODELS_H_
+#include <algorithm>
+
namespace libmv {
enum DistortionModelType {
DISTORTION_MODEL_POLYNOMIAL,
- DISTORTION_MODEL_DIVISION
+ DISTORTION_MODEL_DIVISION,
+ DISTORTION_MODEL_NUKE,
};
// Invert camera intrinsics on the image point to get normalized coordinates.
@@ -126,6 +129,79 @@ inline void ApplyDivisionDistortionModel(const T &focal_length_x,
*image_y = focal_length_y * yd + principal_point_y;
}
+// Invert camera intrinsics on the image point to get normalized coordinates.
+// This inverts the radial lens distortion to a point which is in image pixel
+// coordinates to get normalized coordinates.
+//
+// Uses Nuke distortion model.
+template <typename T>
+void InvertNukeDistortionModel(const T &focal_length_x,
+ const T &focal_length_y,
+ const T &principal_point_x,
+ const T &principal_point_y,
+ const int image_width,
+ const int image_height,
+ const T &k1,
+ const T &k2,
+ const T &image_x,
+ const T &image_y,
+ T *normalized_x,
+ T *normalized_y) {
+ // According to the documentation:
+ //
+ // xu = xd / (1 + k0 * rd^2 + k1 * rd^4)
+ // yu = yd / (1 + k0 * rd^2 + k1 * rd^4)
+ //
+ // Legend:
+ // (xd, yd) are the distorted cartesian coordinates,
+ // (rd, phid) are the distorted polar coordinates,
+ // (xu, yu) are the undistorted cartesian coordinates,
+ // (ru, phiu) are the undistorted polar coordinates,
+ // the k-values are the distortion coefficients.
+ //
+ // The coordinate systems are relative to the distortion centre.
+
+ const int max_image_size = std::max(image_width, image_height);
+ const double max_half_image_size = max_image_size * 0.5;
+
+ if (max_half_image_size == 0.0) {
+ *normalized_x = image_x * max_half_image_size / focal_length_x;
+ *normalized_y = image_y * max_half_image_size / focal_length_y;
+ return;
+ }
+
+ const T xd = (image_x - principal_point_x) / max_half_image_size;
+ const T yd = (image_y - principal_point_y) / max_half_image_size;
+
+ T rd2 = xd*xd + yd*yd;
+ T rd4 = rd2 * rd2;
+ T r_coeff = T(1) / (T(1) + k1*rd2 + k2*rd4);
+ T xu = xd * r_coeff;
+ T yu = yd * r_coeff;
+
+ *normalized_x = xu * max_half_image_size / focal_length_x;
+ *normalized_y = yu * max_half_image_size / focal_length_y;
+}
+
+// Apply camera intrinsics to the normalized point to get image coordinates.
+// This applies the radial lens distortion to a point which is in normalized
+// camera coordinates (i.e. the principal point is at (0, 0)) to get image
+// coordinates in pixels. Templated for use with autodifferentiation.
+//
+// Uses Nuke distortion model.
+void ApplyNukeDistortionModel(const double focal_length_x,
+ const double focal_length_y,
+ const double principal_point_x,
+ const double principal_point_y,
+ const int image_width,
+ const int image_height,
+ const double k1,
+ const double k2,
+ const double normalized_x,
+ const double normalized_y,
+ double *image_x,
+ double *image_y);
+
} // namespace libmv
#endif // LIBMV_SIMPLE_PIPELINE_DISTORTION_MODELS_H_
diff --git a/intern/libmv/libmv/simple_pipeline/initialize_reconstruction.h b/intern/libmv/libmv/simple_pipeline/initialize_reconstruction.h
index 744436246b0..32cd4285190 100644
--- a/intern/libmv/libmv/simple_pipeline/initialize_reconstruction.h
+++ b/intern/libmv/libmv/simple_pipeline/initialize_reconstruction.h
@@ -33,7 +33,7 @@ class ProjectiveReconstruction;
Initialize the \link EuclideanReconstruction reconstruction \endlink using
two frames.
- \a markers should contain all \l Marker markers \endlink belonging to
+ \a markers should contain all \link Marker markers \endlink belonging to
tracks visible in both frames. The pose estimation of the camera for
these frames will be inserted into \a *reconstruction.
@@ -54,7 +54,7 @@ bool EuclideanReconstructTwoFrames(const vector<Marker> &markers,
Initialize the \link ProjectiveReconstruction reconstruction \endlink using
two frames.
- \a markers should contain all \l Marker markers \endlink belonging to
+ \a markers should contain all \link Marker markers \endlink belonging to
tracks visible in both frames. An estimate of the projection matrices for
the two frames will get added to the reconstruction.
diff --git a/intern/libmv/libmv/simple_pipeline/intersect.h b/intern/libmv/libmv/simple_pipeline/intersect.h
index 3a0ffa7418b..15d6f998557 100644
--- a/intern/libmv/libmv/simple_pipeline/intersect.h
+++ b/intern/libmv/libmv/simple_pipeline/intersect.h
@@ -35,10 +35,10 @@ namespace libmv {
the frames for which there is a marker for that track must have a
corresponding reconstructed camera in \a *reconstruction.
- \a markers should contain all \l Marker markers \endlink belonging to
+ \a markers should contain all \link Marker markers \endlink belonging to
tracks visible in all frames.
\a reconstruction should contain the cameras for all frames.
- The new \l Point points \endlink will be inserted in \a reconstruction.
+ The new \link Point points \endlink will be inserted in \a reconstruction.
\note This assumes a calibrated reconstruction, e.g. the markers are
already corrected for camera intrinsics and radial distortion.
@@ -57,10 +57,10 @@ bool EuclideanIntersect(const vector<Marker> &markers,
track. Each of the frames for which there is a marker for that track must
have a corresponding reconstructed camera in \a *reconstruction.
- \a markers should contain all \l Marker markers \endlink belonging to
+ \a markers should contain all \link Marker markers \endlink belonging to
tracks visible in all frames.
\a reconstruction should contain the cameras for all frames.
- The new \l Point points \endlink will be inserted in \a reconstruction.
+ The new \link Point points \endlink will be inserted in \a reconstruction.
\note This assumes that radial distortion is already corrected for, but
does not assume that e.g. focal length and principal point are
diff --git a/intern/libmv/libmv/simple_pipeline/reconstruction.cc b/intern/libmv/libmv/simple_pipeline/reconstruction.cc
index 65e5dd27d5d..851eedb5bb1 100644
--- a/intern/libmv/libmv/simple_pipeline/reconstruction.cc
+++ b/intern/libmv/libmv/simple_pipeline/reconstruction.cc
@@ -27,14 +27,14 @@ namespace libmv {
EuclideanReconstruction::EuclideanReconstruction() {}
EuclideanReconstruction::EuclideanReconstruction(
const EuclideanReconstruction &other) {
- cameras_ = other.cameras_;
+ image_to_cameras_map_ = other.image_to_cameras_map_;
points_ = other.points_;
}
EuclideanReconstruction &EuclideanReconstruction::operator=(
const EuclideanReconstruction &other) {
if (&other != this) {
- cameras_ = other.cameras_;
+ image_to_cameras_map_ = other.image_to_cameras_map_;
points_ = other.points_;
}
return *this;
@@ -44,12 +44,13 @@ void EuclideanReconstruction::InsertCamera(int image,
const Mat3 &R,
const Vec3 &t) {
LG << "InsertCamera " << image << ":\nR:\n"<< R << "\nt:\n" << t;
- if (image >= cameras_.size()) {
- cameras_.resize(image + 1);
- }
- cameras_[image].image = image;
- cameras_[image].R = R;
- cameras_[image].t = t;
+
+ EuclideanCamera camera;
+ camera.image = image;
+ camera.R = R;
+ camera.t = t;
+
+ image_to_cameras_map_.insert(make_pair(image, camera));
}
void EuclideanReconstruction::InsertPoint(int track, const Vec3 &X) {
@@ -69,22 +70,18 @@ EuclideanCamera *EuclideanReconstruction::CameraForImage(int image) {
const EuclideanCamera *EuclideanReconstruction::CameraForImage(
int image) const {
- if (image < 0 || image >= cameras_.size()) {
+ ImageToCameraMap::const_iterator it = image_to_cameras_map_.find(image);
+ if (it == image_to_cameras_map_.end()) {
return NULL;
}
- const EuclideanCamera *camera = &cameras_[image];
- if (camera->image == -1) {
- return NULL;
- }
- return camera;
+ return &it->second;
}
vector<EuclideanCamera> EuclideanReconstruction::AllCameras() const {
vector<EuclideanCamera> cameras;
- for (int i = 0; i < cameras_.size(); ++i) {
- if (cameras_[i].image != -1) {
- cameras.push_back(cameras_[i]);
- }
+ for (const ImageToCameraMap::value_type& image_and_camera :
+ image_to_cameras_map_) {
+ cameras.push_back(image_and_camera.second);
}
return cameras;
}
@@ -115,14 +112,14 @@ vector<EuclideanPoint> EuclideanReconstruction::AllPoints() const {
return points;
}
-void ProjectiveReconstruction::InsertCamera(int image,
- const Mat34 &P) {
+void ProjectiveReconstruction::InsertCamera(int image, const Mat34 &P) {
LG << "InsertCamera " << image << ":\nP:\n"<< P;
- if (image >= cameras_.size()) {
- cameras_.resize(image + 1);
- }
- cameras_[image].image = image;
- cameras_[image].P = P;
+
+ ProjectiveCamera camera;
+ camera.image = image;
+ camera.P = P;
+
+ image_to_cameras_map_.insert(make_pair(image, camera));
}
void ProjectiveReconstruction::InsertPoint(int track, const Vec4 &X) {
@@ -142,22 +139,18 @@ ProjectiveCamera *ProjectiveReconstruction::CameraForImage(int image) {
const ProjectiveCamera *ProjectiveReconstruction::CameraForImage(
int image) const {
- if (image < 0 || image >= cameras_.size()) {
- return NULL;
+ ImageToCameraMap::const_iterator it = image_to_cameras_map_.find(image);
+ if (it == image_to_cameras_map_.end()) {
+ return NULL;
}
- const ProjectiveCamera *camera = &cameras_[image];
- if (camera->image == -1) {
- return NULL;
- }
- return camera;
+ return &it->second;
}
vector<ProjectiveCamera> ProjectiveReconstruction::AllCameras() const {
vector<ProjectiveCamera> cameras;
- for (int i = 0; i < cameras_.size(); ++i) {
- if (cameras_[i].image != -1) {
- cameras.push_back(cameras_[i]);
- }
+ for (const ImageToCameraMap::value_type& image_and_camera :
+ image_to_cameras_map_) {
+ cameras.push_back(image_and_camera.second);
}
return cameras;
}
diff --git a/intern/libmv/libmv/simple_pipeline/reconstruction.h b/intern/libmv/libmv/simple_pipeline/reconstruction.h
index 947a0636476..544aeac042e 100644
--- a/intern/libmv/libmv/simple_pipeline/reconstruction.h
+++ b/intern/libmv/libmv/simple_pipeline/reconstruction.h
@@ -22,6 +22,7 @@
#define LIBMV_SIMPLE_PIPELINE_RECONSTRUCTION_H_
#include "libmv/base/vector.h"
+#include "libmv/base/map.h"
#include "libmv/numeric/numeric.h"
namespace libmv {
@@ -29,7 +30,7 @@ namespace libmv {
/*!
A EuclideanCamera is the location and rotation of the camera viewing \a image.
- \a image identify which image from \l Tracks this camera represents.
+ \a image identify which image from \link Tracks this camera represents.
\a R is a 3x3 matrix representing the rotation of the camera.
\a t is a translation vector representing its positions.
@@ -47,7 +48,7 @@ struct EuclideanCamera {
/*!
A Point is the 3D location of a track.
- \a track identify which track from \l Tracks this point corresponds to.
+ \a track identify which track from \link Tracks this point corresponds to.
\a X represents the 3D position of the track.
\sa Reconstruction
@@ -89,7 +90,7 @@ class EuclideanReconstruction {
\a image is the key used to retrieve the cameras with the other methods
in this class.
- \note You should use the same \a image identifier as in \l Tracks.
+ \note You should use the same \a image identifier as in \link Tracks.
*/
void InsertCamera(int image, const Mat3 &R, const Vec3 &t);
@@ -101,7 +102,7 @@ class EuclideanReconstruction {
\a track is the key used to retrieve the points with the
other methods in this class.
- \note You should use the same \a track identifier as in \l Tracks.
+ \note You should use the same \a track identifier as in \link Tracks.
*/
void InsertPoint(int track, const Vec3 &X);
@@ -120,14 +121,18 @@ class EuclideanReconstruction {
vector<EuclideanPoint> AllPoints() const;
private:
- vector<EuclideanCamera> cameras_;
+ // Indexed by frame number.
+ typedef map<int, EuclideanCamera> ImageToCameraMap;
+ ImageToCameraMap image_to_cameras_map_;
+
+ // Insxed by track.
vector<EuclideanPoint> points_;
};
/*!
A ProjectiveCamera is the projection matrix for the camera of \a image.
- \a image identify which image from \l Tracks this camera represents.
+ \a image identify which image from \link Tracks this camera represents.
\a P is the 3x4 projection matrix.
\sa ProjectiveReconstruction
@@ -143,7 +148,7 @@ struct ProjectiveCamera {
/*!
A Point is the 3D location of a track.
- \a track identifies which track from \l Tracks this point corresponds to.
+ \a track identifies which track from \link Tracks this point corresponds to.
\a X is the homogeneous 3D position of the track.
\sa Reconstruction
@@ -177,7 +182,7 @@ class ProjectiveReconstruction {
\a image is the key used to retrieve the cameras with the other methods
in this class.
- \note You should use the same \a image identifier as in \l Tracks.
+ \note You should use the same \a image identifier as in \link Tracks.
*/
void InsertCamera(int image, const Mat34 &P);
@@ -189,7 +194,7 @@ class ProjectiveReconstruction {
\a track is the key used to retrieve the points with the
other methods in this class.
- \note You should use the same \a track identifier as in \l Tracks.
+ \note You should use the same \a track identifier as in \link Tracks.
*/
void InsertPoint(int track, const Vec4 &X);
@@ -208,7 +213,11 @@ class ProjectiveReconstruction {
vector<ProjectivePoint> AllPoints() const;
private:
- vector<ProjectiveCamera> cameras_;
+ // Indexed by frame number.
+ typedef map<int, ProjectiveCamera> ImageToCameraMap;
+ ImageToCameraMap image_to_cameras_map_;
+
+ // Indexed by track.
vector<ProjectivePoint> points_;
};
diff --git a/intern/libmv/libmv/simple_pipeline/resect.h b/intern/libmv/libmv/simple_pipeline/resect.h
index 7ca3237437e..f13d2e2d425 100644
--- a/intern/libmv/libmv/simple_pipeline/resect.h
+++ b/intern/libmv/libmv/simple_pipeline/resect.h
@@ -35,7 +35,7 @@ namespace libmv {
reconstruction object, and solves for the pose and orientation of the
camera for that frame.
- \a markers should contain \l Marker markers \endlink belonging to tracks
+ \a markers should contain \link Marker markers \endlink belonging to tracks
visible in the one frame to be resectioned. Each of the tracks associated
with the markers must have a corresponding reconstructed 3D position in the
\a *reconstruction object.
@@ -62,7 +62,7 @@ bool EuclideanResect(const vector<Marker> &markers,
frame in the reconstruction object, and solves for the projective matrix of
the camera for that frame.
- \a markers should contain \l Marker markers \endlink belonging to tracks
+ \a markers should contain \link Marker markers \endlink belonging to tracks
visible in the one frame to be resectioned. Each of the tracks associated
with the markers must have a corresponding reconstructed homogeneous 3D
position in the \a *reconstruction object.
diff --git a/intern/libmv/libmv/simple_pipeline/tracks.h b/intern/libmv/libmv/simple_pipeline/tracks.h
index a54a43659b7..752d2790a1c 100644
--- a/intern/libmv/libmv/simple_pipeline/tracks.h
+++ b/intern/libmv/libmv/simple_pipeline/tracks.h
@@ -36,7 +36,7 @@ namespace libmv {
\a weight is used by bundle adjustment and weight means how much the
track affects on a final solution.
- \note Markers are typically aggregated with the help of the \l Tracks class.
+ \note Markers are typically aggregated with the help of the \link Tracks class.
\sa Tracks
*/
@@ -56,7 +56,7 @@ struct Marker {
images, which must get created before any 3D reconstruction can take place.
The container has several fast lookups for queries typically needed for
- structure from motion algorithms, such as \l MarkersForTracksInBothImages().
+ structure from motion algorithms, such as \link MarkersForTracksInBothImages().
\sa Marker
*/
@@ -81,7 +81,7 @@ class Tracks {
\a weight is used by bundle adjustment and weight means how much the
track affects on a final solution.
- \note To get an identifier for a new track, use \l MaxTrack() + 1.
+ \note To get an identifier for a new track, use \link MaxTrack() + 1.
*/
// TODO(sergey): Consider using InsetWeightedMarker istead of using
// stupid default value?
diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp
index e6da083f3e5..95013958561 100644
--- a/intern/mantaflow/intern/MANTA_main.cpp
+++ b/intern/mantaflow/intern/MANTA_main.cpp
@@ -48,7 +48,16 @@
#include "MEM_guardedalloc.h"
-std::atomic<int> MANTA::solverID(0);
+using std::cerr;
+using std::cout;
+using std::endl;
+using std::ifstream;
+using std::istringstream;
+using std::ofstream;
+using std::ostringstream;
+using std::to_string;
+
+atomic<int> MANTA::solverID(0);
int MANTA::with_debug(0);
/* Number of particles that the cache reads at once (with zlib). */
@@ -61,30 +70,31 @@ int MANTA::with_debug(0);
MANTA::MANTA(int *res, FluidModifierData *mmd) : mCurrentID(++solverID)
{
if (with_debug)
- std::cout << "FLUID: " << mCurrentID << " with res(" << res[0] << ", " << res[1] << ", "
- << res[2] << ")" << std::endl;
-
- mmd->domain->fluid = this;
-
- mUsingLiquid = (mmd->domain->type == FLUID_DOMAIN_TYPE_LIQUID);
- mUsingSmoke = (mmd->domain->type == FLUID_DOMAIN_TYPE_GAS);
- mUsingNoise = (mmd->domain->flags & FLUID_DOMAIN_USE_NOISE) && mUsingSmoke;
- mUsingFractions = (mmd->domain->flags & FLUID_DOMAIN_USE_FRACTIONS) && mUsingLiquid;
- mUsingMesh = (mmd->domain->flags & FLUID_DOMAIN_USE_MESH) && mUsingLiquid;
- mUsingDiffusion = (mmd->domain->flags & FLUID_DOMAIN_USE_DIFFUSION) && mUsingLiquid;
- mUsingMVel = (mmd->domain->flags & FLUID_DOMAIN_USE_SPEED_VECTORS) && mUsingLiquid;
- mUsingGuiding = (mmd->domain->flags & FLUID_DOMAIN_USE_GUIDE);
- mUsingDrops = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) && mUsingLiquid;
- mUsingBubbles = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) && mUsingLiquid;
- mUsingFloats = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) && mUsingLiquid;
- mUsingTracers = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_TRACER) && mUsingLiquid;
-
- mUsingHeat = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_HEAT) && mUsingSmoke;
- mUsingFire = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_FIRE) && mUsingSmoke;
- mUsingColors = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) && mUsingSmoke;
- mUsingObstacle = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE);
- mUsingInvel = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL);
- mUsingOutflow = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW);
+ cout << "FLUID: " << mCurrentID << " with res(" << res[0] << ", " << res[1] << ", " << res[2]
+ << ")" << endl;
+
+ FluidDomainSettings *mds = mmd->domain;
+ mds->fluid = this;
+
+ mUsingLiquid = (mds->type == FLUID_DOMAIN_TYPE_LIQUID);
+ mUsingSmoke = (mds->type == FLUID_DOMAIN_TYPE_GAS);
+ mUsingNoise = (mds->flags & FLUID_DOMAIN_USE_NOISE) && mUsingSmoke;
+ mUsingFractions = (mds->flags & FLUID_DOMAIN_USE_FRACTIONS) && mUsingLiquid;
+ mUsingMesh = (mds->flags & FLUID_DOMAIN_USE_MESH) && mUsingLiquid;
+ mUsingDiffusion = (mds->flags & FLUID_DOMAIN_USE_DIFFUSION) && mUsingLiquid;
+ mUsingMVel = (mds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS) && mUsingLiquid;
+ mUsingGuiding = (mds->flags & FLUID_DOMAIN_USE_GUIDE);
+ mUsingDrops = (mds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) && mUsingLiquid;
+ mUsingBubbles = (mds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) && mUsingLiquid;
+ mUsingFloats = (mds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) && mUsingLiquid;
+ mUsingTracers = (mds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER) && mUsingLiquid;
+
+ mUsingHeat = (mds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT) && mUsingSmoke;
+ mUsingFire = (mds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE) && mUsingSmoke;
+ mUsingColors = (mds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) && mUsingSmoke;
+ mUsingObstacle = (mds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE);
+ mUsingInvel = (mds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL);
+ mUsingOutflow = (mds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW);
// Simulation constants
mTempAmb = 0; // TODO: Maybe use this later for buoyancy calculation
@@ -92,10 +102,8 @@ MANTA::MANTA(int *res, FluidModifierData *mmd) : mCurrentID(++solverID)
mResY = res[1];
mResZ = res[2];
mMaxRes = MAX3(mResX, mResY, mResZ);
- mConstantScaling = 64.0f / mMaxRes;
- mConstantScaling = (mConstantScaling < 1.0f) ? 1.0f : mConstantScaling;
mTotalCells = mResX * mResY * mResZ;
- mResGuiding = mmd->domain->res;
+ mResGuiding = mds->res;
// Smoke low res grids
mDensity = nullptr;
@@ -185,90 +193,93 @@ MANTA::MANTA(int *res, FluidModifierData *mmd) : mCurrentID(++solverID)
// Setup Mantaflow in Python
initializeMantaflow();
+ // Initializa RNA map with values that Python will need
+ initializeRNAMap(mmd);
+
// Initialize Mantaflow variables in Python
// Liquid
if (mUsingLiquid) {
- initDomain(mmd);
- initLiquid(mmd);
+ initDomain();
+ initLiquid();
if (mUsingObstacle)
- initObstacle(mmd);
+ initObstacle();
if (mUsingInvel)
- initInVelocity(mmd);
+ initInVelocity();
if (mUsingOutflow)
- initOutflow(mmd);
+ initOutflow();
if (mUsingDrops || mUsingBubbles || mUsingFloats || mUsingTracers) {
- mUpresParticle = mmd->domain->particle_scale;
+ mUpresParticle = mds->particle_scale;
mResXParticle = mUpresParticle * mResX;
mResYParticle = mUpresParticle * mResY;
mResZParticle = mUpresParticle * mResZ;
mTotalCellsParticles = mResXParticle * mResYParticle * mResZParticle;
- initSndParts(mmd);
- initLiquidSndParts(mmd);
+ initSndParts();
+ initLiquidSndParts();
}
if (mUsingMesh) {
- mUpresMesh = mmd->domain->mesh_scale;
+ mUpresMesh = mds->mesh_scale;
mResXMesh = mUpresMesh * mResX;
mResYMesh = mUpresMesh * mResY;
mResZMesh = mUpresMesh * mResZ;
mTotalCellsMesh = mResXMesh * mResYMesh * mResZMesh;
// Initialize Mantaflow variables in Python
- initMesh(mmd);
- initLiquidMesh(mmd);
+ initMesh();
+ initLiquidMesh();
}
if (mUsingDiffusion) {
- initCurvature(mmd);
+ initCurvature();
}
if (mUsingGuiding) {
- mResGuiding = (mmd->domain->guide_parent) ? mmd->domain->guide_res : mmd->domain->res;
- initGuiding(mmd);
+ mResGuiding = (mds->guide_parent) ? mds->guide_res : mds->res;
+ initGuiding();
}
if (mUsingFractions) {
- initFractions(mmd);
+ initFractions();
}
}
// Smoke
if (mUsingSmoke) {
- initDomain(mmd);
- initSmoke(mmd);
+ initDomain();
+ initSmoke();
if (mUsingHeat)
- initHeat(mmd);
+ initHeat();
if (mUsingFire)
- initFire(mmd);
+ initFire();
if (mUsingColors)
- initColors(mmd);
+ initColors();
if (mUsingObstacle)
- initObstacle(mmd);
+ initObstacle();
if (mUsingInvel)
- initInVelocity(mmd);
+ initInVelocity();
if (mUsingOutflow)
- initOutflow(mmd);
+ initOutflow();
if (mUsingGuiding) {
- mResGuiding = (mmd->domain->guide_parent) ? mmd->domain->guide_res : mmd->domain->res;
- initGuiding(mmd);
+ mResGuiding = (mds->guide_parent) ? mds->guide_res : mds->res;
+ initGuiding();
}
if (mUsingNoise) {
- int amplify = mmd->domain->noise_scale;
+ int amplify = mds->noise_scale;
mResXNoise = amplify * mResX;
mResYNoise = amplify * mResY;
mResZNoise = amplify * mResZ;
mTotalCellsHigh = mResXNoise * mResYNoise * mResZNoise;
// Initialize Mantaflow variables in Python
- initNoise(mmd);
- initSmokeNoise(mmd);
+ initNoise();
+ initSmokeNoise();
if (mUsingFire)
- initFireHigh(mmd);
+ initFireHigh();
if (mUsingColors)
- initColorsHigh(mmd);
+ initColorsHigh();
}
}
updatePointers();
@@ -277,32 +288,32 @@ MANTA::MANTA(int *res, FluidModifierData *mmd) : mCurrentID(++solverID)
void MANTA::initDomain(FluidModifierData *mmd)
{
// Vector will hold all python commands that are to be executed
- std::vector<std::string> pythonCommands;
+ vector<string> pythonCommands;
// Set manta debug level first
pythonCommands.push_back(manta_import + manta_debuglevel);
- std::ostringstream ss;
+ ostringstream ss;
ss << "set_manta_debuglevel(" << with_debug << ")";
pythonCommands.push_back(ss.str());
// Now init basic fluid domain
- std::string tmpString = fluid_variables + fluid_solver + fluid_alloc + fluid_cache_helper +
- fluid_bake_multiprocessing + fluid_bake_data + fluid_bake_noise +
- fluid_bake_mesh + fluid_bake_particles + fluid_bake_guiding +
- fluid_file_import + fluid_file_export + fluid_save_data +
- fluid_load_data + fluid_pre_step + fluid_post_step +
- fluid_adapt_time_step + fluid_time_stepping;
- std::string finalString = parseScript(tmpString, mmd);
+ string tmpString = fluid_variables + fluid_solver + fluid_alloc + fluid_cache_helper +
+ fluid_bake_multiprocessing + fluid_bake_data + fluid_bake_noise +
+ fluid_bake_mesh + fluid_bake_particles + fluid_bake_guiding +
+ fluid_file_import + fluid_file_export + fluid_save_data + fluid_load_data +
+ fluid_pre_step + fluid_post_step + fluid_adapt_time_step +
+ fluid_time_stepping;
+ string finalString = parseScript(tmpString, mmd);
pythonCommands.push_back(finalString);
runPythonString(pythonCommands);
}
void MANTA::initNoise(FluidModifierData *mmd)
{
- std::vector<std::string> pythonCommands;
- std::string tmpString = fluid_variables_noise + fluid_solver_noise;
- std::string finalString = parseScript(tmpString, mmd);
+ vector<string> pythonCommands;
+ string tmpString = fluid_variables_noise + fluid_solver_noise;
+ string finalString = parseScript(tmpString, mmd);
pythonCommands.push_back(finalString);
runPythonString(pythonCommands);
@@ -310,10 +321,10 @@ void MANTA::initNoise(FluidModifierData *mmd)
void MANTA::initSmoke(FluidModifierData *mmd)
{
- std::vector<std::string> pythonCommands;
- std::string tmpString = smoke_variables + smoke_alloc + smoke_adaptive_step + smoke_save_data +
- smoke_load_data + smoke_step;
- std::string finalString = parseScript(tmpString, mmd);
+ vector<string> pythonCommands;
+ string tmpString = smoke_variables + smoke_alloc + smoke_adaptive_step + smoke_save_data +
+ smoke_load_data + smoke_step;
+ string finalString = parseScript(tmpString, mmd);
pythonCommands.push_back(finalString);
runPythonString(pythonCommands);
@@ -321,10 +332,10 @@ void MANTA::initSmoke(FluidModifierData *mmd)
void MANTA::initSmokeNoise(FluidModifierData *mmd)
{
- std::vector<std::string> pythonCommands;
- std::string tmpString = smoke_variables_noise + smoke_alloc_noise + smoke_wavelet_noise +
- smoke_save_noise + smoke_load_noise + smoke_step_noise;
- std::string finalString = parseScript(tmpString, mmd);
+ vector<string> pythonCommands;
+ string tmpString = smoke_variables_noise + smoke_alloc_noise + smoke_wavelet_noise +
+ smoke_save_noise + smoke_load_noise + smoke_step_noise;
+ string finalString = parseScript(tmpString, mmd);
pythonCommands.push_back(finalString);
runPythonString(pythonCommands);
@@ -334,9 +345,9 @@ void MANTA::initSmokeNoise(FluidModifierData *mmd)
void MANTA::initHeat(FluidModifierData *mmd)
{
if (!mHeat) {
- std::vector<std::string> pythonCommands;
- std::string tmpString = smoke_alloc_heat + smoke_with_heat;
- std::string finalString = parseScript(tmpString, mmd);
+ vector<string> pythonCommands;
+ string tmpString = smoke_alloc_heat + smoke_with_heat;
+ string finalString = parseScript(tmpString, mmd);
pythonCommands.push_back(finalString);
runPythonString(pythonCommands);
@@ -347,9 +358,9 @@ void MANTA::initHeat(FluidModifierData *mmd)
void MANTA::initFire(FluidModifierData *mmd)
{
if (!mFuel) {
- std::vector<std::string> pythonCommands;
- std::string tmpString = smoke_alloc_fire + smoke_with_fire;
- std::string finalString = parseScript(tmpString, mmd);
+ vector<string> pythonCommands;
+ string tmpString = smoke_alloc_fire + smoke_with_fire;
+ string finalString = parseScript(tmpString, mmd);
pythonCommands.push_back(finalString);
runPythonString(pythonCommands);
@@ -360,9 +371,9 @@ void MANTA::initFire(FluidModifierData *mmd)
void MANTA::initFireHigh(FluidModifierData *mmd)
{
if (!mFuelHigh) {
- std::vector<std::string> pythonCommands;
- std::string tmpString = smoke_alloc_fire_noise + smoke_with_fire;
- std::string finalString = parseScript(tmpString, mmd);
+ vector<string> pythonCommands;
+ string tmpString = smoke_alloc_fire_noise + smoke_with_fire;
+ string finalString = parseScript(tmpString, mmd);
pythonCommands.push_back(finalString);
runPythonString(pythonCommands);
@@ -373,9 +384,9 @@ void MANTA::initFireHigh(FluidModifierData *mmd)
void MANTA::initColors(FluidModifierData *mmd)
{
if (!mColorR) {
- std::vector<std::string> pythonCommands;
- std::string tmpString = smoke_alloc_colors + smoke_init_colors + smoke_with_colors;
- std::string finalString = parseScript(tmpString, mmd);
+ vector<string> pythonCommands;
+ string tmpString = smoke_alloc_colors + smoke_init_colors + smoke_with_colors;
+ string finalString = parseScript(tmpString, mmd);
pythonCommands.push_back(finalString);
runPythonString(pythonCommands);
@@ -386,9 +397,9 @@ void MANTA::initColors(FluidModifierData *mmd)
void MANTA::initColorsHigh(FluidModifierData *mmd)
{
if (!mColorRHigh) {
- std::vector<std::string> pythonCommands;
- std::string tmpString = smoke_alloc_colors_noise + smoke_init_colors_noise + smoke_with_colors;
- std::string finalString = parseScript(tmpString, mmd);
+ vector<string> pythonCommands;
+ string tmpString = smoke_alloc_colors_noise + smoke_init_colors_noise + smoke_with_colors;
+ string finalString = parseScript(tmpString, mmd);
pythonCommands.push_back(finalString);
runPythonString(pythonCommands);
@@ -399,10 +410,10 @@ void MANTA::initColorsHigh(FluidModifierData *mmd)
void MANTA::initLiquid(FluidModifierData *mmd)
{
if (!mPhiIn) {
- std::vector<std::string> pythonCommands;
- std::string tmpString = liquid_variables + liquid_alloc + liquid_init_phi + liquid_save_data +
- liquid_load_data + liquid_adaptive_step + liquid_step;
- std::string finalString = parseScript(tmpString, mmd);
+ vector<string> pythonCommands;
+ string tmpString = liquid_variables + liquid_alloc + liquid_init_phi + liquid_save_data +
+ liquid_load_data + liquid_adaptive_step + liquid_step;
+ string finalString = parseScript(tmpString, mmd);
pythonCommands.push_back(finalString);
runPythonString(pythonCommands);
@@ -412,9 +423,9 @@ void MANTA::initLiquid(FluidModifierData *mmd)
void MANTA::initMesh(FluidModifierData *mmd)
{
- std::vector<std::string> pythonCommands;
- std::string tmpString = fluid_variables_mesh + fluid_solver_mesh + liquid_load_mesh;
- std::string finalString = parseScript(tmpString, mmd);
+ vector<string> pythonCommands;
+ string tmpString = fluid_variables_mesh + fluid_solver_mesh + liquid_load_mesh;
+ string finalString = parseScript(tmpString, mmd);
pythonCommands.push_back(finalString);
runPythonString(pythonCommands);
@@ -423,9 +434,9 @@ void MANTA::initMesh(FluidModifierData *mmd)
void MANTA::initLiquidMesh(FluidModifierData *mmd)
{
- std::vector<std::string> pythonCommands;
- std::string tmpString = liquid_alloc_mesh + liquid_step_mesh + liquid_save_mesh;
- std::string finalString = parseScript(tmpString, mmd);
+ vector<string> pythonCommands;
+ string tmpString = liquid_alloc_mesh + liquid_step_mesh + liquid_save_mesh;
+ string finalString = parseScript(tmpString, mmd);
pythonCommands.push_back(finalString);
runPythonString(pythonCommands);
@@ -445,9 +456,9 @@ void MANTA::initCurvature(FluidModifierData *mmd)
void MANTA::initObstacle(FluidModifierData *mmd)
{
if (!mPhiObsIn) {
- std::vector<std::string> pythonCommands;
- std::string tmpString = fluid_alloc_obstacle + fluid_with_obstacle;
- std::string finalString = parseScript(tmpString, mmd);
+ vector<string> pythonCommands;
+ string tmpString = fluid_alloc_obstacle + fluid_with_obstacle;
+ string finalString = parseScript(tmpString, mmd);
pythonCommands.push_back(finalString);
runPythonString(pythonCommands);
@@ -458,10 +469,10 @@ void MANTA::initObstacle(FluidModifierData *mmd)
void MANTA::initGuiding(FluidModifierData *mmd)
{
if (!mPhiGuideIn) {
- std::vector<std::string> pythonCommands;
- std::string tmpString = fluid_variables_guiding + fluid_solver_guiding + fluid_alloc_guiding +
- fluid_save_guiding + fluid_load_vel + fluid_load_guiding;
- std::string finalString = parseScript(tmpString, mmd);
+ vector<string> pythonCommands;
+ string tmpString = fluid_variables_guiding + fluid_solver_guiding + fluid_alloc_guiding +
+ fluid_save_guiding + fluid_load_vel + fluid_load_guiding;
+ string finalString = parseScript(tmpString, mmd);
pythonCommands.push_back(finalString);
runPythonString(pythonCommands);
@@ -471,9 +482,9 @@ void MANTA::initGuiding(FluidModifierData *mmd)
void MANTA::initFractions(FluidModifierData *mmd)
{
- std::vector<std::string> pythonCommands;
- std::string tmpString = fluid_alloc_fractions + fluid_with_fractions;
- std::string finalString = parseScript(tmpString, mmd);
+ vector<string> pythonCommands;
+ string tmpString = fluid_alloc_fractions + fluid_with_fractions;
+ string finalString = parseScript(tmpString, mmd);
pythonCommands.push_back(finalString);
runPythonString(pythonCommands);
@@ -483,9 +494,9 @@ void MANTA::initFractions(FluidModifierData *mmd)
void MANTA::initInVelocity(FluidModifierData *mmd)
{
if (!mInVelocityX) {
- std::vector<std::string> pythonCommands;
- std::string tmpString = fluid_alloc_invel + fluid_with_invel;
- std::string finalString = parseScript(tmpString, mmd);
+ vector<string> pythonCommands;
+ string tmpString = fluid_alloc_invel + fluid_with_invel;
+ string finalString = parseScript(tmpString, mmd);
pythonCommands.push_back(finalString);
runPythonString(pythonCommands);
@@ -496,9 +507,9 @@ void MANTA::initInVelocity(FluidModifierData *mmd)
void MANTA::initOutflow(FluidModifierData *mmd)
{
if (!mPhiOutIn) {
- std::vector<std::string> pythonCommands;
- std::string tmpString = fluid_alloc_outflow + fluid_with_outflow;
- std::string finalString = parseScript(tmpString, mmd);
+ vector<string> pythonCommands;
+ string tmpString = fluid_alloc_outflow + fluid_with_outflow;
+ string finalString = parseScript(tmpString, mmd);
pythonCommands.push_back(finalString);
runPythonString(pythonCommands);
@@ -508,9 +519,9 @@ void MANTA::initOutflow(FluidModifierData *mmd)
void MANTA::initSndParts(FluidModifierData *mmd)
{
- std::vector<std::string> pythonCommands;
- std::string tmpString = fluid_variables_particles + fluid_solver_particles;
- std::string finalString = parseScript(tmpString, mmd);
+ vector<string> pythonCommands;
+ string tmpString = fluid_variables_particles + fluid_solver_particles;
+ string finalString = parseScript(tmpString, mmd);
pythonCommands.push_back(finalString);
runPythonString(pythonCommands);
@@ -519,11 +530,11 @@ void MANTA::initSndParts(FluidModifierData *mmd)
void MANTA::initLiquidSndParts(FluidModifierData *mmd)
{
if (!mSndParticleData) {
- std::vector<std::string> pythonCommands;
- std::string tmpString = liquid_alloc_particles + liquid_variables_particles +
- liquid_step_particles + fluid_with_sndparts + liquid_load_particles +
- liquid_save_particles;
- std::string finalString = parseScript(tmpString, mmd);
+ vector<string> pythonCommands;
+ string tmpString = liquid_alloc_particles + liquid_variables_particles +
+ liquid_step_particles + fluid_with_sndparts + liquid_load_particles +
+ liquid_save_particles;
+ string finalString = parseScript(tmpString, mmd);
pythonCommands.push_back(finalString);
runPythonString(pythonCommands);
@@ -533,24 +544,27 @@ void MANTA::initLiquidSndParts(FluidModifierData *mmd)
MANTA::~MANTA()
{
if (with_debug)
- std::cout << "~FLUID: " << mCurrentID << " with res(" << mResX << ", " << mResY << ", "
- << mResZ << ")" << std::endl;
+ cout << "~FLUID: " << mCurrentID << " with res(" << mResX << ", " << mResY << ", " << mResZ
+ << ")" << endl;
// Destruction string for Python
- std::string tmpString = "";
- std::vector<std::string> pythonCommands;
+ string tmpString = "";
+ vector<string> pythonCommands;
bool result = false;
tmpString += manta_import;
tmpString += fluid_delete_all;
+ // Initializa RNA map with values that Python will need
+ initializeRNAMap();
+
// Leave out mmd argument in parseScript since only looking up IDs
- std::string finalString = parseScript(tmpString);
+ string finalString = parseScript(tmpString);
pythonCommands.push_back(finalString);
result = runPythonString(pythonCommands);
assert(result);
- (void)result; // not needed in release
+ UNUSED_VARS(result);
}
/**
@@ -566,7 +580,7 @@ MANTA::~MANTA()
*/
static PyObject *manta_main_module = nullptr;
-bool MANTA::runPythonString(std::vector<std::string> commands)
+bool MANTA::runPythonString(vector<string> commands)
{
bool success = true;
PyGILState_STATE gilstate = PyGILState_Ensure();
@@ -575,8 +589,8 @@ bool MANTA::runPythonString(std::vector<std::string> commands)
manta_main_module = PyImport_ImportModule("__main__");
}
- for (std::vector<std::string>::iterator it = commands.begin(); it != commands.end(); ++it) {
- std::string command = *it;
+ for (vector<string>::iterator it = commands.begin(); it != commands.end(); ++it) {
+ string command = *it;
PyObject *globals_dict = PyModule_GetDict(manta_main_module);
PyObject *return_value = PyRun_String(
@@ -601,10 +615,10 @@ bool MANTA::runPythonString(std::vector<std::string> commands)
void MANTA::initializeMantaflow()
{
if (with_debug)
- std::cout << "Fluid: Initializing Mantaflow framework" << std::endl;
+ cout << "Fluid: Initializing Mantaflow framework" << endl;
- std::string filename = "manta_scene_" + std::to_string(mCurrentID) + ".py";
- std::vector<std::string> fill = std::vector<std::string>();
+ string filename = "manta_scene_" + to_string(mCurrentID) + ".py";
+ vector<string> fill = vector<string>();
// Initialize extension classes and wrappers
srand(0);
@@ -616,17 +630,17 @@ void MANTA::initializeMantaflow()
void MANTA::terminateMantaflow()
{
if (with_debug)
- std::cout << "Fluid: Releasing Mantaflow framework" << std::endl;
+ cout << "Fluid: Releasing Mantaflow framework" << endl;
PyGILState_STATE gilstate = PyGILState_Ensure();
Pb::finalize(); // Namespace from Mantaflow (registry)
PyGILState_Release(gilstate);
}
-static std::string getCacheFileEnding(char cache_format)
+static string getCacheFileEnding(char cache_format)
{
if (MANTA::with_debug)
- std::cout << "MANTA::getCacheFileEnding()" << std::endl;
+ cout << "MANTA::getCacheFileEnding()" << endl;
switch (cache_format) {
case FLUID_DOMAIN_FILE_UNI:
@@ -640,409 +654,254 @@ static std::string getCacheFileEnding(char cache_format)
case FLUID_DOMAIN_FILE_OBJECT:
return FLUID_DOMAIN_EXTENSION_OBJ;
default:
- std::cerr << "Fluid Error -- Could not find file extension. Using default file extension."
- << std::endl;
+ cerr << "Fluid Error -- Could not find file extension. Using default file extension."
+ << endl;
return FLUID_DOMAIN_EXTENSION_UNI;
}
}
-std::string MANTA::getRealValue(const std::string &varName, FluidModifierData *mmd)
+static string getBooleanString(int value)
{
- std::ostringstream ss;
- bool is2D = false;
- int tmpVar;
- float tmpFloat;
+ return (value) ? "True" : "False";
+}
- if (varName == "ID") {
- ss << mCurrentID;
- return ss.str();
- }
+void MANTA::initializeRNAMap(FluidModifierData *mmd)
+{
+ if (with_debug)
+ cout << "MANTA::initializeRNAMap()" << endl;
+
+ mRNAMap["ID"] = to_string(mCurrentID);
if (!mmd) {
- std::cerr << "Fluid Error -- Invalid modifier data." << std::endl;
- ss << "ERROR - INVALID MODIFIER DATA";
- return ss.str();
- }
-
- is2D = (mmd->domain->solver_res == 2);
-
- if (varName == "USING_SMOKE")
- ss << ((mmd->domain->type == FLUID_DOMAIN_TYPE_GAS) ? "True" : "False");
- else if (varName == "USING_LIQUID")
- ss << ((mmd->domain->type == FLUID_DOMAIN_TYPE_LIQUID) ? "True" : "False");
- else if (varName == "USING_COLORS")
- ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_COLORS ? "True" : "False");
- else if (varName == "USING_HEAT")
- ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_HEAT ? "True" : "False");
- else if (varName == "USING_FIRE")
- ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_FIRE ? "True" : "False");
- else if (varName == "USING_NOISE")
- ss << (mmd->domain->flags & FLUID_DOMAIN_USE_NOISE ? "True" : "False");
- else if (varName == "USING_OBSTACLE")
- ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE ? "True" : "False");
- else if (varName == "USING_GUIDING")
- ss << (mmd->domain->flags & FLUID_DOMAIN_USE_GUIDE ? "True" : "False");
- else if (varName == "USING_INVEL")
- ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL ? "True" : "False");
- else if (varName == "USING_OUTFLOW")
- ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW ? "True" : "False");
- else if (varName == "USING_LOG_DISSOLVE")
- ss << (mmd->domain->flags & FLUID_DOMAIN_USE_DISSOLVE_LOG ? "True" : "False");
- else if (varName == "USING_DISSOLVE")
- ss << (mmd->domain->flags & FLUID_DOMAIN_USE_DISSOLVE ? "True" : "False");
- else if (varName == "SOLVER_DIM")
- ss << mmd->domain->solver_res;
- else if (varName == "DO_OPEN") {
- tmpVar = (FLUID_DOMAIN_BORDER_BACK | FLUID_DOMAIN_BORDER_FRONT | FLUID_DOMAIN_BORDER_LEFT |
- FLUID_DOMAIN_BORDER_RIGHT | FLUID_DOMAIN_BORDER_BOTTOM | FLUID_DOMAIN_BORDER_TOP);
- ss << (((mmd->domain->border_collisions & tmpVar) == tmpVar) ? "False" : "True");
- }
- else if (varName == "BOUND_CONDITIONS") {
- if (mmd->domain->solver_res == 2) {
- if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_LEFT) == 0)
- ss << "x";
- if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_RIGHT) == 0)
- ss << "X";
- if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_FRONT) == 0)
- ss << "y";
- if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_BACK) == 0)
- ss << "Y";
- }
- if (mmd->domain->solver_res == 3) {
- if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_LEFT) == 0)
- ss << "x";
- if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_RIGHT) == 0)
- ss << "X";
- if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_FRONT) == 0)
- ss << "y";
- if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_BACK) == 0)
- ss << "Y";
- if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_BOTTOM) == 0)
- ss << "z";
- if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_TOP) == 0)
- ss << "Z";
- }
- }
- else if (varName == "BOUNDARY_WIDTH")
- ss << mmd->domain->boundary_width;
- else if (varName == "RES")
- ss << mMaxRes;
- else if (varName == "RESX")
- ss << mResX;
- else if (varName == "RESY")
- if (is2D) {
- ss << mResZ;
- }
- else {
- ss << mResY;
- }
- else if (varName == "RESZ") {
- if (is2D) {
- ss << 1;
- }
- else {
- ss << mResZ;
- }
- }
- else if (varName == "FRAME_LENGTH")
- ss << mmd->domain->frame_length;
- else if (varName == "CFL")
- ss << mmd->domain->cfl_condition;
- else if (varName == "DT")
- ss << mmd->domain->dt;
- else if (varName == "TIMESTEPS_MIN")
- ss << mmd->domain->timesteps_minimum;
- else if (varName == "TIMESTEPS_MAX")
- ss << mmd->domain->timesteps_maximum;
- else if (varName == "TIME_TOTAL")
- ss << mmd->domain->time_total;
- else if (varName == "TIME_PER_FRAME")
- ss << mmd->domain->time_per_frame;
- else if (varName == "VORTICITY")
- ss << mmd->domain->vorticity / mConstantScaling;
- else if (varName == "FLAME_VORTICITY")
- ss << mmd->domain->flame_vorticity / mConstantScaling;
- else if (varName == "NOISE_SCALE")
- ss << mmd->domain->noise_scale;
- else if (varName == "MESH_SCALE")
- ss << mmd->domain->mesh_scale;
- else if (varName == "PARTICLE_SCALE")
- ss << mmd->domain->particle_scale;
- else if (varName == "NOISE_RESX")
- ss << mResXNoise;
- else if (varName == "NOISE_RESY") {
- if (is2D) {
- ss << mResZNoise;
- }
- else {
- ss << mResYNoise;
- }
- }
- else if (varName == "NOISE_RESZ") {
- if (is2D) {
- ss << 1;
- }
- else {
- ss << mResZNoise;
- }
- }
- else if (varName == "MESH_RESX")
- ss << mResXMesh;
- else if (varName == "MESH_RESY") {
- if (is2D) {
- ss << mResZMesh;
- }
- else {
- ss << mResYMesh;
- }
- }
- else if (varName == "MESH_RESZ") {
- if (is2D) {
- ss << 1;
- }
- else {
- ss << mResZMesh;
- }
- }
- else if (varName == "PARTICLE_RESX")
- ss << mResXParticle;
- else if (varName == "PARTICLE_RESY") {
- if (is2D) {
- ss << mResZParticle;
- }
- else {
- ss << mResYParticle;
- }
- }
- else if (varName == "PARTICLE_RESZ") {
- if (is2D) {
- ss << 1;
- }
- else {
- ss << mResZParticle;
- }
- }
- else if (varName == "GUIDING_RESX")
- ss << mResGuiding[0];
- else if (varName == "GUIDING_RESY") {
- if (is2D) {
- ss << mResGuiding[2];
- }
- else {
- ss << mResGuiding[1];
- }
+ if (with_debug)
+ cout << "No modifier data given in RNA map setup - returning early" << endl;
+ return;
}
- else if (varName == "GUIDING_RESZ") {
- if (is2D) {
- ss << 1;
- }
- else {
- ss << mResGuiding[2];
- }
+
+ FluidDomainSettings *mds = mmd->domain;
+ bool is2D = (mds->solver_res == 2);
+
+ string borderCollisions = "";
+ if ((mds->border_collisions & FLUID_DOMAIN_BORDER_LEFT) == 0)
+ borderCollisions += "x";
+ if ((mds->border_collisions & FLUID_DOMAIN_BORDER_RIGHT) == 0)
+ borderCollisions += "X";
+ if ((mds->border_collisions & FLUID_DOMAIN_BORDER_FRONT) == 0)
+ borderCollisions += "y";
+ if ((mds->border_collisions & FLUID_DOMAIN_BORDER_BACK) == 0)
+ borderCollisions += "Y";
+ if ((mds->border_collisions & FLUID_DOMAIN_BORDER_BOTTOM) == 0)
+ borderCollisions += "z";
+ if ((mds->border_collisions & FLUID_DOMAIN_BORDER_TOP) == 0)
+ borderCollisions += "Z";
+
+ string simulationMethod = "";
+ if (mds->simulation_method & FLUID_DOMAIN_METHOD_FLIP)
+ simulationMethod += "'FLIP'";
+ else if (mds->simulation_method & FLUID_DOMAIN_METHOD_APIC)
+ simulationMethod += "'APIC'";
+
+ string particleTypesStr = "";
+ if (mds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY)
+ particleTypesStr += "PtypeSpray";
+ if (mds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) {
+ if (!particleTypesStr.empty())
+ particleTypesStr += "|";
+ particleTypesStr += "PtypeBubble";
+ }
+ if (mds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) {
+ if (!particleTypesStr.empty())
+ particleTypesStr += "|";
+ particleTypesStr += "PtypeFoam";
+ }
+ if (mds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER) {
+ if (!particleTypesStr.empty())
+ particleTypesStr += "|";
+ particleTypesStr += "PtypeTracer";
+ }
+ if (particleTypesStr.empty())
+ particleTypesStr = "0";
+
+ int particleTypes = (FLUID_DOMAIN_PARTICLE_SPRAY | FLUID_DOMAIN_PARTICLE_BUBBLE |
+ FLUID_DOMAIN_PARTICLE_FOAM | FLUID_DOMAIN_PARTICLE_TRACER);
+
+ string cacheDirectory(mds->cache_directory);
+
+ float viscosity = mds->viscosity_base * pow(10.0f, -mds->viscosity_exponent);
+ float domainSize = MAX3(mds->global_size[0], mds->global_size[1], mds->global_size[2]);
+
+ mRNAMap["USING_SMOKE"] = getBooleanString(mds->type == FLUID_DOMAIN_TYPE_GAS);
+ mRNAMap["USING_LIQUID"] = getBooleanString(mds->type == FLUID_DOMAIN_TYPE_LIQUID);
+ mRNAMap["USING_COLORS"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS);
+ mRNAMap["USING_HEAT"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT);
+ mRNAMap["USING_FIRE"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE);
+ mRNAMap["USING_NOISE"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_NOISE);
+ mRNAMap["USING_OBSTACLE"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE);
+ mRNAMap["USING_GUIDING"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_GUIDE);
+ mRNAMap["USING_INVEL"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL);
+ mRNAMap["USING_OUTFLOW"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW);
+ mRNAMap["USING_LOG_DISSOLVE"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_DISSOLVE_LOG);
+ mRNAMap["USING_DISSOLVE"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_DISSOLVE);
+ mRNAMap["DO_OPEN"] = getBooleanString(mds->border_collisions == 0);
+ mRNAMap["CACHE_RESUMABLE"] = getBooleanString(mds->cache_type != FLUID_DOMAIN_CACHE_FINAL);
+ mRNAMap["USING_ADAPTIVETIME"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_TIME);
+ mRNAMap["USING_SPEEDVECTORS"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS);
+ mRNAMap["USING_FRACTIONS"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_FRACTIONS);
+ mRNAMap["DELETE_IN_OBSTACLE"] = getBooleanString(mds->flags & FLUID_DOMAIN_DELETE_IN_OBSTACLE);
+ mRNAMap["USING_DIFFUSION"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_DIFFUSION);
+ mRNAMap["USING_MESH"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_MESH);
+ mRNAMap["USING_IMPROVED_MESH"] = getBooleanString(mds->mesh_generator ==
+ FLUID_DOMAIN_MESH_IMPROVED);
+ mRNAMap["USING_SNDPARTS"] = getBooleanString(mds->particle_type & particleTypes);
+ mRNAMap["SNDPARTICLE_BOUNDARY_DELETE"] = getBooleanString(mds->sndparticle_boundary ==
+ SNDPARTICLE_BOUNDARY_DELETE);
+ mRNAMap["SNDPARTICLE_BOUNDARY_PUSHOUT"] = getBooleanString(mds->sndparticle_boundary ==
+ SNDPARTICLE_BOUNDARY_PUSHOUT);
+
+ mRNAMap["SOLVER_DIM"] = to_string(mds->solver_res);
+ mRNAMap["BOUND_CONDITIONS"] = borderCollisions;
+ mRNAMap["BOUNDARY_WIDTH"] = to_string(mds->boundary_width);
+ mRNAMap["RES"] = to_string(mMaxRes);
+ mRNAMap["RESX"] = to_string(mResX);
+ mRNAMap["RESY"] = (is2D) ? to_string(mResZ) : to_string(mResY);
+ mRNAMap["RESZ"] = (is2D) ? to_string(1) : to_string(mResZ);
+ mRNAMap["TIME_SCALE"] = to_string(mds->time_scale);
+ mRNAMap["FRAME_LENGTH"] = to_string(mds->frame_length);
+ mRNAMap["CFL"] = to_string(mds->cfl_condition);
+ mRNAMap["DT"] = to_string(mds->dt);
+ mRNAMap["TIMESTEPS_MIN"] = to_string(mds->timesteps_minimum);
+ mRNAMap["TIMESTEPS_MAX"] = to_string(mds->timesteps_maximum);
+ mRNAMap["TIME_TOTAL"] = to_string(mds->time_total);
+ mRNAMap["TIME_PER_FRAME"] = to_string(mds->time_per_frame);
+ mRNAMap["VORTICITY"] = to_string(mds->vorticity);
+ mRNAMap["FLAME_VORTICITY"] = to_string(mds->flame_vorticity);
+ mRNAMap["NOISE_SCALE"] = to_string(mds->noise_scale);
+ mRNAMap["MESH_SCALE"] = to_string(mds->mesh_scale);
+ mRNAMap["PARTICLE_SCALE"] = to_string(mds->particle_scale);
+ mRNAMap["NOISE_RESX"] = to_string(mResXNoise);
+ mRNAMap["NOISE_RESY"] = (is2D) ? to_string(mResZNoise) : to_string(mResYNoise);
+ mRNAMap["NOISE_RESZ"] = (is2D) ? to_string(1) : to_string(mResZNoise);
+ mRNAMap["MESH_RESX"] = to_string(mResXMesh);
+ mRNAMap["MESH_RESY"] = (is2D) ? to_string(mResZMesh) : to_string(mResYMesh);
+ mRNAMap["MESH_RESZ"] = (is2D) ? to_string(1) : to_string(mResZMesh);
+ mRNAMap["PARTICLE_RESX"] = to_string(mResXParticle);
+ mRNAMap["PARTICLE_RESY"] = (is2D) ? to_string(mResZParticle) : to_string(mResYParticle);
+ mRNAMap["PARTICLE_RESZ"] = (is2D) ? to_string(1) : to_string(mResZParticle);
+ mRNAMap["GUIDING_RESX"] = to_string(mResGuiding[0]);
+ mRNAMap["GUIDING_RESY"] = (is2D) ? to_string(mResGuiding[2]) : to_string(mResGuiding[1]);
+ mRNAMap["GUIDING_RESZ"] = (is2D) ? to_string(1) : to_string(mResGuiding[2]);
+ mRNAMap["MIN_RESX"] = to_string(mds->res_min[0]);
+ mRNAMap["MIN_RESY"] = to_string(mds->res_min[1]);
+ mRNAMap["MIN_RESZ"] = to_string(mds->res_min[2]);
+ mRNAMap["BASE_RESX"] = to_string(mds->base_res[0]);
+ mRNAMap["BASE_RESY"] = to_string(mds->base_res[1]);
+ mRNAMap["BASE_RESZ"] = to_string(mds->base_res[2]);
+ mRNAMap["WLT_STR"] = to_string(mds->noise_strength);
+ mRNAMap["NOISE_POSSCALE"] = to_string(mds->noise_pos_scale);
+ mRNAMap["NOISE_TIMEANIM"] = to_string(mds->noise_time_anim);
+ mRNAMap["COLOR_R"] = to_string(mds->active_color[0]);
+ mRNAMap["COLOR_G"] = to_string(mds->active_color[1]);
+ mRNAMap["COLOR_B"] = to_string(mds->active_color[2]);
+ mRNAMap["BUOYANCY_ALPHA"] = to_string(mds->alpha);
+ mRNAMap["BUOYANCY_BETA"] = to_string(mds->beta);
+ mRNAMap["DISSOLVE_SPEED"] = to_string(mds->diss_speed);
+ mRNAMap["BURNING_RATE"] = to_string(mds->burning_rate);
+ mRNAMap["FLAME_SMOKE"] = to_string(mds->flame_smoke);
+ mRNAMap["IGNITION_TEMP"] = to_string(mds->flame_ignition);
+ mRNAMap["MAX_TEMP"] = to_string(mds->flame_max_temp);
+ mRNAMap["FLAME_SMOKE_COLOR_X"] = to_string(mds->flame_smoke_color[0]);
+ mRNAMap["FLAME_SMOKE_COLOR_Y"] = to_string(mds->flame_smoke_color[1]);
+ mRNAMap["FLAME_SMOKE_COLOR_Z"] = to_string(mds->flame_smoke_color[2]);
+ mRNAMap["CURRENT_FRAME"] = to_string(int(mmd->time));
+ mRNAMap["START_FRAME"] = to_string(mds->cache_frame_start);
+ mRNAMap["END_FRAME"] = to_string(mds->cache_frame_end);
+ mRNAMap["CACHE_DATA_FORMAT"] = getCacheFileEnding(mds->cache_data_format);
+ mRNAMap["CACHE_MESH_FORMAT"] = getCacheFileEnding(mds->cache_mesh_format);
+ mRNAMap["CACHE_NOISE_FORMAT"] = getCacheFileEnding(mds->cache_noise_format);
+ mRNAMap["CACHE_PARTICLE_FORMAT"] = getCacheFileEnding(mds->cache_particle_format);
+ mRNAMap["SIMULATION_METHOD"] = simulationMethod;
+ mRNAMap["FLIP_RATIO"] = to_string(mds->flip_ratio);
+ mRNAMap["PARTICLE_RANDOMNESS"] = to_string(mds->particle_randomness);
+ mRNAMap["PARTICLE_NUMBER"] = to_string(mds->particle_number);
+ mRNAMap["PARTICLE_MINIMUM"] = to_string(mds->particle_minimum);
+ mRNAMap["PARTICLE_MAXIMUM"] = to_string(mds->particle_maximum);
+ mRNAMap["PARTICLE_RADIUS"] = to_string(mds->particle_radius);
+ mRNAMap["FRACTIONS_THRESHOLD"] = to_string(mds->fractions_threshold);
+ mRNAMap["MESH_CONCAVE_UPPER"] = to_string(mds->mesh_concave_upper);
+ mRNAMap["MESH_CONCAVE_LOWER"] = to_string(mds->mesh_concave_lower);
+ mRNAMap["MESH_PARTICLE_RADIUS"] = to_string(mds->mesh_particle_radius);
+ mRNAMap["MESH_SMOOTHEN_POS"] = to_string(mds->mesh_smoothen_pos);
+ mRNAMap["MESH_SMOOTHEN_NEG"] = to_string(mds->mesh_smoothen_neg);
+ mRNAMap["PARTICLE_BAND_WIDTH"] = to_string(mds->particle_band_width);
+ mRNAMap["SNDPARTICLE_TAU_MIN_WC"] = to_string(mds->sndparticle_tau_min_wc);
+ mRNAMap["SNDPARTICLE_TAU_MAX_WC"] = to_string(mds->sndparticle_tau_max_wc);
+ mRNAMap["SNDPARTICLE_TAU_MIN_TA"] = to_string(mds->sndparticle_tau_min_ta);
+ mRNAMap["SNDPARTICLE_TAU_MAX_TA"] = to_string(mds->sndparticle_tau_max_ta);
+ mRNAMap["SNDPARTICLE_TAU_MIN_K"] = to_string(mds->sndparticle_tau_min_k);
+ mRNAMap["SNDPARTICLE_TAU_MAX_K"] = to_string(mds->sndparticle_tau_max_k);
+ mRNAMap["SNDPARTICLE_K_WC"] = to_string(mds->sndparticle_k_wc);
+ mRNAMap["SNDPARTICLE_K_TA"] = to_string(mds->sndparticle_k_ta);
+ mRNAMap["SNDPARTICLE_K_B"] = to_string(mds->sndparticle_k_b);
+ mRNAMap["SNDPARTICLE_K_D"] = to_string(mds->sndparticle_k_d);
+ mRNAMap["SNDPARTICLE_L_MIN"] = to_string(mds->sndparticle_l_min);
+ mRNAMap["SNDPARTICLE_L_MAX"] = to_string(mds->sndparticle_l_max);
+ mRNAMap["SNDPARTICLE_POTENTIAL_RADIUS"] = to_string(mds->sndparticle_potential_radius);
+ mRNAMap["SNDPARTICLE_UPDATE_RADIUS"] = to_string(mds->sndparticle_update_radius);
+ mRNAMap["LIQUID_SURFACE_TENSION"] = to_string(mds->surface_tension);
+ mRNAMap["FLUID_VISCOSITY"] = to_string(viscosity);
+ mRNAMap["FLUID_DOMAIN_SIZE"] = to_string(domainSize);
+ mRNAMap["SNDPARTICLE_TYPES"] = particleTypesStr;
+ mRNAMap["GUIDING_ALPHA"] = to_string(mds->guide_alpha);
+ mRNAMap["GUIDING_BETA"] = to_string(mds->guide_beta);
+ mRNAMap["GUIDING_FACTOR"] = to_string(mds->guide_vel_factor);
+ mRNAMap["GRAVITY_X"] = to_string(mds->gravity[0]);
+ mRNAMap["GRAVITY_Y"] = to_string(mds->gravity[1]);
+ mRNAMap["GRAVITY_Z"] = to_string(mds->gravity[2]);
+ mRNAMap["CACHE_DIR"] = cacheDirectory;
+ mRNAMap["NAME_DENSITY"] = FLUID_GRIDNAME_DENSITY;
+ mRNAMap["NAME_SHADOW"] = FLUID_GRIDNAME_SHADOW;
+ mRNAMap["NAME_HEAT"] = FLUID_GRIDNAME_HEAT;
+ mRNAMap["NAME_VELOCITY"] = FLUID_GRIDNAME_VELOCITY;
+ mRNAMap["NAME_COLORR"] = FLUID_GRIDNAME_COLORR;
+ mRNAMap["NAME_COLORG"] = FLUID_GRIDNAME_COLORG;
+ mRNAMap["NAME_COLORB"] = FLUID_GRIDNAME_COLORB;
+ mRNAMap["NAME_FLAME"] = FLUID_GRIDNAME_FLAME;
+ mRNAMap["NAME_FUEL"] = FLUID_GRIDNAME_FUEL;
+ mRNAMap["NAME_REACT"] = FLUID_GRIDNAME_REACT;
+ mRNAMap["NAME_DENSITYNOISE"] = FLUID_GRIDNAME_DENSITYNOISE;
+ mRNAMap["NAME_COLORRNOISE"] = FLUID_GRIDNAME_COLORRNOISE;
+ mRNAMap["NAME_COLORGNOISE"] = FLUID_GRIDNAME_COLORGNOISE;
+ mRNAMap["NAME_COLORBNOISE"] = FLUID_GRIDNAME_COLORBNOISE;
+ mRNAMap["NAME_FLAMENOISE"] = FLUID_GRIDNAME_FLAMENOISE;
+ mRNAMap["NAME_FUELNOISE"] = FLUID_GRIDNAME_FUELNOISE;
+ mRNAMap["NAME_REACTNOISE"] = FLUID_GRIDNAME_REACTNOISE;
+}
+
+string MANTA::getRealValue(const string &varName)
+{
+ if (with_debug)
+ cout << "MANTA::getRealValue()" << endl;
+
+ unordered_map<string, string>::iterator it;
+ it = mRNAMap.find(varName);
+
+ if (it == mRNAMap.end()) {
+ cerr << "Fluid Error -- variable " << varName << " not found in RNA map " << it->second
+ << endl;
+ return "";
}
- else if (varName == "MIN_RESX")
- ss << mmd->domain->res_min[0];
- else if (varName == "MIN_RESY")
- ss << mmd->domain->res_min[1];
- else if (varName == "MIN_RESZ")
- ss << mmd->domain->res_min[2];
- else if (varName == "BASE_RESX")
- ss << mmd->domain->base_res[0];
- else if (varName == "BASE_RESY")
- ss << mmd->domain->base_res[1];
- else if (varName == "BASE_RESZ")
- ss << mmd->domain->base_res[2];
- else if (varName == "WLT_STR")
- ss << mmd->domain->noise_strength;
- else if (varName == "NOISE_POSSCALE")
- ss << mmd->domain->noise_pos_scale;
- else if (varName == "NOISE_TIMEANIM")
- ss << mmd->domain->noise_time_anim;
- else if (varName == "COLOR_R")
- ss << mmd->domain->active_color[0];
- else if (varName == "COLOR_G")
- ss << mmd->domain->active_color[1];
- else if (varName == "COLOR_B")
- ss << mmd->domain->active_color[2];
- else if (varName == "BUOYANCY_ALPHA")
- ss << mmd->domain->alpha;
- else if (varName == "BUOYANCY_BETA")
- ss << mmd->domain->beta;
- else if (varName == "DISSOLVE_SPEED")
- ss << mmd->domain->diss_speed;
- else if (varName == "BURNING_RATE")
- ss << mmd->domain->burning_rate;
- else if (varName == "FLAME_SMOKE")
- ss << mmd->domain->flame_smoke;
- else if (varName == "IGNITION_TEMP")
- ss << mmd->domain->flame_ignition;
- else if (varName == "MAX_TEMP")
- ss << mmd->domain->flame_max_temp;
- else if (varName == "FLAME_SMOKE_COLOR_X")
- ss << mmd->domain->flame_smoke_color[0];
- else if (varName == "FLAME_SMOKE_COLOR_Y")
- ss << mmd->domain->flame_smoke_color[1];
- else if (varName == "FLAME_SMOKE_COLOR_Z")
- ss << mmd->domain->flame_smoke_color[2];
- else if (varName == "CURRENT_FRAME")
- ss << mmd->time;
- else if (varName == "START_FRAME")
- ss << mmd->domain->cache_frame_start;
- else if (varName == "END_FRAME")
- ss << mmd->domain->cache_frame_end;
- else if (varName == "CACHE_DATA_FORMAT")
- ss << getCacheFileEnding(mmd->domain->cache_data_format);
- else if (varName == "CACHE_MESH_FORMAT")
- ss << getCacheFileEnding(mmd->domain->cache_mesh_format);
- else if (varName == "CACHE_NOISE_FORMAT")
- ss << getCacheFileEnding(mmd->domain->cache_noise_format);
- else if (varName == "CACHE_PARTICLE_FORMAT")
- ss << getCacheFileEnding(mmd->domain->cache_particle_format);
- else if (varName == "SIMULATION_METHOD") {
- if (mmd->domain->simulation_method & FLUID_DOMAIN_METHOD_FLIP) {
- ss << "'FLIP'";
- }
- else if (mmd->domain->simulation_method & FLUID_DOMAIN_METHOD_APIC) {
- ss << "'APIC'";
- }
- else {
- ss << "'NONE'";
- }
+ if (with_debug) {
+ cout << "Found variable " << varName << " with value " << it->second << endl;
}
- else if (varName == "FLIP_RATIO")
- ss << mmd->domain->flip_ratio;
- else if (varName == "PARTICLE_RANDOMNESS")
- ss << mmd->domain->particle_randomness;
- else if (varName == "PARTICLE_NUMBER")
- ss << mmd->domain->particle_number;
- else if (varName == "PARTICLE_MINIMUM")
- ss << mmd->domain->particle_minimum;
- else if (varName == "PARTICLE_MAXIMUM")
- ss << mmd->domain->particle_maximum;
- else if (varName == "PARTICLE_RADIUS")
- ss << mmd->domain->particle_radius;
- else if (varName == "FRACTIONS_THRESHOLD")
- ss << mmd->domain->fractions_threshold;
- else if (varName == "MESH_CONCAVE_UPPER")
- ss << mmd->domain->mesh_concave_upper;
- else if (varName == "MESH_CONCAVE_LOWER")
- ss << mmd->domain->mesh_concave_lower;
- else if (varName == "MESH_PARTICLE_RADIUS")
- ss << mmd->domain->mesh_particle_radius;
- else if (varName == "MESH_SMOOTHEN_POS")
- ss << mmd->domain->mesh_smoothen_pos;
- else if (varName == "MESH_SMOOTHEN_NEG")
- ss << mmd->domain->mesh_smoothen_neg;
- else if (varName == "USING_MESH")
- ss << (mmd->domain->flags & FLUID_DOMAIN_USE_MESH ? "True" : "False");
- else if (varName == "USING_IMPROVED_MESH")
- ss << (mmd->domain->mesh_generator == FLUID_DOMAIN_MESH_IMPROVED ? "True" : "False");
- else if (varName == "PARTICLE_BAND_WIDTH")
- ss << mmd->domain->particle_band_width;
- else if (varName == "SNDPARTICLE_TAU_MIN_WC")
- ss << mmd->domain->sndparticle_tau_min_wc;
- else if (varName == "SNDPARTICLE_TAU_MAX_WC")
- ss << mmd->domain->sndparticle_tau_max_wc;
- else if (varName == "SNDPARTICLE_TAU_MIN_TA")
- ss << mmd->domain->sndparticle_tau_min_ta;
- else if (varName == "SNDPARTICLE_TAU_MAX_TA")
- ss << mmd->domain->sndparticle_tau_max_ta;
- else if (varName == "SNDPARTICLE_TAU_MIN_K")
- ss << mmd->domain->sndparticle_tau_min_k;
- else if (varName == "SNDPARTICLE_TAU_MAX_K")
- ss << mmd->domain->sndparticle_tau_max_k;
- else if (varName == "SNDPARTICLE_K_WC")
- ss << mmd->domain->sndparticle_k_wc;
- else if (varName == "SNDPARTICLE_K_TA")
- ss << mmd->domain->sndparticle_k_ta;
- else if (varName == "SNDPARTICLE_K_B")
- ss << mmd->domain->sndparticle_k_b;
- else if (varName == "SNDPARTICLE_K_D")
- ss << mmd->domain->sndparticle_k_d;
- else if (varName == "SNDPARTICLE_L_MIN")
- ss << mmd->domain->sndparticle_l_min;
- else if (varName == "SNDPARTICLE_L_MAX")
- ss << mmd->domain->sndparticle_l_max;
- else if (varName == "SNDPARTICLE_BOUNDARY_DELETE")
- ss << (mmd->domain->sndparticle_boundary == SNDPARTICLE_BOUNDARY_DELETE);
- else if (varName == "SNDPARTICLE_BOUNDARY_PUSHOUT")
- ss << (mmd->domain->sndparticle_boundary == SNDPARTICLE_BOUNDARY_PUSHOUT);
- else if (varName == "SNDPARTICLE_POTENTIAL_RADIUS")
- ss << mmd->domain->sndparticle_potential_radius;
- else if (varName == "SNDPARTICLE_UPDATE_RADIUS")
- ss << mmd->domain->sndparticle_update_radius;
- else if (varName == "LIQUID_SURFACE_TENSION")
- ss << mmd->domain->surface_tension;
- else if (varName == "FLUID_VISCOSITY")
- ss << mmd->domain->viscosity_base * pow(10.0f, -mmd->domain->viscosity_exponent);
- else if (varName == "FLUID_DOMAIN_SIZE") {
- tmpFloat = MAX3(
- mmd->domain->global_size[0], mmd->domain->global_size[1], mmd->domain->global_size[2]);
- ss << tmpFloat;
- }
- else if (varName == "SNDPARTICLE_TYPES") {
- if (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) {
- ss << "PtypeSpray";
- }
- if (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) {
- if (!ss.str().empty())
- ss << "|";
- ss << "PtypeBubble";
- }
- if (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) {
- if (!ss.str().empty())
- ss << "|";
- ss << "PtypeFoam";
- }
- if (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_TRACER) {
- if (!ss.str().empty())
- ss << "|";
- ss << "PtypeTracer";
- }
- if (ss.str().empty())
- ss << "0";
- }
- else if (varName == "USING_SNDPARTS") {
- tmpVar = (FLUID_DOMAIN_PARTICLE_SPRAY | FLUID_DOMAIN_PARTICLE_BUBBLE |
- FLUID_DOMAIN_PARTICLE_FOAM | FLUID_DOMAIN_PARTICLE_TRACER);
- ss << (((mmd->domain->particle_type & tmpVar)) ? "True" : "False");
- }
- else if (varName == "GUIDING_ALPHA")
- ss << mmd->domain->guide_alpha;
- else if (varName == "GUIDING_BETA")
- ss << mmd->domain->guide_beta;
- else if (varName == "GUIDING_FACTOR")
- ss << mmd->domain->guide_vel_factor;
- else if (varName == "GRAVITY_X")
- ss << mmd->domain->gravity[0];
- else if (varName == "GRAVITY_Y")
- ss << mmd->domain->gravity[1];
- else if (varName == "GRAVITY_Z")
- ss << mmd->domain->gravity[2];
- else if (varName == "CACHE_DIR")
- ss << mmd->domain->cache_directory;
- else if (varName == "CACHE_RESUMABLE")
- ss << (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL ? "False" : "True");
- else if (varName == "USING_ADAPTIVETIME")
- ss << (mmd->domain->flags & FLUID_DOMAIN_USE_ADAPTIVE_TIME ? "True" : "False");
- else if (varName == "USING_SPEEDVECTORS")
- ss << (mmd->domain->flags & FLUID_DOMAIN_USE_SPEED_VECTORS ? "True" : "False");
- else if (varName == "USING_FRACTIONS")
- ss << (mmd->domain->flags & FLUID_DOMAIN_USE_FRACTIONS ? "True" : "False");
- else if (varName == "DELETE_IN_OBSTACLE")
- ss << (mmd->domain->flags & FLUID_DOMAIN_DELETE_IN_OBSTACLE ? "True" : "False");
- else if (varName == "USING_DIFFUSION")
- ss << (mmd->domain->flags & FLUID_DOMAIN_USE_DIFFUSION ? "True" : "False");
- else
- std::cerr << "Fluid Error -- Unknown option: " << varName << std::endl;
- return ss.str();
-}
-
-std::string MANTA::parseLine(const std::string &line, FluidModifierData *mmd)
+
+ return it->second;
+}
+
+string MANTA::parseLine(const string &line)
{
if (line.size() == 0)
return "";
- std::string res = "";
+ string res = "";
int currPos = 0, start_del = 0, end_del = -1;
bool readingVar = false;
const char delimiter = '$';
@@ -1055,7 +914,7 @@ std::string MANTA::parseLine(const std::string &line, FluidModifierData *mmd)
else if (line[currPos] == delimiter && readingVar) {
readingVar = false;
end_del = currPos;
- res += getRealValue(line.substr(start_del, currPos - start_del), mmd);
+ res += getRealValue(line.substr(start_del, currPos - start_del));
}
currPos++;
}
@@ -1063,13 +922,21 @@ std::string MANTA::parseLine(const std::string &line, FluidModifierData *mmd)
return res;
}
-std::string MANTA::parseScript(const std::string &setup_string, FluidModifierData *mmd)
+string MANTA::parseScript(const string &setup_string, FluidModifierData *mmd)
{
- std::istringstream f(setup_string);
- std::ostringstream res;
- std::string line = "";
+ if (MANTA::with_debug)
+ cout << "MANTA::parseScript()" << endl;
+
+ istringstream f(setup_string);
+ ostringstream res;
+ string line = "";
+
+ // Update RNA map if modifier data is handed over
+ if (mmd) {
+ initializeRNAMap(mmd);
+ }
while (getline(f, line)) {
- res << parseLine(line, mmd) << "\n";
+ res << parseLine(line) << "\n";
}
return res.str();
}
@@ -1077,13 +944,14 @@ std::string MANTA::parseScript(const std::string &setup_string, FluidModifierDat
bool MANTA::updateFlipStructures(FluidModifierData *mmd, int framenr)
{
if (MANTA::with_debug)
- std::cout << "MANTA::updateFlipStructures()" << std::endl;
+ cout << "MANTA::updateFlipStructures()" << endl;
+ FluidDomainSettings *mds = mmd->domain;
mFlipFromFile = false;
if (!mUsingLiquid)
return false;
- if (BLI_path_is_rel(mmd->domain->cache_directory))
+ if (BLI_path_is_rel(mds->cache_directory))
return false;
int result = 0;
@@ -1096,9 +964,8 @@ bool MANTA::updateFlipStructures(FluidModifierData *mmd, int framenr)
mFlipParticleData->clear();
mFlipParticleVelocity->clear();
- std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format);
- std::string file = getFile(
- mmd, FLUID_DOMAIN_DIR_DATA, FLUID_DOMAIN_FILE_PP, pformat.c_str(), framenr);
+ string pformat = getCacheFileEnding(mds->cache_particle_format);
+ string file = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_FILENAME_PP, pformat, framenr);
expected += 1;
if (BLI_exists(file.c_str())) {
@@ -1106,7 +973,7 @@ bool MANTA::updateFlipStructures(FluidModifierData *mmd, int framenr)
assert(result == expected);
}
- file = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_DOMAIN_FILE_PVEL, pformat.c_str(), framenr);
+ file = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_FILENAME_PVEL, pformat, framenr);
expected += 1;
if (BLI_exists(file.c_str())) {
result += updateParticlesFromFile(file, false, true);
@@ -1119,13 +986,14 @@ bool MANTA::updateFlipStructures(FluidModifierData *mmd, int framenr)
bool MANTA::updateMeshStructures(FluidModifierData *mmd, int framenr)
{
if (MANTA::with_debug)
- std::cout << "MANTA::updateMeshStructures()" << std::endl;
+ cout << "MANTA::updateMeshStructures()" << endl;
+ FluidDomainSettings *mds = mmd->domain;
mMeshFromFile = false;
if (!mUsingMesh)
return false;
- if (BLI_path_is_rel(mmd->domain->cache_directory))
+ if (BLI_path_is_rel(mds->cache_directory))
return false;
int result = 0;
@@ -1141,9 +1009,9 @@ bool MANTA::updateMeshStructures(FluidModifierData *mmd, int framenr)
if (mMeshVelocities)
mMeshVelocities->clear();
- std::string mformat = getCacheFileEnding(mmd->domain->cache_mesh_format);
- std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format);
- std::string file = getFile(mmd, FLUID_DOMAIN_DIR_MESH, FLUID_DOMAIN_FILE_MESH, mformat, framenr);
+ string mformat = getCacheFileEnding(mds->cache_mesh_format);
+ string dformat = getCacheFileEnding(mds->cache_data_format);
+ string file = getFile(mmd, FLUID_DOMAIN_DIR_MESH, FLUID_FILENAME_MESH, mformat, framenr);
expected += 1;
if (BLI_exists(file.c_str())) {
@@ -1152,7 +1020,7 @@ bool MANTA::updateMeshStructures(FluidModifierData *mmd, int framenr)
}
if (mUsingMVel) {
- file = getFile(mmd, FLUID_DOMAIN_DIR_MESH, FLUID_DOMAIN_FILE_MESHVEL, dformat, framenr);
+ file = getFile(mmd, FLUID_DOMAIN_DIR_MESH, FLUID_FILENAME_MESHVEL, dformat, framenr);
expected += 1;
if (BLI_exists(file.c_str())) {
result += updateMeshFromFile(file);
@@ -1166,13 +1034,14 @@ bool MANTA::updateMeshStructures(FluidModifierData *mmd, int framenr)
bool MANTA::updateParticleStructures(FluidModifierData *mmd, int framenr)
{
if (MANTA::with_debug)
- std::cout << "MANTA::updateParticleStructures()" << std::endl;
+ cout << "MANTA::updateParticleStructures()" << endl;
+ FluidDomainSettings *mds = mmd->domain;
mParticlesFromFile = false;
if (!mUsingDrops && !mUsingBubbles && !mUsingFloats && !mUsingTracers)
return false;
- if (BLI_path_is_rel(mmd->domain->cache_directory))
+ if (BLI_path_is_rel(mds->cache_directory))
return false;
int result = 0;
@@ -1186,9 +1055,8 @@ bool MANTA::updateParticleStructures(FluidModifierData *mmd, int framenr)
mSndParticleVelocity->clear();
mSndParticleLife->clear();
- std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format);
- std::string file = getFile(
- mmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_DOMAIN_FILE_PPSND, pformat, framenr);
+ string pformat = getCacheFileEnding(mds->cache_particle_format);
+ string file = getFile(mmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_FILENAME_PPSND, pformat, framenr);
expected += 1;
if (BLI_exists(file.c_str())) {
@@ -1196,14 +1064,14 @@ bool MANTA::updateParticleStructures(FluidModifierData *mmd, int framenr)
assert(result == expected);
}
- file = getFile(mmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_DOMAIN_FILE_PVELSND, pformat, framenr);
+ file = getFile(mmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_FILENAME_PVELSND, pformat, framenr);
expected += 1;
if (BLI_exists(file.c_str())) {
result += updateParticlesFromFile(file, true, true);
assert(result == expected);
}
- file = getFile(mmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_DOMAIN_FILE_PLIFESND, pformat, framenr);
+ file = getFile(mmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_FILENAME_PLIFESND, pformat, framenr);
expected += 1;
if (BLI_exists(file.c_str())) {
result += updateParticlesFromFile(file, true, false);
@@ -1213,183 +1081,278 @@ bool MANTA::updateParticleStructures(FluidModifierData *mmd, int framenr)
return mParticlesFromFile = (result == expected);
}
+static void assertGridItems(vector<MANTA::GridItem> gList)
+{
+ vector<MANTA::GridItem>::iterator gIter = gList.begin();
+ int *resPrev = (*gIter).res;
+
+ for (vector<MANTA::GridItem>::iterator it = gList.begin(); it != gList.end(); ++it) {
+ MANTA::GridItem item = *it;
+ assert(
+ ELEM(item.type, FLUID_DOMAIN_GRID_FLOAT, FLUID_DOMAIN_GRID_INT, FLUID_DOMAIN_GRID_VEC3F));
+ assert(item.pointer[0]);
+ if (item.type == FLUID_DOMAIN_GRID_VEC3F) {
+ assert(item.pointer[1] && item.pointer[2]);
+ }
+ assert(item.res[0] == resPrev[0] && item.res[1] == resPrev[1] && item.res[2] == resPrev[2]);
+ assert((item.name).compare("") != 0);
+ }
+
+ UNUSED_VARS(resPrev);
+}
+
bool MANTA::updateSmokeStructures(FluidModifierData *mmd, int framenr)
{
if (MANTA::with_debug)
- std::cout << "MANTA::updateGridStructures()" << std::endl;
+ cout << "MANTA::updateGridStructures()" << endl;
+ FluidDomainSettings *mds = mmd->domain;
mSmokeFromFile = false;
if (!mUsingSmoke)
return false;
- if (BLI_path_is_rel(mmd->domain->cache_directory))
+ if (BLI_path_is_rel(mds->cache_directory))
return false;
int result = 0;
- int expected = 0; /* Expected number of read successes for this frame. */
-
- std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format);
- std::string file = getFile(
- mmd, FLUID_DOMAIN_DIR_DATA, FLUID_DOMAIN_FILE_DENSITY, dformat, framenr);
-
- expected += 1;
- if (BLI_exists(file.c_str())) {
- result += updateGridFromFile(file, mDensity, false);
- assert(result == expected);
- }
-
- file = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_DOMAIN_FILE_SHADOW, dformat, framenr);
- expected += 1;
- if (BLI_exists(file.c_str())) {
- result += updateGridFromFile(file, mShadow, false);
- assert(result == expected);
- }
-
- if (mUsingHeat) {
- file = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_DOMAIN_FILE_HEAT, dformat, framenr);
- expected += 1;
- if (BLI_exists(file.c_str())) {
- result += updateGridFromFile(file, mHeat, false);
- assert(result == expected);
- }
- }
-
- if (mUsingColors) {
- file = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_DOMAIN_FILE_COLORR, dformat, framenr);
- expected += 1;
- if (BLI_exists(file.c_str())) {
- result += updateGridFromFile(file, mColorR, false);
- assert(result == expected);
- }
-
- file = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_DOMAIN_FILE_COLORG, dformat, framenr);
- expected += 1;
- if (BLI_exists(file.c_str())) {
- result += updateGridFromFile(file, mColorG, false);
- assert(result == expected);
- }
-
- file = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_DOMAIN_FILE_COLORB, dformat, framenr);
- expected += 1;
- if (BLI_exists(file.c_str())) {
- result += updateGridFromFile(file, mColorB, false);
- assert(result == expected);
- }
- }
-
- if (mUsingFire) {
- file = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_DOMAIN_FILE_FLAME, dformat, framenr);
- expected += 1;
- if (BLI_exists(file.c_str())) {
- result += updateGridFromFile(file, mFlame, false);
- assert(result == expected);
- }
-
- file = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_DOMAIN_FILE_FUEL, dformat, framenr);
- expected += 1;
- if (BLI_exists(file.c_str())) {
- result += updateGridFromFile(file, mFuel, false);
- assert(result == expected);
- }
-
- file = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_DOMAIN_FILE_REACT, dformat, framenr);
- expected += 1;
- if (BLI_exists(file.c_str())) {
- result += updateGridFromFile(file, mReact, false);
- assert(result == expected);
- }
- }
-
- return mSmokeFromFile = (result == expected);
+ string dformat = getCacheFileEnding(mds->cache_data_format);
+
+ vector<FileItem> filesData;
+ vector<GridItem> gridsData;
+
+ int res[] = {mResX, mResY, mResZ};
+
+ /* Put grid pointers into pointer lists, some grids have more than 1 pointer. */
+ void *aDensity[] = {mDensity};
+ void *aShadow[] = {mShadow};
+ void *aVelocities[] = {mVelocityX, mVelocityY, mVelocityZ};
+ void *aHeat[] = {mHeat};
+ void *aColorR[] = {mColorR};
+ void *aColorG[] = {mColorG};
+ void *aColorB[] = {mColorB};
+ void *aFlame[] = {mFlame};
+ void *aFuel[] = {mFuel};
+ void *aReact[] = {mReact};
+
+ /* File names for grids. */
+ string fDensity = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_FILENAME_DENSITY, dformat, framenr);
+ string fShadow = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_FILENAME_SHADOW, dformat, framenr);
+ string fVel = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_FILENAME_VELOCITY, dformat, framenr);
+ string fHeat = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_FILENAME_HEAT, dformat, framenr);
+ string fColorR = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_FILENAME_COLORR, dformat, framenr);
+ string fColorG = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_FILENAME_COLORG, dformat, framenr);
+ string fColorB = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_FILENAME_COLORB, dformat, framenr);
+ string fFlame = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_FILENAME_FLAME, dformat, framenr);
+ string fFuel = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_FILENAME_FUEL, dformat, framenr);
+ string fReact = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_FILENAME_REACT, dformat, framenr);
+ string fFluid = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_FILENAME_DATA, dformat, framenr);
+
+ /* Prepare grid info containers. */
+ GridItem gDensity = {aDensity, FLUID_DOMAIN_GRID_FLOAT, res, FLUID_GRIDNAME_DENSITY};
+ GridItem gShadow = {aShadow, FLUID_DOMAIN_GRID_FLOAT, res, FLUID_GRIDNAME_SHADOW};
+ GridItem gVel = {aVelocities, FLUID_DOMAIN_GRID_VEC3F, res, FLUID_GRIDNAME_VELOCITY};
+ GridItem gHeat = {aHeat, FLUID_DOMAIN_GRID_FLOAT, res, FLUID_GRIDNAME_HEAT};
+ GridItem gColorR = {aColorR, FLUID_DOMAIN_GRID_FLOAT, res, FLUID_GRIDNAME_COLORR};
+ GridItem gColorG = {aColorG, FLUID_DOMAIN_GRID_FLOAT, res, FLUID_GRIDNAME_COLORG};
+ GridItem gColorB = {aColorB, FLUID_DOMAIN_GRID_FLOAT, res, FLUID_GRIDNAME_COLORB};
+ GridItem gFlame = {aFlame, FLUID_DOMAIN_GRID_FLOAT, res, FLUID_GRIDNAME_FLAME};
+ GridItem gFuel = {aFuel, FLUID_DOMAIN_GRID_FLOAT, res, FLUID_GRIDNAME_FUEL};
+ GridItem gReact = {aReact, FLUID_DOMAIN_GRID_FLOAT, res, FLUID_GRIDNAME_REACT};
+
+ /* TODO (sebbas): For now, only allow single file mode. Combined grid file export is todo. */
+ const int fileMode = FLUID_DOMAIN_CACHE_FILES_SINGLE;
+ if (fileMode == FLUID_DOMAIN_CACHE_FILES_SINGLE) {
+
+ filesData.push_back({fDensity, {gDensity}});
+ filesData.push_back({fShadow, {gShadow}});
+ filesData.push_back({fVel, {gVel}});
+ if (mUsingHeat) {
+ filesData.push_back({fHeat, {gHeat}});
+ }
+ if (mUsingColors) {
+ filesData.push_back({fColorR, {gColorR}});
+ filesData.push_back({fColorG, {gColorG}});
+ filesData.push_back({fColorB, {gColorB}});
+ }
+ if (mUsingFire) {
+ filesData.push_back({fFlame, {gFlame}});
+ filesData.push_back({fFuel, {gFuel}});
+ filesData.push_back({fReact, {gReact}});
+ }
+ }
+ else if (fileMode == FLUID_DOMAIN_CACHE_FILES_COMBINED) {
+
+ gridsData.push_back(gDensity);
+ gridsData.push_back(gShadow);
+ gridsData.push_back(gVel);
+ if (mUsingHeat) {
+ gridsData.push_back(gHeat);
+ }
+ if (mUsingColors) {
+ gridsData.push_back(gColorR);
+ gridsData.push_back(gColorG);
+ gridsData.push_back(gColorB);
+ }
+ if (mUsingFire) {
+ gridsData.push_back(gFlame);
+ gridsData.push_back(gFuel);
+ gridsData.push_back(gReact);
+ }
+
+ if (with_debug) {
+ assertGridItems(gridsData);
+ }
+ filesData.push_back({fFluid, gridsData});
+ }
+
+ /* Update files from data directory. */
+ for (vector<FileItem>::iterator it = filesData.begin(); it != filesData.end(); ++it) {
+ FileItem item = *it;
+ if (BLI_exists(item.filename.c_str())) {
+ result += updateGridsFromFile(item.filename, item.grids);
+ assert(result);
+ }
+ }
+
+ return mSmokeFromFile = result;
}
bool MANTA::updateNoiseStructures(FluidModifierData *mmd, int framenr)
{
if (MANTA::with_debug)
- std::cout << "MANTA::updateNoiseStructures()" << std::endl;
+ cout << "MANTA::updateNoiseStructures()" << endl;
+ FluidDomainSettings *mds = mmd->domain;
mNoiseFromFile = false;
if (!mUsingSmoke || !mUsingNoise)
return false;
- if (BLI_path_is_rel(mmd->domain->cache_directory))
+ if (BLI_path_is_rel(mds->cache_directory))
return false;
int result = 0;
- int expected = 0; /* Expected number of read successes for this frame. */
+ string dformat = getCacheFileEnding(mds->cache_data_format);
+ string nformat = getCacheFileEnding(mds->cache_noise_format);
+
+ vector<FileItem> filesData, filesNoise;
+ vector<GridItem> gridsData, gridsNoise;
+
+ int resData[] = {mResX, mResY, mResZ};
+ int resNoise[] = {mResXNoise, mResYNoise, mResZNoise};
+
+ /* Put grid pointers into pointer lists, some grids have more than 1 pointer. */
+ void *aShadow[] = {mShadow};
+ void *aVelocities[] = {mVelocityX, mVelocityY, mVelocityZ};
+ void *aDensity[] = {mDensityHigh};
+ void *aColorR[] = {mColorRHigh};
+ void *aColorG[] = {mColorGHigh};
+ void *aColorB[] = {mColorBHigh};
+ void *aFlame[] = {mFlameHigh};
+ void *aFuel[] = {mFuelHigh};
+ void *aReact[] = {mReactHigh};
- std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format);
- std::string nformat = getCacheFileEnding(mmd->domain->cache_noise_format);
- std::string file = getFile(
- mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_DOMAIN_FILE_DENSITYNOISE, nformat, framenr);
+ /* File names for grids. */
+ string fShadow = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_FILENAME_SHADOW, dformat, framenr);
+ string fVel = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_FILENAME_VELOCITY, dformat, framenr);
+ string fFluid = getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_FILENAME_DATA, dformat, framenr);
- expected += 1;
- if (BLI_exists(file.c_str())) {
- result += updateGridFromFile(file, mDensityHigh, true);
- assert(result == expected);
- }
+ string fDensity = getFile(
+ mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_FILENAME_DENSITYNOISE, nformat, framenr);
+ string fColorR = getFile(
+ mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_FILENAME_COLORRNOISE, nformat, framenr);
+ string fColorG = getFile(
+ mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_FILENAME_COLORGNOISE, nformat, framenr);
+ string fColorB = getFile(
+ mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_FILENAME_COLORBNOISE, nformat, framenr);
+ string fFlame = getFile(
+ mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_FILENAME_FLAMENOISE, nformat, framenr);
+ string fFuel = getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_FILENAME_FUELNOISE, nformat, framenr);
+ string fReact = getFile(
+ mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_FILENAME_REACTNOISE, nformat, framenr);
+ string fNoise = getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_FILENAME_NOISE, nformat, framenr);
- file = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_DOMAIN_FILE_SHADOW, dformat, framenr);
- expected += 1;
- if (BLI_exists(file.c_str())) {
- result += updateGridFromFile(file, mShadow, false);
- assert(result == expected);
- }
+ /* Prepare grid info containers. */
+ GridItem gShadow = {aShadow, FLUID_DOMAIN_GRID_FLOAT, resData, FLUID_GRIDNAME_SHADOW};
+ GridItem gVel = {aVelocities, FLUID_DOMAIN_GRID_VEC3F, resData, FLUID_GRIDNAME_VELOCITY};
- if (mUsingColors) {
- file = getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_DOMAIN_FILE_COLORRNOISE, nformat, framenr);
- expected += 1;
- if (BLI_exists(file.c_str())) {
- result += updateGridFromFile(file, mColorRHigh, true);
- assert(result == expected);
- }
+ GridItem gDensity = {aDensity, FLUID_DOMAIN_GRID_FLOAT, resNoise, FLUID_GRIDNAME_DENSITYNOISE};
+ GridItem gColorR = {aColorR, FLUID_DOMAIN_GRID_FLOAT, resNoise, FLUID_GRIDNAME_COLORRNOISE};
+ GridItem gColorG = {aColorG, FLUID_DOMAIN_GRID_FLOAT, resNoise, FLUID_GRIDNAME_COLORGNOISE};
+ GridItem gColorB = {aColorB, FLUID_DOMAIN_GRID_FLOAT, resNoise, FLUID_GRIDNAME_COLORBNOISE};
+ GridItem gFlame = {aFlame, FLUID_DOMAIN_GRID_FLOAT, resNoise, FLUID_GRIDNAME_FLAMENOISE};
+ GridItem gFuel = {aFuel, FLUID_DOMAIN_GRID_FLOAT, resNoise, FLUID_GRIDNAME_FUELNOISE};
+ GridItem gReact = {aReact, FLUID_DOMAIN_GRID_FLOAT, resNoise, FLUID_GRIDNAME_REACTNOISE};
- file = getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_DOMAIN_FILE_COLORGNOISE, nformat, framenr);
- expected += 1;
- if (BLI_exists(file.c_str())) {
- result += updateGridFromFile(file, mColorGHigh, true);
- assert(result == expected);
- }
+ /* TODO (sebbas): For now, only allow single file mode. Combined grid file export is todo. */
+ const int fileMode = FLUID_DOMAIN_CACHE_FILES_SINGLE;
+ if (fileMode == FLUID_DOMAIN_CACHE_FILES_SINGLE) {
- file = getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_DOMAIN_FILE_COLORBNOISE, nformat, framenr);
- expected += 1;
- if (BLI_exists(file.c_str())) {
- result += updateGridFromFile(file, mColorBHigh, true);
- assert(result == expected);
+ filesData.push_back({fShadow, {gShadow}});
+ filesData.push_back({fVel, {gVel}});
+
+ filesNoise.push_back({fDensity, {gDensity}});
+ if (mUsingColors) {
+ filesNoise.push_back({fColorR, {gColorR}});
+ filesNoise.push_back({fColorG, {gColorG}});
+ filesNoise.push_back({fColorB, {gColorB}});
+ }
+ if (mUsingFire) {
+ filesNoise.push_back({fFlame, {gFlame}});
+ filesNoise.push_back({fFuel, {gFuel}});
+ filesNoise.push_back({fReact, {gReact}});
}
}
+ else if (fileMode == FLUID_DOMAIN_CACHE_FILES_COMBINED) {
- if (mUsingFire) {
- file = getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_DOMAIN_FILE_FLAMENOISE, nformat, framenr);
- expected += 1;
- if (BLI_exists(file.c_str())) {
- result += updateGridFromFile(file, mFlameHigh, true);
- assert(result == expected);
+ gridsData.push_back(gShadow);
+ gridsData.push_back(gVel);
+
+ gridsNoise.push_back(gDensity);
+ if (mUsingColors) {
+ gridsNoise.push_back(gColorR);
+ gridsNoise.push_back(gColorG);
+ gridsNoise.push_back(gColorB);
+ }
+ if (mUsingFire) {
+ gridsNoise.push_back(gFlame);
+ gridsNoise.push_back(gFuel);
+ gridsNoise.push_back(gReact);
}
- file = getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_DOMAIN_FILE_FUELNOISE, nformat, framenr);
- expected += 1;
- if (BLI_exists(file.c_str())) {
- result += updateGridFromFile(file, mFuelHigh, true);
- assert(result == expected);
+ if (with_debug) {
+ assertGridItems(gridsData);
+ assertGridItems(gridsNoise);
}
+ filesData.push_back({fFluid, gridsData});
+ filesNoise.push_back({fNoise, gridsNoise});
+ }
- file = getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_DOMAIN_FILE_REACTNOISE, nformat, framenr);
- expected += 1;
- if (BLI_exists(file.c_str())) {
- result += updateGridFromFile(file, mReactHigh, true);
- assert(result == expected);
+ /* Update files from data directory. */
+ for (vector<FileItem>::iterator it = filesData.begin(); it != filesData.end(); ++it) {
+ FileItem item = *it;
+ if (BLI_exists(item.filename.c_str())) {
+ result += updateGridsFromFile(item.filename, item.grids);
+ assert(result);
+ }
+ }
+
+ /* Update files from noise directory. */
+ for (vector<FileItem>::iterator it = filesNoise.begin(); it != filesNoise.end(); ++it) {
+ FileItem item = *it;
+ if (BLI_exists(item.filename.c_str())) {
+ result += updateGridsFromFile(item.filename, item.grids);
+ assert(result);
}
}
- return mNoiseFromFile = (result == expected);
+ return mNoiseFromFile = result;
}
/* Dirty hack: Needed to format paths from python code that is run via PyRun_SimpleString */
-static std::string escapeSlashes(std::string const &s)
+static string escapeSlashes(string const &s)
{
- std::string result = "";
- for (std::string::const_iterator i = s.begin(), end = s.end(); i != end; ++i) {
+ string result = "";
+ for (string::const_iterator i = s.begin(), end = s.end(); i != end; ++i) {
unsigned char c = *i;
if (c == '\\')
result += "\\\\";
@@ -1402,21 +1365,20 @@ static std::string escapeSlashes(std::string const &s)
bool MANTA::writeConfiguration(FluidModifierData *mmd, int framenr)
{
if (with_debug)
- std::cout << "MANTA::writeConfiguration()" << std::endl;
+ cout << "MANTA::writeConfiguration()" << endl;
FluidDomainSettings *mds = mmd->domain;
- std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_CONFIG);
- std::string format = FLUID_DOMAIN_EXTENSION_UNI;
- std::string file = getFile(
- mmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_DOMAIN_FILE_CONFIG, format, framenr);
+ string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_CONFIG);
+ string format = FLUID_DOMAIN_EXTENSION_UNI;
+ string file = getFile(mmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_FILENAME_CONFIG, format, framenr);
/* Create 'config' subdir if it does not exist already. */
BLI_dir_create_recursive(directory.c_str());
gzFile gzf = (gzFile)BLI_gzopen(file.c_str(), "wb1"); // do some compression
if (!gzf) {
- std::cerr << "Fluid Error -- Cannot open file " << file << std::endl;
+ cerr << "Fluid Error -- Cannot open file " << file << endl;
return false;
}
@@ -1434,6 +1396,7 @@ bool MANTA::writeConfiguration(FluidModifierData *mmd, int framenr)
gzwrite(gzf, &mds->res_min, 3 * sizeof(int));
gzwrite(gzf, &mds->res_max, 3 * sizeof(int));
gzwrite(gzf, &mds->active_color, 3 * sizeof(float));
+ gzwrite(gzf, &mds->time_total, sizeof(int));
return (gzclose(gzf) == Z_OK);
}
@@ -1441,17 +1404,18 @@ bool MANTA::writeConfiguration(FluidModifierData *mmd, int framenr)
bool MANTA::writeData(FluidModifierData *mmd, int framenr)
{
if (with_debug)
- std::cout << "MANTA::writeData()" << std::endl;
+ cout << "MANTA::writeData()" << endl;
- std::ostringstream ss;
- std::vector<std::string> pythonCommands;
+ ostringstream ss;
+ vector<string> pythonCommands;
+ FluidDomainSettings *mds = mmd->domain;
- std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_DATA);
- std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format);
- std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format);
+ string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_DATA);
+ string dformat = getCacheFileEnding(mds->cache_data_format);
+ string pformat = getCacheFileEnding(mds->cache_particle_format);
- bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL);
- std::string resumable_cache = (final_cache) ? "False" : "True";
+ bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL);
+ string resumable_cache = (final_cache) ? "False" : "True";
ss.str("");
ss << "fluid_save_data_" << mCurrentID << "('" << escapeSlashes(directory) << "', " << framenr
@@ -1476,16 +1440,17 @@ bool MANTA::writeData(FluidModifierData *mmd, int framenr)
bool MANTA::writeNoise(FluidModifierData *mmd, int framenr)
{
if (with_debug)
- std::cout << "MANTA::writeNoise()" << std::endl;
+ cout << "MANTA::writeNoise()" << endl;
- std::ostringstream ss;
- std::vector<std::string> pythonCommands;
+ ostringstream ss;
+ vector<string> pythonCommands;
+ FluidDomainSettings *mds = mmd->domain;
- std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_NOISE);
- std::string nformat = getCacheFileEnding(mmd->domain->cache_noise_format);
+ string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_NOISE);
+ string nformat = getCacheFileEnding(mds->cache_noise_format);
- bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL);
- std::string resumable_cache = (final_cache) ? "False" : "True";
+ bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL);
+ string resumable_cache = (final_cache) ? "False" : "True";
if (mUsingSmoke && mUsingNoise) {
ss.str("");
@@ -1499,22 +1464,21 @@ bool MANTA::writeNoise(FluidModifierData *mmd, int framenr)
bool MANTA::readConfiguration(FluidModifierData *mmd, int framenr)
{
if (with_debug)
- std::cout << "MANTA::readConfiguration()" << std::endl;
+ cout << "MANTA::readConfiguration()" << endl;
FluidDomainSettings *mds = mmd->domain;
float dummy;
- std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_CONFIG);
- std::string format = FLUID_DOMAIN_EXTENSION_UNI;
- std::string file = getFile(
- mmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_DOMAIN_FILE_CONFIG, format, framenr);
+ string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_CONFIG);
+ string format = FLUID_DOMAIN_EXTENSION_UNI;
+ string file = getFile(mmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_FILENAME_CONFIG, format, framenr);
if (!hasConfig(mmd, framenr))
return false;
gzFile gzf = (gzFile)BLI_gzopen(file.c_str(), "rb"); // do some compression
if (!gzf) {
- std::cerr << "Fluid Error -- Cannot open file " << file << std::endl;
+ cerr << "Fluid Error -- Cannot open file " << file << endl;
return false;
}
@@ -1532,6 +1496,8 @@ bool MANTA::readConfiguration(FluidModifierData *mmd, int framenr)
gzread(gzf, &mds->res_min, 3 * sizeof(int));
gzread(gzf, &mds->res_max, 3 * sizeof(int));
gzread(gzf, &mds->active_color, 3 * sizeof(float));
+ gzread(gzf, &mds->time_total, sizeof(int));
+
mds->total_cells = mds->res[0] * mds->res[1] * mds->res[2];
return (gzclose(gzf) == Z_OK);
@@ -1540,21 +1506,22 @@ bool MANTA::readConfiguration(FluidModifierData *mmd, int framenr)
bool MANTA::readData(FluidModifierData *mmd, int framenr)
{
if (with_debug)
- std::cout << "MANTA::readData()" << std::endl;
+ cout << "MANTA::readData()" << endl;
if (!mUsingSmoke && !mUsingLiquid)
return false;
- std::ostringstream ss;
- std::vector<std::string> pythonCommands;
+ ostringstream ss;
+ vector<string> pythonCommands;
+ FluidDomainSettings *mds = mmd->domain;
bool result = true;
- std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_DATA);
- std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format);
- std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format);
+ string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_DATA);
+ string dformat = getCacheFileEnding(mds->cache_data_format);
+ string pformat = getCacheFileEnding(mds->cache_particle_format);
- bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL);
- std::string resumable_cache = (final_cache) ? "False" : "True";
+ bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL);
+ string resumable_cache = (final_cache) ? "False" : "True";
/* Sanity check: Are cache files present? */
if (!hasData(mmd, framenr))
@@ -1585,19 +1552,20 @@ bool MANTA::readData(FluidModifierData *mmd, int framenr)
bool MANTA::readNoise(FluidModifierData *mmd, int framenr)
{
if (with_debug)
- std::cout << "MANTA::readNoise()" << std::endl;
+ cout << "MANTA::readNoise()" << endl;
if (!mUsingSmoke || !mUsingNoise)
return false;
- std::ostringstream ss;
- std::vector<std::string> pythonCommands;
+ ostringstream ss;
+ vector<string> pythonCommands;
+ FluidDomainSettings *mds = mmd->domain;
- std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_NOISE);
- std::string nformat = getCacheFileEnding(mmd->domain->cache_noise_format);
+ string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_NOISE);
+ string nformat = getCacheFileEnding(mds->cache_noise_format);
- bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL);
- std::string resumable_cache = (final_cache) ? "False" : "True";
+ bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL);
+ string resumable_cache = (final_cache) ? "False" : "True";
/* Sanity check: Are cache files present? */
if (!hasNoise(mmd, framenr))
@@ -1617,17 +1585,18 @@ bool MANTA::readNoise(FluidModifierData *mmd, int framenr)
bool MANTA::readMesh(FluidModifierData *mmd, int framenr)
{
if (with_debug)
- std::cout << "MANTA::readMesh()" << std::endl;
+ cout << "MANTA::readMesh()" << endl;
if (!mUsingLiquid || !mUsingMesh)
return false;
- std::ostringstream ss;
- std::vector<std::string> pythonCommands;
+ ostringstream ss;
+ vector<string> pythonCommands;
+ FluidDomainSettings *mds = mmd->domain;
- std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_MESH);
- std::string mformat = getCacheFileEnding(mmd->domain->cache_mesh_format);
- std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format);
+ string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_MESH);
+ string mformat = getCacheFileEnding(mds->cache_mesh_format);
+ string dformat = getCacheFileEnding(mds->cache_data_format);
/* Sanity check: Are cache files present? */
if (!hasMesh(mmd, framenr))
@@ -1654,21 +1623,22 @@ bool MANTA::readMesh(FluidModifierData *mmd, int framenr)
bool MANTA::readParticles(FluidModifierData *mmd, int framenr)
{
if (with_debug)
- std::cout << "MANTA::readParticles()" << std::endl;
+ cout << "MANTA::readParticles()" << endl;
if (!mUsingLiquid)
return false;
if (!mUsingDrops && !mUsingBubbles && !mUsingFloats && !mUsingTracers)
return false;
- std::ostringstream ss;
- std::vector<std::string> pythonCommands;
+ ostringstream ss;
+ vector<string> pythonCommands;
+ FluidDomainSettings *mds = mmd->domain;
- std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_PARTICLES);
- std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format);
+ string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_PARTICLES);
+ string pformat = getCacheFileEnding(mds->cache_particle_format);
- bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL);
- std::string resumable_cache = (final_cache) ? "False" : "True";
+ bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL);
+ string resumable_cache = (final_cache) ? "False" : "True";
/* Sanity check: Are cache files present? */
if (!hasParticles(mmd, framenr))
@@ -1685,19 +1655,21 @@ bool MANTA::readParticles(FluidModifierData *mmd, int framenr)
bool MANTA::readGuiding(FluidModifierData *mmd, int framenr, bool sourceDomain)
{
if (with_debug)
- std::cout << "MANTA::readGuiding()" << std::endl;
+ cout << "MANTA::readGuiding()" << endl;
+
+ FluidDomainSettings *mds = mmd->domain;
if (!mUsingGuiding)
return false;
- if (!mmd->domain)
+ if (!mds)
return false;
- std::ostringstream ss;
- std::vector<std::string> pythonCommands;
+ ostringstream ss;
+ vector<string> pythonCommands;
- std::string directory = (sourceDomain) ? getDirectory(mmd, FLUID_DOMAIN_DIR_DATA) :
- getDirectory(mmd, FLUID_DOMAIN_DIR_GUIDE);
- std::string gformat = getCacheFileEnding(mmd->domain->cache_data_format);
+ string directory = (sourceDomain) ? getDirectory(mmd, FLUID_DOMAIN_DIR_DATA) :
+ getDirectory(mmd, FLUID_DOMAIN_DIR_GUIDE);
+ string gformat = getCacheFileEnding(mds->cache_data_format);
/* Sanity check: Are cache files present? */
if (!hasGuiding(mmd, framenr, sourceDomain))
@@ -1721,28 +1693,26 @@ bool MANTA::readGuiding(FluidModifierData *mmd, int framenr, bool sourceDomain)
bool MANTA::bakeData(FluidModifierData *mmd, int framenr)
{
if (with_debug)
- std::cout << "MANTA::bakeData()" << std::endl;
+ cout << "MANTA::bakeData()" << endl;
- std::string tmpString, finalString;
- std::ostringstream ss;
- std::vector<std::string> pythonCommands;
+ string tmpString, finalString;
+ ostringstream ss;
+ vector<string> pythonCommands;
+ FluidDomainSettings *mds = mmd->domain;
char cacheDirData[FILE_MAX], cacheDirGuiding[FILE_MAX];
cacheDirData[0] = '\0';
cacheDirGuiding[0] = '\0';
- std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format);
- std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format);
- std::string gformat = dformat; // Use same data format for guiding format
+ string dformat = getCacheFileEnding(mds->cache_data_format);
+ string pformat = getCacheFileEnding(mds->cache_particle_format);
+ string gformat = dformat; // Use same data format for guiding format
- BLI_path_join(cacheDirData,
- sizeof(cacheDirData),
- mmd->domain->cache_directory,
- FLUID_DOMAIN_DIR_DATA,
- nullptr);
+ BLI_path_join(
+ cacheDirData, sizeof(cacheDirData), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, nullptr);
BLI_path_join(cacheDirGuiding,
sizeof(cacheDirGuiding),
- mmd->domain->cache_directory,
+ mds->cache_directory,
FLUID_DOMAIN_DIR_GUIDE,
nullptr);
BLI_path_make_safe(cacheDirData);
@@ -1760,31 +1730,26 @@ bool MANTA::bakeData(FluidModifierData *mmd, int framenr)
bool MANTA::bakeNoise(FluidModifierData *mmd, int framenr)
{
if (with_debug)
- std::cout << "MANTA::bakeNoise()" << std::endl;
+ cout << "MANTA::bakeNoise()" << endl;
- std::ostringstream ss;
- std::vector<std::string> pythonCommands;
+ ostringstream ss;
+ vector<string> pythonCommands;
+ FluidDomainSettings *mds = mmd->domain;
char cacheDirData[FILE_MAX], cacheDirNoise[FILE_MAX];
cacheDirData[0] = '\0';
cacheDirNoise[0] = '\0';
- std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format);
- std::string nformat = getCacheFileEnding(mmd->domain->cache_noise_format);
+ string dformat = getCacheFileEnding(mds->cache_data_format);
+ string nformat = getCacheFileEnding(mds->cache_noise_format);
- bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL);
- std::string resumable_cache = (final_cache) ? "False" : "True";
+ bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL);
+ string resumable_cache = (final_cache) ? "False" : "True";
- BLI_path_join(cacheDirData,
- sizeof(cacheDirData),
- mmd->domain->cache_directory,
- FLUID_DOMAIN_DIR_DATA,
- nullptr);
- BLI_path_join(cacheDirNoise,
- sizeof(cacheDirNoise),
- mmd->domain->cache_directory,
- FLUID_DOMAIN_DIR_NOISE,
- nullptr);
+ BLI_path_join(
+ cacheDirData, sizeof(cacheDirData), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, nullptr);
+ BLI_path_join(
+ cacheDirNoise, sizeof(cacheDirNoise), mds->cache_directory, FLUID_DOMAIN_DIR_NOISE, nullptr);
BLI_path_make_safe(cacheDirData);
BLI_path_make_safe(cacheDirNoise);
@@ -1800,29 +1765,24 @@ bool MANTA::bakeNoise(FluidModifierData *mmd, int framenr)
bool MANTA::bakeMesh(FluidModifierData *mmd, int framenr)
{
if (with_debug)
- std::cout << "MANTA::bakeMesh()" << std::endl;
+ cout << "MANTA::bakeMesh()" << endl;
- std::ostringstream ss;
- std::vector<std::string> pythonCommands;
+ ostringstream ss;
+ vector<string> pythonCommands;
+ FluidDomainSettings *mds = mmd->domain;
char cacheDirData[FILE_MAX], cacheDirMesh[FILE_MAX];
cacheDirData[0] = '\0';
cacheDirMesh[0] = '\0';
- std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format);
- std::string mformat = getCacheFileEnding(mmd->domain->cache_mesh_format);
- std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format);
+ string dformat = getCacheFileEnding(mds->cache_data_format);
+ string mformat = getCacheFileEnding(mds->cache_mesh_format);
+ string pformat = getCacheFileEnding(mds->cache_particle_format);
- BLI_path_join(cacheDirData,
- sizeof(cacheDirData),
- mmd->domain->cache_directory,
- FLUID_DOMAIN_DIR_DATA,
- nullptr);
- BLI_path_join(cacheDirMesh,
- sizeof(cacheDirMesh),
- mmd->domain->cache_directory,
- FLUID_DOMAIN_DIR_MESH,
- nullptr);
+ BLI_path_join(
+ cacheDirData, sizeof(cacheDirData), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, nullptr);
+ BLI_path_join(
+ cacheDirMesh, sizeof(cacheDirMesh), mds->cache_directory, FLUID_DOMAIN_DIR_MESH, nullptr);
BLI_path_make_safe(cacheDirData);
BLI_path_make_safe(cacheDirMesh);
@@ -1838,29 +1798,27 @@ bool MANTA::bakeMesh(FluidModifierData *mmd, int framenr)
bool MANTA::bakeParticles(FluidModifierData *mmd, int framenr)
{
if (with_debug)
- std::cout << "MANTA::bakeParticles()" << std::endl;
+ cout << "MANTA::bakeParticles()" << endl;
- std::ostringstream ss;
- std::vector<std::string> pythonCommands;
+ ostringstream ss;
+ vector<string> pythonCommands;
+ FluidDomainSettings *mds = mmd->domain;
char cacheDirData[FILE_MAX], cacheDirParticles[FILE_MAX];
cacheDirData[0] = '\0';
cacheDirParticles[0] = '\0';
- std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format);
- std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format);
+ string dformat = getCacheFileEnding(mds->cache_data_format);
+ string pformat = getCacheFileEnding(mds->cache_particle_format);
- bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL);
- std::string resumable_cache = (final_cache) ? "False" : "True";
+ bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL);
+ string resumable_cache = (final_cache) ? "False" : "True";
- BLI_path_join(cacheDirData,
- sizeof(cacheDirData),
- mmd->domain->cache_directory,
- FLUID_DOMAIN_DIR_DATA,
- nullptr);
+ BLI_path_join(
+ cacheDirData, sizeof(cacheDirData), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, nullptr);
BLI_path_join(cacheDirParticles,
sizeof(cacheDirParticles),
- mmd->domain->cache_directory,
+ mds->cache_directory,
FLUID_DOMAIN_DIR_PARTICLES,
nullptr);
BLI_path_make_safe(cacheDirData);
@@ -1878,22 +1836,23 @@ bool MANTA::bakeParticles(FluidModifierData *mmd, int framenr)
bool MANTA::bakeGuiding(FluidModifierData *mmd, int framenr)
{
if (with_debug)
- std::cout << "MANTA::bakeGuiding()" << std::endl;
+ cout << "MANTA::bakeGuiding()" << endl;
- std::ostringstream ss;
- std::vector<std::string> pythonCommands;
+ ostringstream ss;
+ vector<string> pythonCommands;
+ FluidDomainSettings *mds = mmd->domain;
char cacheDirGuiding[FILE_MAX];
cacheDirGuiding[0] = '\0';
- std::string gformat = getCacheFileEnding(mmd->domain->cache_data_format);
+ string gformat = getCacheFileEnding(mds->cache_data_format);
- bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL);
- std::string resumable_cache = (final_cache) ? "False" : "True";
+ bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL);
+ string resumable_cache = (final_cache) ? "False" : "True";
BLI_path_join(cacheDirGuiding,
sizeof(cacheDirGuiding),
- mmd->domain->cache_directory,
+ mds->cache_directory,
FLUID_DOMAIN_DIR_GUIDE,
nullptr);
BLI_path_make_safe(cacheDirGuiding);
@@ -1908,8 +1867,8 @@ bool MANTA::bakeGuiding(FluidModifierData *mmd, int framenr)
bool MANTA::updateVariables(FluidModifierData *mmd)
{
- std::string tmpString, finalString;
- std::vector<std::string> pythonCommands;
+ string tmpString, finalString;
+ vector<string> pythonCommands;
tmpString += fluid_variables;
if (mUsingSmoke)
@@ -1939,13 +1898,15 @@ bool MANTA::updateVariables(FluidModifierData *mmd)
void MANTA::exportSmokeScript(FluidModifierData *mmd)
{
if (with_debug)
- std::cout << "MANTA::exportSmokeScript()" << std::endl;
+ cout << "MANTA::exportSmokeScript()" << endl;
char cacheDir[FILE_MAX] = "\0";
char cacheDirScript[FILE_MAX] = "\0";
+ FluidDomainSettings *mds = mmd->domain;
+
BLI_path_join(
- cacheDir, sizeof(cacheDir), mmd->domain->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, nullptr);
+ cacheDir, sizeof(cacheDir), mds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, nullptr);
BLI_path_make_safe(cacheDir);
/* Create 'script' subdir if it does not exist already */
BLI_dir_create_recursive(cacheDir);
@@ -1953,16 +1914,16 @@ void MANTA::exportSmokeScript(FluidModifierData *mmd)
cacheDirScript, sizeof(cacheDirScript), cacheDir, FLUID_DOMAIN_SMOKE_SCRIPT, nullptr);
BLI_path_make_safe(cacheDir);
- bool noise = mmd->domain->flags & FLUID_DOMAIN_USE_NOISE;
- bool heat = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_HEAT;
- bool colors = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_COLORS;
- bool fire = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_FIRE;
- bool obstacle = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE;
- bool guiding = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE;
- bool invel = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL;
- bool outflow = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW;
+ bool noise = mds->flags & FLUID_DOMAIN_USE_NOISE;
+ bool heat = mds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT;
+ bool colors = mds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS;
+ bool fire = mds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE;
+ bool obstacle = mds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE;
+ bool guiding = mds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE;
+ bool invel = mds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL;
+ bool outflow = mds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW;
- std::string manta_script;
+ string manta_script;
// Libraries
manta_script += header_libraries + manta_import;
@@ -2034,10 +1995,10 @@ void MANTA::exportSmokeScript(FluidModifierData *mmd)
manta_script += header_main + smoke_standalone + fluid_standalone;
// Fill in missing variables in script
- std::string final_script = MANTA::parseScript(manta_script, mmd);
+ string final_script = MANTA::parseScript(manta_script, mmd);
// Write script
- std::ofstream myfile;
+ ofstream myfile;
myfile.open(cacheDirScript);
myfile << final_script;
myfile.close();
@@ -2046,13 +2007,15 @@ void MANTA::exportSmokeScript(FluidModifierData *mmd)
void MANTA::exportLiquidScript(FluidModifierData *mmd)
{
if (with_debug)
- std::cout << "MANTA::exportLiquidScript()" << std::endl;
+ cout << "MANTA::exportLiquidScript()" << endl;
char cacheDir[FILE_MAX] = "\0";
char cacheDirScript[FILE_MAX] = "\0";
+ FluidDomainSettings *mds = mmd->domain;
+
BLI_path_join(
- cacheDir, sizeof(cacheDir), mmd->domain->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, nullptr);
+ cacheDir, sizeof(cacheDir), mds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, nullptr);
BLI_path_make_safe(cacheDir);
/* Create 'script' subdir if it does not exist already */
BLI_dir_create_recursive(cacheDir);
@@ -2060,18 +2023,18 @@ void MANTA::exportLiquidScript(FluidModifierData *mmd)
cacheDirScript, sizeof(cacheDirScript), cacheDir, FLUID_DOMAIN_LIQUID_SCRIPT, nullptr);
BLI_path_make_safe(cacheDirScript);
- bool mesh = mmd->domain->flags & FLUID_DOMAIN_USE_MESH;
- bool drops = mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY;
- bool bubble = mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE;
- bool floater = mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_FOAM;
- bool tracer = mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_TRACER;
- bool obstacle = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE;
- bool fractions = mmd->domain->flags & FLUID_DOMAIN_USE_FRACTIONS;
- bool guiding = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE;
- bool invel = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL;
- bool outflow = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW;
+ bool mesh = mds->flags & FLUID_DOMAIN_USE_MESH;
+ bool drops = mds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY;
+ bool bubble = mds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE;
+ bool floater = mds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM;
+ bool tracer = mds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER;
+ bool obstacle = mds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE;
+ bool fractions = mds->flags & FLUID_DOMAIN_USE_FRACTIONS;
+ bool guiding = mds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE;
+ bool invel = mds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL;
+ bool outflow = mds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW;
- std::string manta_script;
+ string manta_script;
// Libraries
manta_script += header_libraries + manta_import;
@@ -2141,10 +2104,10 @@ void MANTA::exportLiquidScript(FluidModifierData *mmd)
manta_script += header_main + liquid_standalone + fluid_standalone;
// Fill in missing variables in script
- std::string final_script = MANTA::parseScript(manta_script, mmd);
+ string final_script = MANTA::parseScript(manta_script, mmd);
// Write script
- std::ofstream myfile;
+ ofstream myfile;
myfile.open(cacheDirScript);
myfile << final_script;
myfile.close();
@@ -2157,14 +2120,12 @@ void MANTA::exportLiquidScript(FluidModifierData *mmd)
*
* Important! Return value: New reference or nullptr
* Caller of this function needs to handle reference count of returned object. */
-static PyObject *callPythonFunction(std::string varName,
- std::string functionName,
- bool isAttribute = false)
+static PyObject *callPythonFunction(string varName, string functionName, bool isAttribute = false)
{
if ((varName == "") || (functionName == "")) {
if (MANTA::with_debug)
- std::cout << "Missing Python variable name and/or function name -- name is: " << varName
- << ", function name is: " << functionName << std::endl;
+ cout << "Missing Python variable name and/or function name -- name is: " << varName
+ << ", function name is: " << functionName << endl;
return nullptr;
}
@@ -2217,8 +2178,8 @@ static void *pyObjectToPointer(PyObject *inputObject)
Py_DECREF(inputObject);
- std::string str(result);
- std::istringstream in(str);
+ string str(result);
+ istringstream in(str);
void *dataPointer = nullptr;
in >> dataPointer;
@@ -2265,11 +2226,11 @@ static long pyObjectToLong(PyObject *inputObject)
int MANTA::getFrame()
{
if (with_debug)
- std::cout << "MANTA::getFrame()" << std::endl;
+ cout << "MANTA::getFrame()" << endl;
- std::string func = "frame";
- std::string id = std::to_string(mCurrentID);
- std::string solver = "s" + id;
+ string func = "frame";
+ string id = to_string(mCurrentID);
+ string solver = "s" + id;
return pyObjectToLong(callPythonFunction(solver, func, true));
}
@@ -2277,11 +2238,11 @@ int MANTA::getFrame()
float MANTA::getTimestep()
{
if (with_debug)
- std::cout << "MANTA::getTimestep()" << std::endl;
+ cout << "MANTA::getTimestep()" << endl;
- std::string func = "timestep";
- std::string id = std::to_string(mCurrentID);
- std::string solver = "s" + id;
+ string func = "timestep";
+ string id = to_string(mCurrentID);
+ string solver = "s" + id;
return (float)pyObjectToDouble(callPythonFunction(solver, func, true));
}
@@ -2295,10 +2256,10 @@ bool MANTA::needsRealloc(FluidModifierData *mmd)
void MANTA::adaptTimestep()
{
if (with_debug)
- std::cout << "MANTA::adaptTimestep()" << std::endl;
+ cout << "MANTA::adaptTimestep()" << endl;
- std::vector<std::string> pythonCommands;
- std::ostringstream ss;
+ vector<string> pythonCommands;
+ ostringstream ss;
ss << "fluid_adapt_time_step_" << mCurrentID << "()";
pythonCommands.push_back(ss.str());
@@ -2306,14 +2267,14 @@ void MANTA::adaptTimestep()
runPythonString(pythonCommands);
}
-bool MANTA::updateMeshFromFile(std::string filename)
+bool MANTA::updateMeshFromFile(string filename)
{
- std::string fname(filename);
- std::string::size_type idx;
+ string fname(filename);
+ string::size_type idx;
idx = fname.rfind('.');
- if (idx != std::string::npos) {
- std::string extension = fname.substr(idx + 1);
+ if (idx != string::npos) {
+ string extension = fname.substr(idx + 1);
if (extension.compare("gz") == 0)
return updateMeshFromBobj(filename);
@@ -2322,27 +2283,25 @@ bool MANTA::updateMeshFromFile(std::string filename)
else if (extension.compare("uni") == 0)
return updateMeshFromUni(filename);
else
- std::cerr << "Fluid Error -- updateMeshFromFile(): Invalid file extension in file: "
- << filename << std::endl;
+ cerr << "Fluid Error -- updateMeshFromFile(): Invalid file extension in file: " << filename
+ << endl;
}
else {
- std::cerr << "Fluid Error -- updateMeshFromFile(): Unable to open file: " << filename
- << std::endl;
+ cerr << "Fluid Error -- updateMeshFromFile(): Unable to open file: " << filename << endl;
}
return false;
}
-bool MANTA::updateMeshFromBobj(std::string filename)
+bool MANTA::updateMeshFromBobj(string filename)
{
if (with_debug)
- std::cout << "MANTA::updateMeshFromBobj()" << std::endl;
+ cout << "MANTA::updateMeshFromBobj()" << endl;
gzFile gzf;
gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb1"); // do some compression
if (!gzf) {
- std::cerr << "Fluid Error -- updateMeshFromBobj(): Unable to open file: " << filename
- << std::endl;
+ cerr << "Fluid Error -- updateMeshFromBobj(): Unable to open file: " << filename << endl;
return false;
}
@@ -2351,15 +2310,14 @@ bool MANTA::updateMeshFromBobj(std::string filename)
// Num vertices
readBytes = gzread(gzf, &numBuffer, sizeof(int));
if (!readBytes) {
- std::cerr
- << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh vertices from "
- << filename << std::endl;
+ cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh vertices from "
+ << filename << endl;
gzclose(gzf);
return false;
}
if (with_debug)
- std::cout << "read mesh , num verts: " << numBuffer << " , in file: " << filename << std::endl;
+ cout << "read mesh , num verts: " << numBuffer << " , in file: " << filename << endl;
int numChunks = (int)(ceil((float)numBuffer / NODE_CHUNK));
int readLen, readStart, readEnd, k;
@@ -2380,8 +2338,8 @@ bool MANTA::updateMeshFromBobj(std::string filename)
readBytes = gzread(gzf, bufferVerts, readLen * sizeof(float) * 3);
if (!readBytes) {
- std::cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh vertices from "
- << filename << std::endl;
+ cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh vertices from "
+ << filename << endl;
MEM_freeN(bufferVerts);
gzclose(gzf);
return false;
@@ -2393,7 +2351,7 @@ bool MANTA::updateMeshFromBobj(std::string filename)
CLAMP(readEnd, 0, numBuffer);
k = 0;
- for (std::vector<MANTA::Node>::size_type j = readStart; j < readEnd; j++, k += 3) {
+ for (vector<MANTA::Node>::size_type j = readStart; j < readEnd; j++, k += 3) {
mMeshNodes->at(j).pos[0] = bufferVerts[k];
mMeshNodes->at(j).pos[1] = bufferVerts[k + 1];
mMeshNodes->at(j).pos[2] = bufferVerts[k + 2];
@@ -2406,15 +2364,14 @@ bool MANTA::updateMeshFromBobj(std::string filename)
// Num normals
readBytes = gzread(gzf, &numBuffer, sizeof(int));
if (!readBytes) {
- std::cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh normals from "
- << filename << std::endl;
+ cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh normals from "
+ << filename << endl;
gzclose(gzf);
return false;
}
if (with_debug)
- std::cout << "read mesh , num normals : " << numBuffer << " , in file: " << filename
- << std::endl;
+ cout << "read mesh , num normals : " << numBuffer << " , in file: " << filename << endl;
if (numBuffer) {
// Normals
@@ -2433,8 +2390,8 @@ bool MANTA::updateMeshFromBobj(std::string filename)
readBytes = gzread(gzf, bufferNormals, readLen * sizeof(float) * 3);
if (!readBytes) {
- std::cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh normals from "
- << filename << std::endl;
+ cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh normals from "
+ << filename << endl;
MEM_freeN(bufferNormals);
gzclose(gzf);
return false;
@@ -2446,7 +2403,7 @@ bool MANTA::updateMeshFromBobj(std::string filename)
CLAMP(readEnd, 0, numBuffer);
k = 0;
- for (std::vector<MANTA::Node>::size_type j = readStart; j < readEnd; j++, k += 3) {
+ for (vector<MANTA::Node>::size_type j = readStart; j < readEnd; j++, k += 3) {
mMeshNodes->at(j).normal[0] = bufferNormals[k];
mMeshNodes->at(j).normal[1] = bufferNormals[k + 1];
mMeshNodes->at(j).normal[2] = bufferNormals[k + 2];
@@ -2459,16 +2416,15 @@ bool MANTA::updateMeshFromBobj(std::string filename)
// Num triangles
readBytes = gzread(gzf, &numBuffer, sizeof(int));
if (!readBytes) {
- std::cerr
- << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh triangles from "
- << filename << std::endl;
+ cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh triangles from "
+ << filename << endl;
gzclose(gzf);
return false;
}
if (with_debug)
- std::cout << "Fluid: Read mesh , num triangles : " << numBuffer << " , in file: " << filename
- << std::endl;
+ cout << "Fluid: Read mesh , num triangles : " << numBuffer << " , in file: " << filename
+ << endl;
numChunks = (int)(ceil((float)numBuffer / TRIANGLE_CHUNK));
@@ -2488,8 +2444,8 @@ bool MANTA::updateMeshFromBobj(std::string filename)
readBytes = gzread(gzf, bufferTriangles, readLen * sizeof(int) * 3);
if (!readBytes) {
- std::cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh triangles from "
- << filename << std::endl;
+ cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh triangles from "
+ << filename << endl;
MEM_freeN(bufferTriangles);
gzclose(gzf);
return false;
@@ -2501,7 +2457,7 @@ bool MANTA::updateMeshFromBobj(std::string filename)
CLAMP(readEnd, 0, numBuffer);
k = 0;
- for (std::vector<MANTA::Triangle>::size_type j = readStart; j < readEnd; j++, k += 3) {
+ for (vector<MANTA::Triangle>::size_type j = readStart; j < readEnd; j++, k += 3) {
mMeshTriangles->at(j).c[0] = bufferTriangles[k];
mMeshTriangles->at(j).c[1] = bufferTriangles[k + 1];
mMeshTriangles->at(j).c[2] = bufferTriangles[k + 2];
@@ -2513,24 +2469,23 @@ bool MANTA::updateMeshFromBobj(std::string filename)
return (gzclose(gzf) == Z_OK);
}
-bool MANTA::updateMeshFromObj(std::string filename)
+bool MANTA::updateMeshFromObj(string filename)
{
if (with_debug)
- std::cout << "MANTA::updateMeshFromObj()" << std::endl;
+ cout << "MANTA::updateMeshFromObj()" << endl;
- std::ifstream ifs(filename);
+ ifstream ifs(filename);
float fbuffer[3];
int ibuffer[3];
int cntVerts = 0, cntNormals = 0, cntTris = 0;
if (!ifs.good()) {
- std::cerr << "Fluid Error -- updateMeshFromObj(): Unable to open file: " << filename
- << std::endl;
+ cerr << "Fluid Error -- updateMeshFromObj(): Unable to open file: " << filename << endl;
return false;
}
while (ifs.good() && !ifs.eof()) {
- std::string id;
+ string id;
ifs >> id;
if (id[0] == '#') {
@@ -2544,8 +2499,8 @@ bool MANTA::updateMeshFromObj(std::string filename)
else if (id == "vn") {
// normals
if (getNumVertices() != cntVerts) {
- std::cerr << "Fluid Error -- updateMeshFromObj(): Invalid number of mesh nodes in file: "
- << filename << std::endl;
+ cerr << "Fluid Error -- updateMeshFromObj(): Invalid number of mesh nodes in file: "
+ << filename << endl;
return false;
}
@@ -2568,20 +2523,20 @@ bool MANTA::updateMeshFromObj(std::string filename)
}
else if (id == "g") {
// group
- std::string group;
+ string group;
ifs >> group;
}
else if (id == "f") {
// face
- std::string face;
+ string face;
for (int i = 0; i < 3; i++) {
ifs >> face;
- if (face.find('/') != std::string::npos)
+ if (face.find('/') != string::npos)
face = face.substr(0, face.find('/')); // ignore other indices
int idx = atoi(face.c_str()) - 1;
if (idx < 0) {
- std::cerr << "Fluid Error -- updateMeshFromObj(): Invalid face encountered in file: "
- << filename << std::endl;
+ cerr << "Fluid Error -- updateMeshFromObj(): Invalid face encountered in file: "
+ << filename << endl;
return false;
}
ibuffer[i] = idx;
@@ -2603,10 +2558,10 @@ bool MANTA::updateMeshFromObj(std::string filename)
return true;
}
-bool MANTA::updateMeshFromUni(std::string filename)
+bool MANTA::updateMeshFromUni(string filename)
{
if (with_debug)
- std::cout << "MANTA::updateMeshFromUni()" << std::endl;
+ cout << "MANTA::updateMeshFromUni()" << endl;
gzFile gzf;
float fbuffer[4];
@@ -2614,8 +2569,7 @@ bool MANTA::updateMeshFromUni(std::string filename)
gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb1"); // do some compression
if (!gzf) {
- std::cerr << "Fluid Error -- updateMeshFromUni(): Unable to open file: " << filename
- << std::endl;
+ cerr << "Fluid Error -- updateMeshFromUni(): Unable to open file: " << filename << endl;
return false;
}
@@ -2623,13 +2577,13 @@ bool MANTA::updateMeshFromUni(std::string filename)
char file_magic[5] = {0, 0, 0, 0, 0};
readBytes = gzread(gzf, file_magic, 4);
if (!readBytes) {
- std::cerr << "Fluid Error -- updateMeshFromUni(): Unable to read header in file: " << filename
- << std::endl;
+ cerr << "Fluid Error -- updateMeshFromUni(): Unable to read header in file: " << filename
+ << endl;
gzclose(gzf);
return false;
}
- std::vector<pVel> *velocityPointer = mMeshVelocities;
+ vector<pVel> *velocityPointer = mMeshVelocities;
// mdata uni header
const int STR_LEN_PDATA = 256;
@@ -2645,19 +2599,18 @@ bool MANTA::updateMeshFromUni(std::string filename)
gzread(gzf, &timestamp, sizeof(unsigned long long));
if (with_debug)
- std::cout << "Fluid: Read " << ibuffer[0] << " vertices in file: " << filename << std::endl;
+ cout << "Fluid: Read " << ibuffer[0] << " vertices in file: " << filename << endl;
// Sanity checks
const int meshSize = sizeof(float) * 3 + sizeof(int);
if (!(bytesPerElement == meshSize) && (elementType == 0)) {
- std::cerr << "Fluid Error -- updateMeshFromUni(): Invalid header in file: " << filename
- << std::endl;
+ cerr << "Fluid Error -- updateMeshFromUni(): Invalid header in file: " << filename << endl;
gzclose(gzf);
return false;
}
if (!ibuffer[0]) { // Any vertices present?
- std::cerr << "Fluid Error -- updateMeshFromUni(): No vertices present in file: " << filename
- << std::endl;
+ cerr << "Fluid Error -- updateMeshFromUni(): No vertices present in file: " << filename
+ << endl;
gzclose(gzf);
return false;
}
@@ -2672,7 +2625,7 @@ bool MANTA::updateMeshFromUni(std::string filename)
velocityPointer->resize(numParticles);
MANTA::pVel *bufferPVel;
- for (std::vector<pVel>::iterator it = velocityPointer->begin(); it != velocityPointer->end();
+ for (vector<pVel>::iterator it = velocityPointer->begin(); it != velocityPointer->end();
++it) {
gzread(gzf, fbuffer, sizeof(float) * 3);
bufferPVel = (MANTA::pVel *)fbuffer;
@@ -2684,44 +2637,42 @@ bool MANTA::updateMeshFromUni(std::string filename)
return (gzclose(gzf) == Z_OK);
}
-bool MANTA::updateParticlesFromFile(std::string filename, bool isSecondarySys, bool isVelData)
+bool MANTA::updateParticlesFromFile(string filename, bool isSecondarySys, bool isVelData)
{
if (with_debug)
- std::cout << "MANTA::updateParticlesFromFile()" << std::endl;
+ cout << "MANTA::updateParticlesFromFile()" << endl;
- std::string fname(filename);
- std::string::size_type idx;
+ string fname(filename);
+ string::size_type idx;
idx = fname.rfind('.');
- if (idx != std::string::npos) {
- std::string extension = fname.substr(idx + 1);
+ if (idx != string::npos) {
+ string extension = fname.substr(idx + 1);
if (extension.compare("uni") == 0)
return updateParticlesFromUni(filename, isSecondarySys, isVelData);
else
- std::cerr << "Fluid Error -- updateParticlesFromFile(): Invalid file extension in file: "
- << filename << std::endl;
+ cerr << "Fluid Error -- updateParticlesFromFile(): Invalid file extension in file: "
+ << filename << endl;
return false;
}
else {
- std::cerr << "Fluid Error -- updateParticlesFromFile(): Unable to open file: " << filename
- << std::endl;
+ cerr << "Fluid Error -- updateParticlesFromFile(): Unable to open file: " << filename << endl;
return false;
}
}
-bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bool isVelData)
+bool MANTA::updateParticlesFromUni(string filename, bool isSecondarySys, bool isVelData)
{
if (with_debug)
- std::cout << "MANTA::updateParticlesFromUni()" << std::endl;
+ cout << "MANTA::updateParticlesFromUni()" << endl;
gzFile gzf;
int ibuffer[4];
gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb1"); // do some compression
if (!gzf) {
- std::cerr << "Fluid Error -- updateParticlesFromUni(): Unable to open file: " << filename
- << std::endl;
+ cerr << "Fluid Error -- updateParticlesFromUni(): Unable to open file: " << filename << endl;
return false;
}
@@ -2729,24 +2680,24 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo
char file_magic[5] = {0, 0, 0, 0, 0};
readBytes = gzread(gzf, file_magic, 4);
if (!readBytes) {
- std::cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read header in file: "
- << filename << std::endl;
+ cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read header in file: " << filename
+ << endl;
gzclose(gzf);
return false;
}
if (!strcmp(file_magic, "PB01")) {
- std::cerr << "Fluid Error -- updateParticlesFromUni(): Particle uni file format v01 not "
- "supported anymore."
- << std::endl;
+ cerr << "Fluid Error -- updateParticlesFromUni(): Particle uni file format v01 not "
+ "supported anymore."
+ << endl;
gzclose(gzf);
return false;
}
// Pointer to FLIP system or to secondary particle system
- std::vector<pData> *dataPointer = nullptr;
- std::vector<pVel> *velocityPointer = nullptr;
- std::vector<float> *lifePointer = nullptr;
+ vector<pData> *dataPointer = nullptr;
+ vector<pVel> *velocityPointer = nullptr;
+ vector<float> *lifePointer = nullptr;
if (isSecondarySys) {
dataPointer = mSndParticleData;
@@ -2772,19 +2723,19 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo
gzread(gzf, &timestamp, sizeof(unsigned long long));
if (with_debug)
- std::cout << "Fluid: Read " << ibuffer[0] << " particles in file: " << filename << std::endl;
+ cout << "Fluid: Read " << ibuffer[0] << " particles in file: " << filename << endl;
// Sanity checks
const int partSysSize = sizeof(float) * 3 + sizeof(int);
if (!(bytesPerElement == partSysSize) && (elementType == 0)) {
- std::cerr << "Fluid Error -- updateParticlesFromUni(): Invalid header in file: " << filename
- << std::endl;
+ cerr << "Fluid Error -- updateParticlesFromUni(): Invalid header in file: " << filename
+ << endl;
gzclose(gzf);
return false;
}
if (!ibuffer[0]) { // Any particles present?
if (with_debug)
- std::cout << "Fluid: No particles present in file: " << filename << std::endl;
+ cout << "Fluid: No particles present in file: " << filename << endl;
gzclose(gzf);
return true; // return true since having no particles in a cache file is valid
}
@@ -2812,9 +2763,8 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo
readBytes = gzread(gzf, bufferPData, readLen * sizeof(pData));
if (!readBytes) {
- std::cerr
- << "Fluid Error -- updateParticlesFromUni(): Unable to read particle data in file: "
- << filename << std::endl;
+ cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read particle data in file: "
+ << filename << endl;
MEM_freeN(bufferPData);
gzclose(gzf);
return false;
@@ -2826,7 +2776,7 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo
CLAMP(readEnd, 0, numParticles);
int k = 0;
- for (std::vector<MANTA::pData>::size_type j = readStart; j < readEnd; j++, k++) {
+ for (vector<MANTA::pData>::size_type j = readStart; j < readEnd; j++, k++) {
dataPointer->at(j).pos[0] = bufferPData[k].pos[0];
dataPointer->at(j).pos[1] = bufferPData[k].pos[1];
dataPointer->at(j).pos[2] = bufferPData[k].pos[2];
@@ -2853,9 +2803,9 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo
readBytes = gzread(gzf, bufferPVel, readLen * sizeof(pVel));
if (!readBytes) {
- std::cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read particle velocities "
- "in file: "
- << filename << std::endl;
+ cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read particle velocities "
+ "in file: "
+ << filename << endl;
MEM_freeN(bufferPVel);
gzclose(gzf);
return false;
@@ -2867,7 +2817,7 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo
CLAMP(readEnd, 0, numParticles);
int k = 0;
- for (std::vector<MANTA::pVel>::size_type j = readStart; j < readEnd; j++, k++) {
+ for (vector<MANTA::pVel>::size_type j = readStart; j < readEnd; j++, k++) {
velocityPointer->at(j).pos[0] = bufferPVel[k].pos[0];
velocityPointer->at(j).pos[1] = bufferPVel[k].pos[1];
velocityPointer->at(j).pos[2] = bufferPVel[k].pos[2];
@@ -2892,9 +2842,8 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo
readBytes = gzread(gzf, bufferPLife, readLen * sizeof(float));
if (!readBytes) {
- std::cerr
- << "Fluid Error -- updateParticlesFromUni(): Unable to read particle life in file: "
- << filename << std::endl;
+ cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read particle life in file: "
+ << filename << endl;
MEM_freeN(bufferPLife);
gzclose(gzf);
return false;
@@ -2906,7 +2855,7 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo
CLAMP(readEnd, 0, numParticles);
int k = 0;
- for (std::vector<float>::size_type j = readStart; j < readEnd; j++, k++) {
+ for (vector<float>::size_type j = readStart; j < readEnd; j++, k++) {
lifePointer->at(j) = bufferPLife[k];
}
todoParticles -= readLen;
@@ -2916,141 +2865,158 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo
return (gzclose(gzf) == Z_OK);
}
-bool MANTA::updateGridFromFile(std::string filename, float *grid, bool isNoise)
+bool MANTA::updateGridsFromFile(string filename, vector<GridItem> grids)
{
if (with_debug)
- std::cout << "MANTA::updateGridFromFile()" << std::endl;
+ cout << "MANTA::updateGridsFromFile()" << endl;
- if (!grid) {
- std::cerr << "Fluid Error -- updateGridFromFile(): Cannot read into uninitialized grid (grid "
- "is null)."
- << std::endl;
+ if (grids.empty()) {
+ cerr << "Fluid Error -- updateGridsFromFile(): Cannot read into uninitialized grid vector."
+ << endl;
return false;
}
- std::string fname(filename);
- std::string::size_type idx;
+ string fname(filename);
+ string::size_type idx;
idx = fname.rfind('.');
- if (idx != std::string::npos) {
- std::string extension = fname.substr(idx + 1);
+ if (idx != string::npos) {
+ string extension = fname.substr(idx);
- if (extension.compare("uni") == 0)
- return updateGridFromUni(filename, grid, isNoise);
+ if (extension.compare(FLUID_DOMAIN_EXTENSION_UNI) == 0) {
+ return updateGridsFromUni(filename, grids);
+ }
#if OPENVDB == 1
- else if (extension.compare("vdb") == 0)
- return updateGridFromVDB(filename, grid, isNoise);
+ else if (extension.compare(FLUID_DOMAIN_EXTENSION_OPENVDB) == 0) {
+ return updateGridsFromVDB(filename, grids);
+ }
#endif
- else if (extension.compare("raw") == 0)
- return updateGridFromRaw(filename, grid, isNoise);
- else
- std::cerr << "Fluid Error -- updateGridFromFile(): Invalid file extension in file: "
- << filename << std::endl;
+ else if (extension.compare(FLUID_DOMAIN_EXTENSION_RAW) == 0) {
+ return updateGridsFromRaw(filename, grids);
+ }
+ else {
+ cerr << "Fluid Error -- updateGridsFromFile(): Invalid file extension in file: " << filename
+ << endl;
+ }
return false;
}
else {
- std::cerr << "Fluid Error -- updateGridFromFile(): Unable to open file: " << filename
- << std::endl;
+ cerr << "Fluid Error -- updateGridsFromFile(): Unable to open file: " << filename << endl;
return false;
}
}
-bool MANTA::updateGridFromUni(std::string filename, float *grid, bool isNoise)
+bool MANTA::updateGridsFromUni(string filename, vector<GridItem> grids)
{
if (with_debug)
- std::cout << "MANTA::updateGridFromUni()" << std::endl;
+ cout << "MANTA::updateGridsFromUni()" << endl;
gzFile gzf;
+ int expectedBytes = 0, readBytes = 0;
int ibuffer[4];
gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb1");
if (!gzf) {
- std::cerr << "Fluid Error -- updateGridFromUni(): Unable to open file: " << filename
- << std::endl;
+ cerr << "Fluid Error -- updateGridsFromUni(): Unable to open file: " << filename << endl;
return false;
}
- int readBytes = 0;
char file_magic[5] = {0, 0, 0, 0, 0};
readBytes = gzread(gzf, file_magic, 4);
if (!readBytes) {
- std::cerr << "Fluid Error -- updateGridFromUni(): Unable to read header in file: " << filename
- << std::endl;
+ cerr << "Fluid Error -- updateGridsFromUni(): Invalid header in file: " << filename << endl;
gzclose(gzf);
return false;
}
-
- if (!strcmp(file_magic, "DDF2")) {
- std::cerr
- << "Fluid Error -- updateGridFromUni(): Grid uni file format DDF2 not supported anymore."
- << std::endl;
+ if (!strcmp(file_magic, "DDF2") || !strcmp(file_magic, "MNT1") || !strcmp(file_magic, "MNT2")) {
+ cerr << "Fluid Error -- updateGridsFromUni(): Unsupported header in file: " << filename
+ << endl;
gzclose(gzf);
return false;
}
- if (!strcmp(file_magic, "MNT1")) {
- std::cerr
- << "Fluid Error -- updateGridFromUni(): Grid uni file format MNT1 not supported anymore."
- << std::endl;
- gzclose(gzf);
- return false;
- }
-
- if (!strcmp(file_magic, "MNT2")) {
- std::cerr
- << "Fluid Error -- updateGridFromUni(): Grid uni file format MNT2 not supported anymore."
- << std::endl;
- gzclose(gzf);
- return false;
- }
+ if (!strcmp(file_magic, "MNT3")) {
- // grid uni header
- const int STR_LEN_GRID = 252;
- int elementType, bytesPerElement; // data type info
- char info[STR_LEN_GRID]; // mantaflow build information
- int dimT; // optionally store forth dimension for 4d grids
- unsigned long long timestamp; // creation time
+ // grid uni header
+ const int STR_LEN_GRID = 252;
+ int elementType, bytesPerElement; // data type info
+ char info[STR_LEN_GRID]; // mantaflow build information
+ int dimT; // optionally store forth dimension for 4d grids
+ unsigned long long timestamp; // creation time
+
+ // read grid header
+ gzread(gzf, &ibuffer, sizeof(int) * 4); // dimX, dimY, dimZ, gridType
+ gzread(gzf, &elementType, sizeof(int));
+ gzread(gzf, &bytesPerElement, sizeof(int));
+ gzread(gzf, &info, sizeof(info));
+ gzread(gzf, &dimT, sizeof(int));
+ gzread(gzf, &timestamp, sizeof(unsigned long long));
- // read grid header
- gzread(gzf, &ibuffer, sizeof(int) * 4); // dimX, dimY, dimZ, gridType
- gzread(gzf, &elementType, sizeof(int));
- gzread(gzf, &bytesPerElement, sizeof(int));
- gzread(gzf, &info, sizeof(info));
- gzread(gzf, &dimT, sizeof(int));
- gzread(gzf, &timestamp, sizeof(unsigned long long));
-
- int resX = (isNoise) ? mResXNoise : mResX;
- int resY = (isNoise) ? mResYNoise : mResY;
- int resZ = (isNoise) ? mResZNoise : mResZ;
+ if (with_debug)
+ cout << "Fluid: Read " << ibuffer[3] << " grid type in file: " << filename << endl;
+
+ for (vector<GridItem>::iterator gIter = grids.begin(); gIter != grids.end(); ++gIter) {
+ GridItem gridItem = *gIter;
+ void **pointerList = gridItem.pointer;
+ int type = gridItem.type;
+ int *res = gridItem.res;
+ assert(pointerList[0]);
+ assert(res[0] == res[0] && res[1] == res[1] && res[2] == res[2]);
+ UNUSED_VARS(res);
+
+ switch (type) {
+ case FLUID_DOMAIN_GRID_VEC3F: {
+ assert(pointerList[1] && pointerList[2]);
+ float **fpointers = (float **)pointerList;
+ expectedBytes = sizeof(float) * 3 * ibuffer[0] * ibuffer[1] * ibuffer[2];
+ readBytes = 0;
+ for (int i = 0; i < ibuffer[0] * ibuffer[1] * ibuffer[2]; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ readBytes += gzread(gzf, fpointers[j], sizeof(float));
+ ++fpointers[j];
+ }
+ }
+ break;
+ }
+ case FLUID_DOMAIN_GRID_FLOAT: {
+ float **fpointers = (float **)pointerList;
+ expectedBytes = sizeof(float) * ibuffer[0] * ibuffer[1] * ibuffer[2];
+ readBytes = gzread(
+ gzf, fpointers[0], sizeof(float) * ibuffer[0] * ibuffer[1] * ibuffer[2]);
+ break;
+ }
+ default: {
+ cerr << "Fluid Error -- Unknown grid type" << endl;
+ }
+ }
- if (with_debug)
- std::cout << "Fluid: Read " << ibuffer[3] << " grid type in file: " << filename << std::endl;
+ if (!readBytes) {
+ cerr << "Fluid Error -- updateGridFromRaw(): Unable to read raw file: " << filename
+ << endl;
+ gzclose(gzf);
+ return false;
+ }
+ assert(expectedBytes == readBytes);
+ UNUSED_VARS(expectedBytes);
- // Sanity checks
- if (ibuffer[0] != resX || ibuffer[1] != resY || ibuffer[2] != resZ) {
- std::cout << "Fluid: Grid dim doesn't match, read: (" << ibuffer[0] << ", " << ibuffer[1]
- << ", " << ibuffer[2] << ") vs setup: (" << resX << ", " << resY << ", " << resZ
- << ")" << std::endl;
+ if (with_debug)
+ cout << "Fluid: Read successfully: " << filename << endl;
+ }
+ }
+ else {
+ cerr << "Fluid Error -- updateGridsFromUni(): Unknown header in file: " << filename << endl;
gzclose(gzf);
return false;
}
- // Actual data reading
- if (!strcmp(file_magic, "MNT3")) {
- gzread(gzf, grid, sizeof(float) * ibuffer[0] * ibuffer[1] * ibuffer[2]);
- }
-
- if (with_debug)
- std::cout << "Fluid: Read successfully: " << filename << std::endl;
-
return (gzclose(gzf) == Z_OK);
}
#if OPENVDB == 1
-bool MANTA::updateGridFromVDB(std::string filename, float *grid, bool isNoise)
+bool MANTA::updateGridsFromVDB(string filename, vector<GridItem> grids)
{
if (with_debug)
- std::cout << "MANTA::updateGridFromVDB()" << std::endl;
+ cout << "MANTA::updateGridsFromVDB()" << endl;
openvdb::initialize();
openvdb::io::File file(filename);
@@ -3058,67 +3024,191 @@ bool MANTA::updateGridFromVDB(std::string filename, float *grid, bool isNoise)
file.open();
}
catch (const openvdb::IoError &) {
- std::cerr << "Fluid Error -- updateGridFromVDB(): IOError, invalid OpenVDB file: " << filename
- << std::endl;
+ cerr << "Fluid Error -- updateGridsFromVDB(): IOError, invalid OpenVDB file: " << filename
+ << endl;
+ return false;
+ }
+ if (grids.empty()) {
+ cerr << "Fluid Error -- updateGridsFromVDB(): No grids found in grid vector" << endl;
return false;
}
+ unordered_map<string, openvdb::FloatGrid::Accessor> floatAccessors;
+ unordered_map<string, openvdb::Vec3SGrid::Accessor> vec3fAccessors;
openvdb::GridBase::Ptr baseGrid;
- for (openvdb::io::File::NameIterator nameIter = file.beginName(); nameIter != file.endName();
- ++nameIter) {
- baseGrid = file.readGrid(nameIter.gridName());
- break;
+
+ /* Get accessors to all grids in this OpenVDB file.*/
+ for (vector<GridItem>::iterator gIter = grids.begin(); gIter != grids.end(); ++gIter) {
+ GridItem gridItem = *gIter;
+ string itemName = gridItem.name;
+ int itemType = gridItem.type;
+
+ for (openvdb::io::File::NameIterator nameIter = file.beginName(); nameIter != file.endName();
+ ++nameIter) {
+ string vdbName = nameIter.gridName();
+ bool nameMatch = !itemName.compare(vdbName);
+
+ /* Support for <= 2.83: If file has only one grid in it, use that grid. */
+ openvdb::io::File::NameIterator peekNext = nameIter;
+ bool onlyGrid = (++peekNext == file.endName());
+ if (onlyGrid) {
+ vdbName = itemName;
+ }
+
+ if (nameMatch || onlyGrid) {
+ baseGrid = file.readGrid(nameIter.gridName());
+
+ switch (itemType) {
+ case FLUID_DOMAIN_GRID_VEC3F: {
+ openvdb::Vec3SGrid::Ptr gridVDB = openvdb::gridPtrCast<openvdb::Vec3SGrid>(baseGrid);
+ openvdb::Vec3SGrid::Accessor vdbAccessor = gridVDB->getAccessor();
+ vec3fAccessors.emplace(vdbName, vdbAccessor);
+ break;
+ }
+ case FLUID_DOMAIN_GRID_FLOAT: {
+ openvdb::FloatGrid::Ptr gridVDB = openvdb::gridPtrCast<openvdb::FloatGrid>(baseGrid);
+ openvdb::FloatGrid::Accessor vdbAccessor = gridVDB->getAccessor();
+ floatAccessors.emplace(vdbName, vdbAccessor);
+ break;
+ }
+ default: {
+ cerr << "Fluid Error -- Unknown grid type" << endl;
+ }
+ }
+ }
+ else {
+ cerr << "Fluid Error -- Could not read grid from file" << endl;
+ return false;
+ }
+ }
}
file.close();
- openvdb::FloatGrid::Ptr gridVDB = openvdb::gridPtrCast<openvdb::FloatGrid>(baseGrid);
- openvdb::FloatGrid::Accessor accessor = gridVDB->getAccessor();
-
- int resX = (isNoise) ? mResXNoise : mResX;
- int resY = (isNoise) ? mResYNoise : mResY;
- int resZ = (isNoise) ? mResZNoise : mResZ;
size_t index = 0;
- for (int z = 0; z < resZ; ++z) {
- for (int y = 0; y < resY; ++y) {
- for (int x = 0; x < resX; ++x, ++index) {
+
+ /* Use res of first grid for grid loop. All grids must be same size anyways. */
+ vector<GridItem>::iterator gIter = grids.begin();
+ int *res = (*gIter).res;
+
+ for (int z = 0; z < res[2]; ++z) {
+ for (int y = 0; y < res[1]; ++y) {
+ for (int x = 0; x < res[0]; ++x, ++index) {
openvdb::Coord xyz(x, y, z);
- float v = accessor.getValue(xyz);
- grid[index] = v;
+
+ for (vector<GridItem>::iterator gIter = grids.begin(); gIter != grids.end(); ++gIter) {
+ GridItem gridItem = *gIter;
+ void **pointerList = gridItem.pointer;
+ int type = gridItem.type;
+ int *res = gridItem.res;
+ assert(pointerList[0]);
+ assert(res[0] == res[0] && res[1] == res[1] && res[2] == res[2]);
+ UNUSED_VARS(res);
+
+ switch (type) {
+ case FLUID_DOMAIN_GRID_VEC3F: {
+ unordered_map<string, openvdb::Vec3SGrid::Accessor>::iterator it;
+ it = vec3fAccessors.find(gridItem.name);
+ if (it == vec3fAccessors.end()) {
+ cerr << "Fluid Error -- '" << gridItem.name << "' not in vdb grid map" << endl;
+ return false;
+ }
+ openvdb::Vec3f v = it->second.getValue(xyz);
+
+ assert(pointerList[1] && pointerList[2]);
+ float **fpointers = (float **)pointerList;
+ for (int j = 0; j < 3; ++j) {
+ (fpointers[j])[index] = (float)v[j];
+ }
+ break;
+ }
+ case FLUID_DOMAIN_GRID_FLOAT: {
+ unordered_map<string, openvdb::FloatGrid::Accessor>::iterator it;
+ it = floatAccessors.find(gridItem.name);
+ if (it == floatAccessors.end()) {
+ cerr << "Fluid Error -- '" << gridItem.name << "' not in vdb grid map" << endl;
+ return false;
+ }
+ float v = it->second.getValue(xyz);
+ float **fpointers = (float **)pointerList;
+ (fpointers[0])[index] = v;
+ break;
+ }
+ default: {
+ cerr << "Fluid Error -- Unknown grid type" << endl;
+ }
+ }
+ }
}
}
}
+ if (with_debug)
+ cout << "Fluid: Read successfully: " << filename << endl;
+
return true;
}
#endif
-bool MANTA::updateGridFromRaw(std::string filename, float *grid, bool isNoise)
+bool MANTA::updateGridsFromRaw(string filename, vector<GridItem> grids)
{
if (with_debug)
- std::cout << "MANTA::updateGridFromRaw()" << std::endl;
+ cout << "MANTA::updateGridsFromRaw()" << endl;
gzFile gzf;
int expectedBytes, readBytes;
gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb");
if (!gzf) {
- std::cout << "MANTA::updateGridFromRaw(): unable to open file" << std::endl;
+ cout << "MANTA::updateGridsFromRaw(): unable to open file" << endl;
return false;
}
- int resX = (isNoise) ? mResXNoise : mResX;
- int resY = (isNoise) ? mResYNoise : mResY;
- int resZ = (isNoise) ? mResZNoise : mResZ;
+ for (vector<GridItem>::iterator gIter = grids.begin(); gIter != grids.end(); ++gIter) {
+ GridItem gridItem = *gIter;
+ void **pointerList = gridItem.pointer;
+ int type = gridItem.type;
+ int *res = gridItem.res;
+ assert(pointerList[0]);
+ assert(res[0] == res[0] && res[1] == res[1] && res[2] == res[2]);
+ UNUSED_VARS(res);
+
+ switch (type) {
+ case FLUID_DOMAIN_GRID_VEC3F: {
+ assert(pointerList[1] && pointerList[2]);
+ float **fpointers = (float **)pointerList;
+ expectedBytes = sizeof(float) * 3 * res[0] * res[1] * res[2];
+ readBytes = 0;
+ for (int i = 0; i < res[0] * res[1] * res[2]; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ readBytes += gzread(gzf, fpointers[j], sizeof(float));
+ ++fpointers[j];
+ }
+ }
+ break;
+ }
+ case FLUID_DOMAIN_GRID_FLOAT: {
+ float **fpointers = (float **)pointerList;
+ expectedBytes = sizeof(float) * res[0] * res[1] * res[2];
+ readBytes = gzread(gzf, fpointers[0], expectedBytes);
+ break;
+ }
+ default: {
+ cerr << "Fluid Error -- Unknown grid type" << endl;
+ }
+ }
+
+ if (!readBytes) {
+ cerr << "Fluid Error -- updateGridsFromRaw(): Unable to read raw file: " << filename << endl;
+ gzclose(gzf);
+ return false;
+ }
+ assert(expectedBytes == readBytes);
- expectedBytes = sizeof(float) * resX * resY * resZ;
- readBytes = gzread(gzf, grid, expectedBytes);
- if (!readBytes) {
- std::cerr << "Fluid Error -- updateGridFromRaw(): Unable to read raw file: " << filename
- << std::endl;
- gzclose(gzf);
- return false;
+ if (with_debug)
+ cout << "Fluid: Read successfully: " << filename << endl;
}
- assert(expectedBytes == readBytes);
+ if (with_debug)
+ cout << "Fluid: Read successfully: " << filename << endl;
return (gzclose(gzf) == Z_OK);
}
@@ -3126,25 +3216,25 @@ bool MANTA::updateGridFromRaw(std::string filename, float *grid, bool isNoise)
void MANTA::updatePointers()
{
if (with_debug)
- std::cout << "MANTA::updatePointers()" << std::endl;
-
- std::string func = "getDataPointer";
- std::string funcNodes = "getNodesDataPointer";
- std::string funcTris = "getTrisDataPointer";
-
- std::string id = std::to_string(mCurrentID);
- std::string solver = "s" + id;
- std::string parts = "pp" + id;
- std::string snd = "sp" + id;
- std::string mesh = "sm" + id;
- std::string mesh2 = "mesh" + id;
- std::string noise = "sn" + id;
- std::string solver_ext = "_" + solver;
- std::string parts_ext = "_" + parts;
- std::string snd_ext = "_" + snd;
- std::string mesh_ext = "_" + mesh;
- std::string mesh_ext2 = "_" + mesh2;
- std::string noise_ext = "_" + noise;
+ cout << "MANTA::updatePointers()" << endl;
+
+ string func = "getDataPointer";
+ string funcNodes = "getNodesDataPointer";
+ string funcTris = "getTrisDataPointer";
+
+ string id = to_string(mCurrentID);
+ string solver = "s" + id;
+ string parts = "pp" + id;
+ string snd = "sp" + id;
+ string mesh = "sm" + id;
+ string mesh2 = "mesh" + id;
+ string noise = "sn" + id;
+ string solver_ext = "_" + solver;
+ string parts_ext = "_" + parts;
+ string snd_ext = "_" + snd;
+ string mesh_ext = "_" + mesh;
+ string mesh_ext2 = "_" + mesh2;
+ string noise_ext = "_" + noise;
mFlags = (int *)pyObjectToPointer(callPythonFunction("flags" + solver_ext, func));
mPhiIn = (float *)pyObjectToPointer(callPythonFunction("phiIn" + solver_ext, func));
@@ -3231,27 +3321,27 @@ void MANTA::updatePointers()
}
if (mUsingLiquid) {
mPhi = (float *)pyObjectToPointer(callPythonFunction("phi" + solver_ext, func));
- mFlipParticleData = (std::vector<pData> *)pyObjectToPointer(
+ mFlipParticleData = (vector<pData> *)pyObjectToPointer(
callPythonFunction("pp" + solver_ext, func));
- mFlipParticleVelocity = (std::vector<pVel> *)pyObjectToPointer(
+ mFlipParticleVelocity = (vector<pVel> *)pyObjectToPointer(
callPythonFunction("pVel" + parts_ext, func));
}
if (mUsingLiquid && mUsingMesh) {
- mMeshNodes = (std::vector<Node> *)pyObjectToPointer(
+ mMeshNodes = (vector<Node> *)pyObjectToPointer(
callPythonFunction("mesh" + mesh_ext, funcNodes));
- mMeshTriangles = (std::vector<Triangle> *)pyObjectToPointer(
+ mMeshTriangles = (vector<Triangle> *)pyObjectToPointer(
callPythonFunction("mesh" + mesh_ext, funcTris));
}
if (mUsingLiquid && mUsingMVel) {
- mMeshVelocities = (std::vector<pVel> *)pyObjectToPointer(
+ mMeshVelocities = (vector<pVel> *)pyObjectToPointer(
callPythonFunction("mVel" + mesh_ext2, func));
}
if (mUsingLiquid && (mUsingDrops | mUsingBubbles | mUsingFloats | mUsingTracers)) {
- mSndParticleData = (std::vector<pData> *)pyObjectToPointer(
+ mSndParticleData = (vector<pData> *)pyObjectToPointer(
callPythonFunction("ppSnd" + snd_ext, func));
- mSndParticleVelocity = (std::vector<pVel> *)pyObjectToPointer(
+ mSndParticleVelocity = (vector<pVel> *)pyObjectToPointer(
callPythonFunction("pVelSnd" + parts_ext, func));
- mSndParticleLife = (std::vector<float> *)pyObjectToPointer(
+ mSndParticleLife = (vector<float> *)pyObjectToPointer(
callPythonFunction("pLifeSnd" + parts_ext, func));
}
@@ -3264,50 +3354,49 @@ void MANTA::updatePointers()
bool MANTA::hasConfig(FluidModifierData *mmd, int framenr)
{
- std::string extension = FLUID_DOMAIN_EXTENSION_UNI;
+ string extension = FLUID_DOMAIN_EXTENSION_UNI;
return BLI_exists(
- getFile(mmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_DOMAIN_FILE_CONFIG, extension, framenr).c_str());
+ getFile(mmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_FILENAME_CONFIG, extension, framenr).c_str());
}
bool MANTA::hasData(FluidModifierData *mmd, int framenr)
{
- std::string filename = (mUsingSmoke) ? FLUID_DOMAIN_FILE_DENSITY : FLUID_DOMAIN_FILE_PP;
- std::string extension = getCacheFileEnding(mmd->domain->cache_data_format);
+ string filename = (mUsingSmoke) ? FLUID_FILENAME_DENSITY : FLUID_FILENAME_PP;
+ string extension = getCacheFileEnding(mmd->domain->cache_data_format);
return BLI_exists(getFile(mmd, FLUID_DOMAIN_DIR_DATA, filename, extension, framenr).c_str());
}
bool MANTA::hasNoise(FluidModifierData *mmd, int framenr)
{
- std::string extension = getCacheFileEnding(mmd->domain->cache_noise_format);
+ string extension = getCacheFileEnding(mmd->domain->cache_noise_format);
return BLI_exists(
- getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_DOMAIN_FILE_DENSITYNOISE, extension, framenr)
+ getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_FILENAME_DENSITYNOISE, extension, framenr)
.c_str());
}
bool MANTA::hasMesh(FluidModifierData *mmd, int framenr)
{
- std::string extension = getCacheFileEnding(mmd->domain->cache_mesh_format);
+ string extension = getCacheFileEnding(mmd->domain->cache_mesh_format);
return BLI_exists(
- getFile(mmd, FLUID_DOMAIN_DIR_MESH, FLUID_DOMAIN_FILE_MESH, extension, framenr).c_str());
+ getFile(mmd, FLUID_DOMAIN_DIR_MESH, FLUID_FILENAME_MESH, extension, framenr).c_str());
}
bool MANTA::hasParticles(FluidModifierData *mmd, int framenr)
{
- std::string extension = getCacheFileEnding(mmd->domain->cache_particle_format);
+ string extension = getCacheFileEnding(mmd->domain->cache_particle_format);
return BLI_exists(
- getFile(mmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_DOMAIN_FILE_PPSND, extension, framenr)
- .c_str());
+ getFile(mmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_FILENAME_PPSND, extension, framenr).c_str());
}
bool MANTA::hasGuiding(FluidModifierData *mmd, int framenr, bool sourceDomain)
{
- std::string subdirectory = (sourceDomain) ? FLUID_DOMAIN_DIR_DATA : FLUID_DOMAIN_DIR_GUIDE;
- std::string filename = (sourceDomain) ? FLUID_DOMAIN_FILE_VEL : FLUID_DOMAIN_FILE_GUIDEVEL;
- std::string extension = getCacheFileEnding(mmd->domain->cache_data_format);
+ string subdirectory = (sourceDomain) ? FLUID_DOMAIN_DIR_DATA : FLUID_DOMAIN_DIR_GUIDE;
+ string filename = (sourceDomain) ? FLUID_FILENAME_VELOCITY : FLUID_FILENAME_GUIDEVEL;
+ string extension = getCacheFileEnding(mmd->domain->cache_data_format);
return BLI_exists(getFile(mmd, subdirectory, filename, extension, framenr).c_str());
}
-std::string MANTA::getDirectory(FluidModifierData *mmd, std::string subdirectory)
+string MANTA::getDirectory(FluidModifierData *mmd, string subdirectory)
{
char directory[FILE_MAX];
BLI_path_join(
@@ -3316,15 +3405,12 @@ std::string MANTA::getDirectory(FluidModifierData *mmd, std::string subdirectory
return directory;
}
-std::string MANTA::getFile(FluidModifierData *mmd,
- std::string subdirectory,
- std::string fname,
- std::string extension,
- int framenr)
+string MANTA::getFile(
+ FluidModifierData *mmd, string subdirectory, string fname, string extension, int framenr)
{
char targetFile[FILE_MAX];
- std::string path = getDirectory(mmd, subdirectory);
- std::string filename = fname + extension;
+ string path = getDirectory(mmd, subdirectory);
+ string filename = fname + extension;
BLI_join_dirfile(targetFile, sizeof(targetFile), path.c_str(), filename.c_str());
BLI_path_frame(targetFile, framenr, 0);
return targetFile;
diff --git a/intern/mantaflow/intern/MANTA_main.h b/intern/mantaflow/intern/MANTA_main.h
index 5c40fdf7dd8..6a8484c75d9 100644
--- a/intern/mantaflow/intern/MANTA_main.h
+++ b/intern/mantaflow/intern/MANTA_main.h
@@ -27,8 +27,14 @@
#include <atomic>
#include <cassert>
#include <string>
+#include <unordered_map>
#include <vector>
+using std::atomic;
+using std::string;
+using std::unordered_map;
+using std::vector;
+
struct MANTA {
public:
MANTA(int *res, struct FluidModifierData *mmd);
@@ -54,25 +60,38 @@ struct MANTA {
int flags;
} Triangle;
+ // Cache helper typedefs
+ typedef struct GridItem {
+ void **pointer; /* Array of pointers for this grid.*/
+ int type;
+ int *res;
+ string name;
+ } GridItem;
+
+ typedef struct FileItem {
+ string filename;
+ vector<GridItem> grids;
+ } FileItem;
+
// Manta step, handling everything
void step(struct FluidModifierData *mmd, int startFrame);
// Grid initialization functions
- void initHeat(struct FluidModifierData *mmd);
- void initFire(struct FluidModifierData *mmd);
- void initColors(struct FluidModifierData *mmd);
- void initFireHigh(struct FluidModifierData *mmd);
- void initColorsHigh(struct FluidModifierData *mmd);
- void initLiquid(FluidModifierData *mmd);
- void initLiquidMesh(FluidModifierData *mmd);
- void initObstacle(FluidModifierData *mmd);
- void initCurvature(FluidModifierData *mmd);
- void initGuiding(FluidModifierData *mmd);
- void initFractions(FluidModifierData *mmd);
- void initInVelocity(FluidModifierData *mmd);
- void initOutflow(FluidModifierData *mmd);
- void initSndParts(FluidModifierData *mmd);
- void initLiquidSndParts(FluidModifierData *mmd);
+ void initHeat(struct FluidModifierData *mmd = NULL);
+ void initFire(struct FluidModifierData *mmd = NULL);
+ void initColors(struct FluidModifierData *mmd = NULL);
+ void initFireHigh(struct FluidModifierData *mmd = NULL);
+ void initColorsHigh(struct FluidModifierData *mmd = NULL);
+ void initLiquid(FluidModifierData *mmd = NULL);
+ void initLiquidMesh(FluidModifierData *mmd = NULL);
+ void initObstacle(FluidModifierData *mmd = NULL);
+ void initCurvature(FluidModifierData *mmd = NULL);
+ void initGuiding(FluidModifierData *mmd = NULL);
+ void initFractions(FluidModifierData *mmd = NULL);
+ void initInVelocity(FluidModifierData *mmd = NULL);
+ void initOutflow(FluidModifierData *mmd = NULL);
+ void initSndParts(FluidModifierData *mmd = NULL);
+ void initLiquidSndParts(FluidModifierData *mmd = NULL);
// Pointer transfer: Mantaflow -> Blender
void updatePointers();
@@ -415,7 +434,7 @@ struct MANTA {
return mPhi;
}
- static std::atomic<int> solverID;
+ static atomic<int> solverID;
static int with_debug; // on or off (1 or 0), also sets manta debug level
// Mesh getters
@@ -742,6 +761,8 @@ struct MANTA {
size_t mTotalCellsMesh;
size_t mTotalCellsParticles;
+ unordered_map<string, string> mRNAMap;
+
int mCurrentID;
bool mUsingHeat;
@@ -854,45 +875,46 @@ struct MANTA {
float *mPhi;
// Mesh fields
- std::vector<Node> *mMeshNodes;
- std::vector<Triangle> *mMeshTriangles;
- std::vector<pVel> *mMeshVelocities;
+ vector<Node> *mMeshNodes;
+ vector<Triangle> *mMeshTriangles;
+ vector<pVel> *mMeshVelocities;
// Particle fields
- std::vector<pData> *mFlipParticleData;
- std::vector<pVel> *mFlipParticleVelocity;
-
- std::vector<pData> *mSndParticleData;
- std::vector<pVel> *mSndParticleVelocity;
- std::vector<float> *mSndParticleLife;
-
- void initDomain(struct FluidModifierData *mmd);
- void initNoise(struct FluidModifierData *mmd);
- void initMesh(struct FluidModifierData *mmd);
- void initSmoke(struct FluidModifierData *mmd);
- void initSmokeNoise(struct FluidModifierData *mmd);
+ vector<pData> *mFlipParticleData;
+ vector<pVel> *mFlipParticleVelocity;
+
+ vector<pData> *mSndParticleData;
+ vector<pVel> *mSndParticleVelocity;
+ vector<float> *mSndParticleLife;
+
+ void initializeRNAMap(struct FluidModifierData *mmd = NULL);
+ void initDomain(struct FluidModifierData *mmd = NULL);
+ void initNoise(struct FluidModifierData *mmd = NULL);
+ void initMesh(struct FluidModifierData *mmd = NULL);
+ void initSmoke(struct FluidModifierData *mmd = NULL);
+ void initSmokeNoise(struct FluidModifierData *mmd = NULL);
void initializeMantaflow();
void terminateMantaflow();
- bool runPythonString(std::vector<std::string> commands);
- std::string getRealValue(const std::string &varName, FluidModifierData *mmd);
- std::string parseLine(const std::string &line, FluidModifierData *mmd);
- std::string parseScript(const std::string &setup_string, FluidModifierData *mmd = NULL);
- bool updateMeshFromBobj(std::string filename);
- bool updateMeshFromObj(std::string filename);
- bool updateMeshFromUni(std::string filename);
- bool updateParticlesFromUni(std::string filename, bool isSecondarySys, bool isVelData);
- bool updateGridFromUni(std::string filename, float *grid, bool isNoise);
- bool updateGridFromVDB(std::string filename, float *grid, bool isNoise);
- bool updateGridFromRaw(std::string filename, float *grid, bool isNoise);
- bool updateMeshFromFile(std::string filename);
- bool updateParticlesFromFile(std::string filename, bool isSecondarySys, bool isVelData);
- bool updateGridFromFile(std::string filename, float *grid, bool isNoise);
- std::string getDirectory(struct FluidModifierData *mmd, std::string subdirectory);
- std::string getFile(struct FluidModifierData *mmd,
- std::string subdirectory,
- std::string fname,
- std::string extension,
- int framenr);
+ bool runPythonString(vector<string> commands);
+ string getRealValue(const string &varName);
+ string parseLine(const string &line);
+ string parseScript(const string &setup_string, FluidModifierData *mmd = NULL);
+ bool updateMeshFromBobj(string filename);
+ bool updateMeshFromObj(string filename);
+ bool updateMeshFromUni(string filename);
+ bool updateParticlesFromUni(string filename, bool isSecondarySys, bool isVelData);
+ bool updateGridsFromUni(string filename, vector<GridItem> grids);
+ bool updateGridsFromVDB(string filename, vector<GridItem> grids);
+ bool updateGridsFromRaw(string filename, vector<GridItem> grids);
+ bool updateMeshFromFile(string filename);
+ bool updateParticlesFromFile(string filename, bool isSecondarySys, bool isVelData);
+ bool updateGridsFromFile(string filename, vector<GridItem> grids);
+ string getDirectory(struct FluidModifierData *mmd, string subdirectory);
+ string getFile(struct FluidModifierData *mmd,
+ string subdirectory,
+ string fname,
+ string extension,
+ int framenr);
};
#endif
diff --git a/intern/mantaflow/intern/strings/fluid_script.h b/intern/mantaflow/intern/strings/fluid_script.h
index dd2111db7d7..cf99717c102 100644
--- a/intern/mantaflow/intern/strings/fluid_script.h
+++ b/intern/mantaflow/intern/strings/fluid_script.h
@@ -92,7 +92,7 @@ const std::string fluid_variables =
mantaMsg('Fluid variables')\n\
dim_s$ID$ = $SOLVER_DIM$\n\
res_s$ID$ = $RES$\n\
-gravity_s$ID$ = vec3($GRAVITY_X$, $GRAVITY_Y$, $GRAVITY_Z$)\n\
+gravity_s$ID$ = vec3($GRAVITY_X$, $GRAVITY_Y$, $GRAVITY_Z$) # in SI unit (e.g. m/s^2)\n\
gs_s$ID$ = vec3($RESX$, $RESY$, $RESZ$)\n\
maxVel_s$ID$ = 0\n\
\n\
@@ -115,9 +115,16 @@ using_speedvectors_s$ID$ = $USING_SPEEDVECTORS$\n\
using_diffusion_s$ID$ = $USING_DIFFUSION$\n\
\n\
# Fluid time params\n\
+timeScale_s$ID$ = $TIME_SCALE$\n\
timeTotal_s$ID$ = $TIME_TOTAL$\n\
timePerFrame_s$ID$ = $TIME_PER_FRAME$\n\
-frameLength_s$ID$ = $FRAME_LENGTH$\n\
+\n\
+# In Blender fluid.c: frame_length = DT_DEFAULT * (25.0 / fps) * time_scale\n\
+# with DT_DEFAULT = 0.1\n\
+frameLength_s$ID$ = $FRAME_LENGTH$\n\
+frameLengthUnscaled_s$ID$ = frameLength_s$ID$ / timeScale_s$ID$\n\
+frameLengthRaw_s$ID$ = 0.1 * 25 # dt = 0.1 at 25 fps\n\
+\n\
dt0_s$ID$ = $DT$\n\
cflCond_s$ID$ = $CFL$\n\
timestepsMin_s$ID$ = $TIMESTEPS_MIN$\n\
@@ -132,8 +139,29 @@ end_frame_s$ID$ = $END_FRAME$\n\
domainSize_s$ID$ = $FLUID_DOMAIN_SIZE$ # longest domain side in meters\n\
viscosity_s$ID$ = $FLUID_VISCOSITY$ / (domainSize_s$ID$*domainSize_s$ID$) # kinematic viscosity in m^2/s\n\
\n\
-# Factor to convert blender velocities to manta velocities\n\
-toMantaUnitsFac_s$ID$ = (1.0 / (1.0 / res_s$ID$))\n # = dt/dx * 1/dt ";
+# Factors to convert Blender units to Manta units\n\
+ratioMetersToRes_s$ID$ = float(domainSize_s$ID$) / float(res_s$ID$) # [meters / cells]\n\
+mantaMsg('1 Mantaflow cell is ' + str(ratioMetersToRes_s$ID$) + ' Blender length units long.')\n\
+\n\
+ratioResToBLength_s$ID$ = float(res_s$ID$) / float(domainSize_s$ID$) # [cells / blength] (blength: cm, m, or km, ... )\n\
+mantaMsg('1 Blender length unit is ' + str(ratioResToBLength_s$ID$) + ' Mantaflow cells long.')\n\
+\n\
+ratioBTimeToTimstep_s$ID$ = float(1) / float(frameLengthRaw_s$ID$) # the time within 1 blender time unit, see also fluid.c\n\
+mantaMsg('1 Blender time unit is ' + str(ratioBTimeToTimstep_s$ID$) + ' Mantaflow time units long.')\n\
+\n\
+ratioFrameToFramelength_s$ID$ = float(1) / float(frameLengthUnscaled_s$ID$ ) # the time within 1 frame\n\
+mantaMsg('frame / frameLength is ' + str(ratioFrameToFramelength_s$ID$) + ' Mantaflow time units long.')\n\
+\n\
+scaleAcceleration_s$ID$ = ratioResToBLength_s$ID$ * (ratioBTimeToTimstep_s$ID$**2)# [meters/btime^2] to [cells/timestep^2] (btime: sec, min, or h, ...)\n\
+mantaMsg('scaleAcceleration is ' + str(scaleAcceleration_s$ID$))\n\
+\n\
+scaleSpeedFrames_s$ID$ = ratioResToBLength_s$ID$ * ratioFrameToFramelength_s$ID$ # [blength/frame] to [cells/frameLength]\n\
+mantaMsg('scaleSpeed is ' + str(scaleSpeedFrames_s$ID$))\n\
+\n\
+scaleSpeedTime_s$ID$ = ratioResToBLength_s$ID$ * ratioBTimeToTimstep_s$ID$ # [blength/btime] to [cells/frameLength]\n\
+mantaMsg('scaleSpeedTime is ' + str(scaleSpeedTime_s$ID$))\n\
+\n\
+gravity_s$ID$ *= scaleAcceleration_s$ID$ # scale from world acceleration to cell based acceleration\n";
const std::string fluid_variables_noise =
"\n\
@@ -231,7 +259,7 @@ const std::string fluid_alloc =
"\n\
mantaMsg('Fluid alloc data')\n\
flags_s$ID$ = s$ID$.create(FlagGrid)\n\
-vel_s$ID$ = s$ID$.create(MACGrid)\n\
+vel_s$ID$ = s$ID$.create(MACGrid, name='$NAME_VELOCITY$')\n\
velTmp_s$ID$ = s$ID$.create(MACGrid)\n\
x_vel_s$ID$ = s$ID$.create(RealGrid)\n\
y_vel_s$ID$ = s$ID$.create(RealGrid)\n\
@@ -342,17 +370,16 @@ def fluid_pre_step_$ID$():\n\
y_obvel_s$ID$.safeDivide(numObs_s$ID$)\n\
z_obvel_s$ID$.safeDivide(numObs_s$ID$)\n\
\n\
- x_obvel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\
- y_obvel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\
- z_obvel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\
- \n\
+ x_obvel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
+ y_obvel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
+ z_obvel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
copyRealToVec3(sourceX=x_obvel_s$ID$, sourceY=y_obvel_s$ID$, sourceZ=z_obvel_s$ID$, target=obvelC_s$ID$)\n\
\n\
# translate invels (world space) to grid space\n\
if using_invel_s$ID$:\n\
- x_invel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\
- y_invel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\
- z_invel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\
+ x_invel_s$ID$.multConst(scaleSpeedTime_s$ID$)\n\
+ y_invel_s$ID$.multConst(scaleSpeedTime_s$ID$)\n\
+ z_invel_s$ID$.multConst(scaleSpeedTime_s$ID$)\n\
copyRealToVec3(sourceX=x_invel_s$ID$, sourceY=y_invel_s$ID$, sourceZ=z_invel_s$ID$, target=invelC_s$ID$)\n\
\n\
if using_guiding_s$ID$:\n\
@@ -362,9 +389,9 @@ def fluid_pre_step_$ID$():\n\
velT_s$ID$.multConst(vec3(gamma_sg$ID$))\n\
\n\
# translate external forces (world space) to grid space\n\
- x_force_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\
- y_force_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\
- z_force_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\
+ x_force_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
+ y_force_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
+ z_force_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
copyRealToVec3(sourceX=x_force_s$ID$, sourceY=y_force_s$ID$, sourceZ=z_force_s$ID$, target=forces_s$ID$)\n\
\n\
# If obstacle has velocity, i.e. is a moving obstacle, switch to dynamic preconditioner\n\
@@ -531,7 +558,7 @@ def bake_noise_process_$ID$(framenr, format_data, format_noise, path_data, path_
\n\
sn$ID$.frame = framenr\n\
sn$ID$.frameLength = frameLength_s$ID$\n\
- sn$ID$.timeTotal = abs(framenr - start_frame_s$ID$) * frameLength_s$ID$\n\
+ sn$ID$.timeTotal = timeTotal_s$ID$\n\
sn$ID$.timestep = frameLength_s$ID$ # no adaptive timestep for noise\n\
\n\
smoke_step_noise_$ID$(framenr)\n\
@@ -549,7 +576,7 @@ def bake_mesh_process_$ID$(framenr, format_data, format_mesh, format_particles,
\n\
sm$ID$.frame = framenr\n\
sm$ID$.frameLength = frameLength_s$ID$\n\
- sm$ID$.timeTotal = abs(framenr - start_frame_s$ID$) * frameLength_s$ID$\n\
+ sm$ID$.timeTotal = timeTotal_s$ID$\n\
sm$ID$.timestep = frameLength_s$ID$ # no adaptive timestep for mesh\n\
\n\
#if using_smoke_s$ID$:\n\
@@ -573,7 +600,7 @@ def bake_particles_process_$ID$(framenr, format_data, format_particles, path_dat
\n\
sp$ID$.frame = framenr\n\
sp$ID$.frameLength = frameLength_s$ID$\n\
- sp$ID$.timeTotal = abs(framenr - start_frame_s$ID$) * frameLength_s$ID$\n\
+ sp$ID$.timeTotal = timeTotal_s$ID$\n\
sp$ID$.timestep = frameLength_s$ID$ # no adaptive timestep for particles\n\
\n\
#if using_smoke_s$ID$:\n\
@@ -598,10 +625,9 @@ def bake_guiding_process_$ID$(framenr, format_guiding, path_guiding, resumable):
y_guidevel_s$ID$.safeDivide(numGuides_s$ID$)\n\
z_guidevel_s$ID$.safeDivide(numGuides_s$ID$)\n\
\n\
- x_guidevel_s$ID$.multConst(Real(toMantaUnitsFac_s$ID$))\n\
- y_guidevel_s$ID$.multConst(Real(toMantaUnitsFac_s$ID$))\n\
- z_guidevel_s$ID$.multConst(Real(toMantaUnitsFac_s$ID$))\n\
- \n\
+ x_guidevel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
+ y_guidevel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
+ z_guidevel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
copyRealToVec3(sourceX=x_guidevel_s$ID$, sourceY=y_guidevel_s$ID$, sourceZ=z_guidevel_s$ID$, target=guidevelC_s$ID$)\n\
\n\
mantaMsg('Extrapolating guiding velocity')\n\
diff --git a/intern/mantaflow/intern/strings/liquid_script.h b/intern/mantaflow/intern/strings/liquid_script.h
index 57f0cbc20b7..e9777eb9cda 100644
--- a/intern/mantaflow/intern/strings/liquid_script.h
+++ b/intern/mantaflow/intern/strings/liquid_script.h
@@ -68,7 +68,7 @@ c_s_sp$ID$ = 0.4 # classification constant for snd parts\n\
c_b_sp$ID$ = 0.77 # classification constant for snd parts\n\
pot_radius_sp$ID$ = $SNDPARTICLE_POTENTIAL_RADIUS$\n\
update_radius_sp$ID$ = $SNDPARTICLE_UPDATE_RADIUS$\n\
-scaleFromManta_sp$ID$ = $FLUID_DOMAIN_SIZE$ / float(res_s$ID$) # resize factor for snd parts\n";
+using_snd_pushout_sp$ID$ = $SNDPARTICLE_BOUNDARY_PUSHOUT$\n";
//////////////////////////////////////////////////////////////////////
// GRIDS & MESH & PARTICLESYSTEM
@@ -268,7 +268,7 @@ def liquid_step_$ID$():\n\
velOld_s$ID$.copyFrom(vel_s$ID$)\n\
\n\
# forces & pressure solve\n\
- addGravity(flags=flags_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$)\n\
+ addGravity(flags=flags_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, scale=False)\n\
\n\
mantaMsg('Adding external forces')\n\
addForceField(flags=flags_s$ID$, vel=vel_s$ID$, force=forces_s$ID$)\n\
@@ -380,10 +380,10 @@ def liquid_step_particles_$ID$():\n\
flags_sp$ID$.updateFromLevelset(levelset=phi_sp$ID$)\n\
\n\
# Actual secondary particle simulation\n\
- flipComputeSecondaryParticlePotentials(potTA=trappedAir_sp$ID$, potWC=waveCrest_sp$ID$, potKE=kineticEnergy_sp$ID$, neighborRatio=neighborRatio_sp$ID$, flags=flags_sp$ID$, v=vel_sp$ID$, normal=normal_sp$ID$, phi=phi_sp$ID$, radius=pot_radius_sp$ID$, tauMinTA=tauMin_ta_sp$ID$, tauMaxTA=tauMax_ta_sp$ID$, tauMinWC=tauMin_wc_sp$ID$, tauMaxWC=tauMax_wc_sp$ID$, tauMinKE=tauMin_k_sp$ID$, tauMaxKE=tauMax_k_sp$ID$, scaleFromManta=scaleFromManta_sp$ID$)\n\
- flipSampleSecondaryParticles(mode='single', flags=flags_sp$ID$, v=vel_sp$ID$, pts_sec=ppSnd_sp$ID$, v_sec=pVelSnd_pp$ID$, l_sec=pLifeSnd_pp$ID$, lMin=lMin_sp$ID$, lMax=lMax_sp$ID$, potTA=trappedAir_sp$ID$, potWC=waveCrest_sp$ID$, potKE=kineticEnergy_sp$ID$, neighborRatio=neighborRatio_sp$ID$, c_s=c_s_sp$ID$, c_b=c_b_sp$ID$, k_ta=k_ta_sp$ID$, k_wc=k_wc_sp$ID$, dt=sp$ID$.timestep)\n\
- flipUpdateSecondaryParticles(mode='linear', pts_sec=ppSnd_sp$ID$, v_sec=pVelSnd_pp$ID$, l_sec=pLifeSnd_pp$ID$, f_sec=pForceSnd_pp$ID$, flags=flags_sp$ID$, v=vel_sp$ID$, neighborRatio=neighborRatio_sp$ID$, radius=update_radius_sp$ID$, gravity=gravity_s$ID$, k_b=k_b_sp$ID$, k_d=k_d_sp$ID$, c_s=c_s_sp$ID$, c_b=c_b_sp$ID$, dt=sp$ID$.timestep)\n\
- if $SNDPARTICLE_BOUNDARY_PUSHOUT$:\n\
+ flipComputeSecondaryParticlePotentials(potTA=trappedAir_sp$ID$, potWC=waveCrest_sp$ID$, potKE=kineticEnergy_sp$ID$, neighborRatio=neighborRatio_sp$ID$, flags=flags_sp$ID$, v=vel_sp$ID$, normal=normal_sp$ID$, phi=phi_sp$ID$, radius=pot_radius_sp$ID$, tauMinTA=tauMin_ta_sp$ID$, tauMaxTA=tauMax_ta_sp$ID$, tauMinWC=tauMin_wc_sp$ID$, tauMaxWC=tauMax_wc_sp$ID$, tauMinKE=tauMin_k_sp$ID$, tauMaxKE=tauMax_k_sp$ID$, scaleFromManta=ratioMetersToRes_s$ID$)\n\
+ flipSampleSecondaryParticles(mode='single', flags=flags_sp$ID$, v=vel_sp$ID$, pts_sec=ppSnd_sp$ID$, v_sec=pVelSnd_pp$ID$, l_sec=pLifeSnd_pp$ID$, lMin=lMin_sp$ID$, lMax=lMax_sp$ID$, potTA=trappedAir_sp$ID$, potWC=waveCrest_sp$ID$, potKE=kineticEnergy_sp$ID$, neighborRatio=neighborRatio_sp$ID$, c_s=c_s_sp$ID$, c_b=c_b_sp$ID$, k_ta=k_ta_sp$ID$, k_wc=k_wc_sp$ID$)\n\
+ flipUpdateSecondaryParticles(mode='linear', pts_sec=ppSnd_sp$ID$, v_sec=pVelSnd_pp$ID$, l_sec=pLifeSnd_pp$ID$, f_sec=pForceSnd_pp$ID$, flags=flags_sp$ID$, v=vel_sp$ID$, neighborRatio=neighborRatio_sp$ID$, radius=update_radius_sp$ID$, gravity=gravity_s$ID$, scale=False, k_b=k_b_sp$ID$, k_d=k_d_sp$ID$, c_s=c_s_sp$ID$, c_b=c_b_sp$ID$)\n\
+ if using_snd_pushout_sp$ID$:\n\
pushOutofObs(parts=ppSnd_sp$ID$, flags=flags_sp$ID$, phiObs=phiObs_sp$ID$, shift=1.0)\n\
flipDeleteParticlesInObstacle(pts=ppSnd_sp$ID$, flags=flags_sp$ID$) # delete particles inside obstacle and outflow cells\n\
\n\
diff --git a/intern/mantaflow/intern/strings/smoke_script.h b/intern/mantaflow/intern/strings/smoke_script.h
index fdb58543cec..72d5e20b58b 100644
--- a/intern/mantaflow/intern/strings/smoke_script.h
+++ b/intern/mantaflow/intern/strings/smoke_script.h
@@ -81,10 +81,10 @@ using_fire_s$ID$ = True\n";
const std::string smoke_alloc =
"\n\
mantaMsg('Smoke alloc')\n\
-shadow_s$ID$ = s$ID$.create(RealGrid)\n\
+shadow_s$ID$ = s$ID$.create(RealGrid, name='$NAME_SHADOW$')\n\
emission_s$ID$ = s$ID$.create(RealGrid)\n\
emissionIn_s$ID$ = s$ID$.create(RealGrid)\n\
-density_s$ID$ = s$ID$.create(RealGrid)\n\
+density_s$ID$ = s$ID$.create(RealGrid, name='$NAME_DENSITY$')\n\
densityIn_s$ID$ = s$ID$.create(RealGrid)\n\
heat_s$ID$ = None # allocated dynamically\n\
heatIn_s$ID$ = None\n\
@@ -108,7 +108,7 @@ const std::string smoke_alloc_noise =
"\n\
mantaMsg('Smoke alloc noise')\n\
vel_sn$ID$ = sn$ID$.create(MACGrid)\n\
-density_sn$ID$ = sn$ID$.create(RealGrid)\n\
+density_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_DENSITYNOISE$')\n\
phiIn_sn$ID$ = sn$ID$.create(LevelsetGrid)\n\
phiOut_sn$ID$ = sn$ID$.create(LevelsetGrid)\n\
phiObs_sn$ID$ = sn$ID$.create(LevelsetGrid)\n\
@@ -157,9 +157,9 @@ if 'color_g_s$ID$' in globals(): del color_g_s$ID$\n\
if 'color_b_s$ID$' in globals(): del color_b_s$ID$\n\
\n\
mantaMsg('Allocating colors')\n\
-color_r_s$ID$ = s$ID$.create(RealGrid)\n\
-color_g_s$ID$ = s$ID$.create(RealGrid)\n\
-color_b_s$ID$ = s$ID$.create(RealGrid)\n\
+color_r_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORR$')\n\
+color_g_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORG$')\n\
+color_b_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORB$')\n\
color_r_in_s$ID$ = s$ID$.create(RealGrid)\n\
color_g_in_s$ID$ = s$ID$.create(RealGrid)\n\
color_b_in_s$ID$ = s$ID$.create(RealGrid)\n\
@@ -178,9 +178,9 @@ if 'color_g_sn$ID$' in globals(): del color_g_sn$ID$\n\
if 'color_b_sn$ID$' in globals(): del color_b_sn$ID$\n\
\n\
mantaMsg('Allocating colors noise')\n\
-color_r_sn$ID$ = sn$ID$.create(RealGrid)\n\
-color_g_sn$ID$ = sn$ID$.create(RealGrid)\n\
-color_b_sn$ID$ = sn$ID$.create(RealGrid)\n\
+color_r_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORRNOISE$')\n\
+color_g_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORGNOISE$')\n\
+color_b_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORBNOISE$')\n\
\n\
# Add objects to dict to load them later on\n\
if 'smoke_noise_dict_final_s$ID$' in globals():\n\
@@ -213,7 +213,7 @@ if 'heat_s$ID$' in globals(): del heat_s$ID$\n\
if 'heatIn_s$ID$' in globals(): del heatIn_s$ID$\n\
\n\
mantaMsg('Allocating heat')\n\
-heat_s$ID$ = s$ID$.create(RealGrid)\n\
+heat_s$ID$ = s$ID$.create(RealGrid, name='$NAME_HEAT$')\n\
heatIn_s$ID$ = s$ID$.create(RealGrid)\n\
\n\
# Add objects to dict to load them later on\n\
@@ -232,9 +232,9 @@ if 'fuelIn_s$ID$' in globals(): del fuelIn_s$ID$\n\
if 'reactIn_s$ID$' in globals(): del reactIn_s$ID$\n\
\n\
mantaMsg('Allocating fire')\n\
-flame_s$ID$ = s$ID$.create(RealGrid)\n\
-fuel_s$ID$ = s$ID$.create(RealGrid)\n\
-react_s$ID$ = s$ID$.create(RealGrid)\n\
+flame_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FLAME$')\n\
+fuel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FUEL$')\n\
+react_s$ID$ = s$ID$.create(RealGrid, name='$NAME_REACT$')\n\
fuelIn_s$ID$ = s$ID$.create(RealGrid)\n\
reactIn_s$ID$ = s$ID$.create(RealGrid)\n\
\n\
@@ -252,9 +252,9 @@ if 'fuel_sn$ID$' in globals(): del fuel_sn$ID$\n\
if 'react_sn$ID$' in globals(): del react_sn$ID$\n\
\n\
mantaMsg('Allocating fire noise')\n\
-flame_sn$ID$ = sn$ID$.create(RealGrid)\n\
-fuel_sn$ID$ = sn$ID$.create(RealGrid)\n\
-react_sn$ID$ = sn$ID$.create(RealGrid)\n\
+flame_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_FLAMENOISE$')\n\
+fuel_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_FUELNOISE$')\n\
+react_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_REACTNOISE$')\n\
\n\
# Add objects to dict to load them later on\n\
if 'smoke_noise_dict_final_s$ID$' in globals():\n\
@@ -376,9 +376,9 @@ def smoke_step_$ID$():\n\
\n\
if using_heat_s$ID$:\n\
mantaMsg('Adding heat buoyancy')\n\
- addBuoyancy(flags=flags_s$ID$, density=heat_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_heat_s$ID$)\n\
+ addBuoyancy(flags=flags_s$ID$, density=heat_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_heat_s$ID$, scale=False)\n\
mantaMsg('Adding buoyancy')\n\
- addBuoyancy(flags=flags_s$ID$, density=density_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_dens_s$ID$)\n\
+ addBuoyancy(flags=flags_s$ID$, density=density_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_dens_s$ID$, scale=False)\n\
\n\
mantaMsg('Adding forces')\n\
addForceField(flags=flags_s$ID$, vel=vel_s$ID$, force=forces_s$ID$)\n\
diff --git a/intern/memutil/MEM_CacheLimiterC-Api.h b/intern/memutil/MEM_CacheLimiterC-Api.h
index 690763a14f0..2bbbfb75555 100644
--- a/intern/memutil/MEM_CacheLimiterC-Api.h
+++ b/intern/memutil/MEM_CacheLimiterC-Api.h
@@ -56,8 +56,8 @@ bool MEM_CacheLimiter_is_disabled(void);
* Create new MEM_CacheLimiter object
* managed objects are destructed with the data_destructor
*
- * \param data_destructor
- * \return A new MEM_CacheLimter object
+ * \param data_destructor: TODO.
+ * \return A new #MEM_CacheLimter object.
*/
MEM_CacheLimiterC *new_MEM_CacheLimiter(MEM_CacheLimiter_Destruct_Func data_destructor,
@@ -68,7 +68,7 @@ MEM_CacheLimiterC *new_MEM_CacheLimiter(MEM_CacheLimiter_Destruct_Func data_dest
*
* Frees the memory of the CacheLimiter but does not touch managed objects!
*
- * \param This "This" pointer
+ * \param This: "This" pointer.
*/
void delete_MEM_CacheLimiter(MEM_CacheLimiterC *This);
@@ -76,7 +76,7 @@ void delete_MEM_CacheLimiter(MEM_CacheLimiterC *This);
/**
* Manage object
*
- * \param This "This" pointer, data data object to manage
+ * \param This: "This" pointer, data data object to manage.
* \return CacheLimiterHandle to ref, unref, touch the managed object
*/
@@ -85,7 +85,7 @@ MEM_CacheLimiterHandleC *MEM_CacheLimiter_insert(MEM_CacheLimiterC *This, void *
/**
* Free objects until memory constraints are satisfied
*
- * \param This "This" pointer
+ * \param This: "This" pointer.
*/
void MEM_CacheLimiter_enforce_limits(MEM_CacheLimiterC *This);
@@ -94,7 +94,7 @@ void MEM_CacheLimiter_enforce_limits(MEM_CacheLimiterC *This);
* Unmanage object previously inserted object.
* Does _not_ delete managed object!
*
- * \param handle of object
+ * \param handle: of object.
*/
void MEM_CacheLimiter_unmanage(MEM_CacheLimiterHandleC *handle);
@@ -102,7 +102,7 @@ void MEM_CacheLimiter_unmanage(MEM_CacheLimiterHandleC *handle);
/**
* Raise priority of object (put it at the tail of the deletion chain)
*
- * \param handle of object
+ * \param handle: of object.
*/
void MEM_CacheLimiter_touch(MEM_CacheLimiterHandleC *handle);
@@ -111,7 +111,7 @@ void MEM_CacheLimiter_touch(MEM_CacheLimiterHandleC *handle);
* Increment reference counter. Objects with reference counter != 0 are _not_
* deleted.
*
- * \param handle of object
+ * \param handle: of object.
*/
void MEM_CacheLimiter_ref(MEM_CacheLimiterHandleC *handle);
@@ -120,7 +120,7 @@ void MEM_CacheLimiter_ref(MEM_CacheLimiterHandleC *handle);
* Decrement reference counter. Objects with reference counter != 0 are _not_
* deleted.
*
- * \param handle of object
+ * \param handle: of object.
*/
void MEM_CacheLimiter_unref(MEM_CacheLimiterHandleC *handle);
@@ -128,7 +128,7 @@ void MEM_CacheLimiter_unref(MEM_CacheLimiterHandleC *handle);
/**
* Get reference counter.
*
- * \param handle of object
+ * \param handle: of object.
*/
int MEM_CacheLimiter_get_refcount(MEM_CacheLimiterHandleC *handle);
@@ -136,7 +136,7 @@ int MEM_CacheLimiter_get_refcount(MEM_CacheLimiterHandleC *handle);
/**
* Get pointer to managed object
*
- * \param handle of object
+ * \param handle: of object.
*/
void *MEM_CacheLimiter_get(MEM_CacheLimiterHandleC *handle);
diff --git a/intern/opensubdiv/CMakeLists.txt b/intern/opensubdiv/CMakeLists.txt
index c411e58be35..13565a6ed28 100644
--- a/intern/opensubdiv/CMakeLists.txt
+++ b/intern/opensubdiv/CMakeLists.txt
@@ -31,7 +31,6 @@ set(SRC
opensubdiv_capi_type.h
opensubdiv_converter_capi.h
opensubdiv_evaluator_capi.h
- opensubdiv_gl_mesh_capi.h
opensubdiv_topology_refiner_capi.h
)
@@ -54,30 +53,20 @@ if(WITH_OPENSUBDIV)
internal/opensubdiv.cc
internal/opensubdiv_converter_factory.cc
internal/opensubdiv_converter_internal.cc
- internal/opensubdiv_converter_orient.cc
internal/opensubdiv_device_context_cuda.cc
internal/opensubdiv_device_context_opencl.cc
internal/opensubdiv_evaluator.cc
internal/opensubdiv_evaluator_internal.cc
- internal/opensubdiv_gl_mesh.cc
- internal/opensubdiv_gl_mesh_draw.cc
- internal/opensubdiv_gl_mesh_fvar.cc
- internal/opensubdiv_gl_mesh_internal.cc
internal/opensubdiv_topology_refiner.cc
internal/opensubdiv_topology_refiner_internal.cc
internal/opensubdiv_util.cc
internal/opensubdiv_converter_factory.h
internal/opensubdiv_converter_internal.h
- internal/opensubdiv_converter_orient.h
- internal/opensubdiv_converter_orient_impl.h
internal/opensubdiv_device_context_cuda.h
internal/opensubdiv_device_context_opencl.h
internal/opensubdiv_edge_map.h
internal/opensubdiv_evaluator_internal.h
- internal/opensubdiv_gl_mesh_draw.h
- internal/opensubdiv_gl_mesh_fvar.h
- internal/opensubdiv_gl_mesh_internal.h
internal/opensubdiv_internal.h
internal/opensubdiv_topology_refiner_internal.h
internal/opensubdiv_util.h
@@ -101,12 +90,8 @@ if(WITH_OPENSUBDIV)
OPENSUBDIV_DEFINE_COMPONENT(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK)
OPENSUBDIV_DEFINE_COMPONENT(OPENSUBDIV_HAS_GLSL_COMPUTE)
- data_to_c_simple(shader/gpu_shader_opensubdiv_vertex.glsl SRC)
- data_to_c_simple(shader/gpu_shader_opensubdiv_geometry.glsl SRC)
- data_to_c_simple(shader/gpu_shader_opensubdiv_fragment.glsl SRC)
-
- add_definitions(-DOSD_USES_GLEW)
add_definitions(${GL_DEFINITIONS})
+ add_definitions(-DOSD_USES_GLEW)
if(WIN32)
add_definitions(-DNOMINMAX)
@@ -131,7 +116,6 @@ else()
list(APPEND SRC
stub/opensubdiv_stub.cc
stub/opensubdiv_evaluator_stub.cc
- stub/opensubdiv_gl_mesh_stub.cc
stub/opensubdiv_topology_refiner_stub.cc
)
endif()
diff --git a/intern/opensubdiv/internal/opensubdiv.cc b/intern/opensubdiv/internal/opensubdiv.cc
index 74b81b13351..e9f6086851b 100644
--- a/intern/opensubdiv/internal/opensubdiv.cc
+++ b/intern/opensubdiv/internal/opensubdiv.cc
@@ -24,7 +24,6 @@
#include "opensubdiv_device_context_cuda.h"
#include "opensubdiv_device_context_opencl.h"
-#include "opensubdiv_gl_mesh_capi.h"
void openSubdiv_init(void)
{
@@ -34,7 +33,6 @@ void openSubdiv_init(void)
void openSubdiv_cleanup(void)
{
- openSubdiv_deinitGLMeshDrawingResources();
}
int openSubdiv_getAvailableEvaluators(void)
@@ -86,7 +84,7 @@ int openSubdiv_getVersionHex(void)
}
int major = 0, minor = 0, patch = 0;
vector<string> tokens;
- opensubdiv_capi::stringSplit(&tokens, version, "_", true);
+ blender::opensubdiv::stringSplit(&tokens, version, "_", true);
if (tokens.size() == 3) {
major = atoi(tokens[0].c_str());
minor = atoi(tokens[1].c_str());
diff --git a/intern/opensubdiv/internal/opensubdiv_converter_factory.cc b/intern/opensubdiv/internal/opensubdiv_converter_factory.cc
index ab93b5ce952..dba2a969062 100644
--- a/intern/opensubdiv/internal/opensubdiv_converter_factory.cc
+++ b/intern/opensubdiv/internal/opensubdiv_converter_factory.cc
@@ -28,14 +28,13 @@
#include <opensubdiv/far/topologyRefinerFactory.h>
#include "internal/opensubdiv_converter_internal.h"
-#include "internal/opensubdiv_converter_orient.h"
#include "internal/opensubdiv_internal.h"
#include "internal/opensubdiv_util.h"
#include "opensubdiv_converter_capi.h"
-using opensubdiv_capi::min;
-using opensubdiv_capi::stack;
-using opensubdiv_capi::vector;
+using blender::opensubdiv::min;
+using blender::opensubdiv::stack;
+using blender::opensubdiv::vector;
struct TopologyRefinerData {
const OpenSubdiv_Converter *converter;
@@ -246,7 +245,8 @@ inline void TopologyRefinerFactory<TopologyRefinerData>::reportInvalidTopology(
} /* namespace OPENSUBDIV_VERSION */
} /* namespace OpenSubdiv */
-namespace opensubdiv_capi {
+namespace blender {
+namespace opensubdiv {
namespace {
@@ -292,4 +292,5 @@ OpenSubdiv::Far::TopologyRefiner *createOSDTopologyRefinerFromConverter(
return TopologyRefinerFactory<TopologyRefinerData>::Create(cb_data, topology_options);
}
-} // namespace opensubdiv_capi
+} // namespace opensubdiv
+} // namespace blender
diff --git a/intern/opensubdiv/internal/opensubdiv_converter_factory.h b/intern/opensubdiv/internal/opensubdiv_converter_factory.h
index a1038474d33..3519d3059b2 100644
--- a/intern/opensubdiv/internal/opensubdiv_converter_factory.h
+++ b/intern/opensubdiv/internal/opensubdiv_converter_factory.h
@@ -27,11 +27,13 @@
struct OpenSubdiv_Converter;
-namespace opensubdiv_capi {
+namespace blender {
+namespace opensubdiv {
OpenSubdiv::Far::TopologyRefiner *createOSDTopologyRefinerFromConverter(
struct OpenSubdiv_Converter *converter);
-} // namespace opensubdiv_capi
+} // namespace opensubdiv
+} // namespace blender
#endif // OPENSUBDIV_CONVERTER_FACTORY_H_
diff --git a/intern/opensubdiv/internal/opensubdiv_converter_internal.cc b/intern/opensubdiv/internal/opensubdiv_converter_internal.cc
index 0335219d6b9..eedca88f77b 100644
--- a/intern/opensubdiv/internal/opensubdiv_converter_internal.cc
+++ b/intern/opensubdiv/internal/opensubdiv_converter_internal.cc
@@ -25,7 +25,8 @@
#include <cassert>
#include <opensubdiv/sdc/crease.h>
-namespace opensubdiv_capi {
+namespace blender {
+namespace opensubdiv {
OpenSubdiv::Sdc::SchemeType getSchemeTypeFromCAPI(OpenSubdiv_SchemeType type)
{
@@ -85,4 +86,5 @@ OpenSubdiv_FVarLinearInterpolation getCAPIFVarLinearInterpolationFromOSD(
return OSD_FVAR_LINEAR_INTERPOLATION_NONE;
}
-} // namespace opensubdiv_capi
+} // namespace opensubdiv
+} // namespace blender
diff --git a/intern/opensubdiv/internal/opensubdiv_converter_internal.h b/intern/opensubdiv/internal/opensubdiv_converter_internal.h
index 11c6bdd7f3b..7c586b0787a 100644
--- a/intern/opensubdiv/internal/opensubdiv_converter_internal.h
+++ b/intern/opensubdiv/internal/opensubdiv_converter_internal.h
@@ -30,7 +30,8 @@
struct OpenSubdiv_Converter;
-namespace opensubdiv_capi {
+namespace blender {
+namespace opensubdiv {
// Convert scheme type from C-API enum to an OpenSubdiv native enum.
OpenSubdiv::Sdc::SchemeType getSchemeTypeFromCAPI(OpenSubdiv_SchemeType type);
@@ -44,6 +45,7 @@ OpenSubdiv::Sdc::Options::FVarLinearInterpolation getFVarLinearInterpolationFrom
OpenSubdiv_FVarLinearInterpolation getCAPIFVarLinearInterpolationFromOSD(
OpenSubdiv::Sdc::Options::FVarLinearInterpolation linear_interpolation);
-} // namespace opensubdiv_capi
+} // namespace opensubdiv
+} // namespace blender
#endif // OPENSUBDIV_CONVERTER_INTERNAL_H_
diff --git a/intern/opensubdiv/internal/opensubdiv_converter_orient.cc b/intern/opensubdiv/internal/opensubdiv_converter_orient.cc
deleted file mode 100644
index e3367fc6314..00000000000
--- a/intern/opensubdiv/internal/opensubdiv_converter_orient.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2018 Blender Foundation. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-// Author: Sergey Sharybin
-
-#include "internal/opensubdiv_converter_orient.h"
-
-#include "internal/opensubdiv_internal.h"
-
-namespace opensubdiv_capi {
-
-void checkOrientedVertexConnectivity(const int num_vertex_edges,
- const int num_vertex_faces,
- const int *vertex_edges,
- const int *vertex_faces,
- const int *dst_vertex_edges,
- const int *dst_vertex_faces)
-{
-#ifndef NDEBUG
- for (int i = 0; i < num_vertex_faces; ++i) {
- bool found = false;
- for (int j = 0; j < num_vertex_faces; ++j) {
- if (vertex_faces[i] == dst_vertex_faces[j]) {
- found = true;
- break;
- }
- }
- if (!found) {
- assert(!"vert-faces connectivity ruined");
- }
- }
- for (int i = 0; i < num_vertex_edges; ++i) {
- bool found = false;
- for (int j = 0; j < num_vertex_edges; ++j) {
- if (vertex_edges[i] == dst_vertex_edges[j]) {
- found = true;
- break;
- }
- }
- if (!found) {
- assert(!"vert-edges connectivity ruined");
- }
- }
-#else
- (void)num_vertex_edges;
- (void)num_vertex_faces;
- (void)vertex_edges;
- (void)vertex_faces;
- (void)dst_vertex_edges;
- (void)dst_vertex_faces;
-#endif
-}
-
-} // namespace opensubdiv_capi
diff --git a/intern/opensubdiv/internal/opensubdiv_converter_orient.h b/intern/opensubdiv/internal/opensubdiv_converter_orient.h
deleted file mode 100644
index 967871845cb..00000000000
--- a/intern/opensubdiv/internal/opensubdiv_converter_orient.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2018 Blender Foundation. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-// Author: Sergey Sharybin
-
-#ifndef OPENSUBDIV_CONVERTER_ORIENT_H_
-# define OPENSUBDIV_CONVERTER_ORIENT_H_
-
-# include <opensubdiv/far/types.h>
-
-// Set of utility functions which are needed to bring topology to an orientation
-// (or, winding, if you wish) which OpenSubdiv expects.
-
-namespace opensubdiv_capi {
-
-inline void reverseFaceVertices(int *face_vertices, const int num_vertices);
-
-// TODO(sergey): Document which value corresponds to which winding.
-inline int getLoopWinding(int vert0_of_face, int vert1_of_face);
-
-inline void reverseFaceLoops(OpenSubdiv::Far::IndexArray *face_vertices,
- OpenSubdiv::Far::IndexArray *face_edges);
-
-// Used for debugging, checks whether orientation happened correct.
-void checkOrientedVertexConnectivity(const int num_vertex_edges,
- const int num_vertex_faces,
- const int *vertex_edges,
- const int *vertex_faces,
- const int *dst_vertex_edges,
- const int *dst_vertex_faces);
-
-} // namespace opensubdiv_capi
-
-#endif // OPENSUBDIV_CONVERTER_ORIENT_H_
-
-#include "internal/opensubdiv_converter_orient_impl.h"
diff --git a/intern/opensubdiv/internal/opensubdiv_converter_orient_impl.h b/intern/opensubdiv/internal/opensubdiv_converter_orient_impl.h
deleted file mode 100644
index aa717f5d99d..00000000000
--- a/intern/opensubdiv/internal/opensubdiv_converter_orient_impl.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2018 Blender Foundation. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-// Author: Sergey Sharybin
-
-#ifndef OPENSUBDIV_CONVERTER_ORIENT_IMPL_H_
-#define OPENSUBDIV_CONVERTER_ORIENT_IMPL_H_
-
-#include "internal/opensubdiv_converter_orient.h"
-
-#include <cmath>
-
-#include "internal/opensubdiv_util.h"
-
-namespace opensubdiv_capi {
-
-inline void reverseFaceVertices(int *face_vertices, const int num_vertices)
-{
- int last_vert = face_vertices[num_vertices - 1];
- for (int i = num_vertices - 1; i > 0; --i) {
- face_vertices[i] = face_vertices[i - 1];
- }
- face_vertices[0] = last_vert;
-}
-
-inline int getLoopWinding(int vert0_of_face, int vert1_of_face)
-{
- int delta_face = vert1_of_face - vert0_of_face;
- if (abs(delta_face) != 1) {
- if (delta_face > 0) {
- delta_face = -1;
- }
- else {
- delta_face = 1;
- }
- }
- return delta_face;
-}
-
-inline void reverseFaceLoops(OpenSubdiv::Far::IndexArray *face_vertices,
- OpenSubdiv::Far::IndexArray *face_edges)
-{
- const int num_face_vertices = face_vertices->size();
- for (int i = 0; i < num_face_vertices / 2; ++i) {
- const int j = num_face_vertices - i - 1;
- if (i != j) {
- swap((*face_vertices)[i], (*face_vertices)[j]);
- swap((*face_edges)[i], (*face_edges)[j]);
- }
- }
- reverseFaceVertices(&(*face_vertices)[0], num_face_vertices);
-}
-
-} // namespace opensubdiv_capi
-
-#endif // OPENSUBDIV_CONVERTER_ORIENT_IMPL_H_
diff --git a/intern/opensubdiv/internal/opensubdiv_edge_map.h b/intern/opensubdiv/internal/opensubdiv_edge_map.h
index e2e6d2328fe..454068b58a4 100644
--- a/intern/opensubdiv/internal/opensubdiv_edge_map.h
+++ b/intern/opensubdiv/internal/opensubdiv_edge_map.h
@@ -21,7 +21,8 @@
#include "internal/opensubdiv_util.h"
-namespace opensubdiv_capi {
+namespace blender {
+namespace opensubdiv {
// Helper class to ease dealing with edge indexing.
// Simply takes care of ensuring order of vertices is strictly defined.
@@ -144,12 +145,13 @@ template<typename T> typename EdgeTagMap<T>::value_type &EdgeTagMap<T>::operator
return edge_tags_[key];
}
-} // namespace opensubdiv_capi
+} // namespace opensubdiv
+} // namespace blender
namespace std {
-template<> struct hash<opensubdiv_capi::EdgeKey> {
- std::size_t operator()(const opensubdiv_capi::EdgeKey &key) const
+template<> struct hash<blender::opensubdiv::EdgeKey> {
+ std::size_t operator()(const blender::opensubdiv::EdgeKey &key) const
{
return key.hash();
}
diff --git a/intern/opensubdiv/internal/opensubdiv_evaluator_internal.cc b/intern/opensubdiv/internal/opensubdiv_evaluator_internal.cc
index c35909a045b..5279752ea4e 100644
--- a/intern/opensubdiv/internal/opensubdiv_evaluator_internal.cc
+++ b/intern/opensubdiv/internal/opensubdiv_evaluator_internal.cc
@@ -53,7 +53,8 @@ using OpenSubdiv::Osd::CpuPatchTable;
using OpenSubdiv::Osd::CpuVertexBuffer;
using OpenSubdiv::Osd::PatchCoord;
-namespace opensubdiv_capi {
+namespace blender {
+namespace opensubdiv {
namespace {
@@ -731,7 +732,8 @@ void CpuEvalOutputAPI::evaluatePatchesLimit(const OpenSubdiv_PatchCoord *patch_c
}
}
-} // namespace opensubdiv_capi
+} // namespace opensubdiv
+} // namespace blender
OpenSubdiv_EvaluatorInternal::OpenSubdiv_EvaluatorInternal()
: eval_output(NULL), patch_map(NULL), patch_table(NULL)
@@ -748,7 +750,7 @@ OpenSubdiv_EvaluatorInternal::~OpenSubdiv_EvaluatorInternal()
OpenSubdiv_EvaluatorInternal *openSubdiv_createEvaluatorInternal(
OpenSubdiv_TopologyRefiner *topology_refiner)
{
- using opensubdiv_capi::vector;
+ using blender::opensubdiv::vector;
TopologyRefiner *refiner = topology_refiner->internal->osd_topology_refiner;
if (refiner == NULL) {
// Happens on bad topology.
@@ -851,13 +853,13 @@ OpenSubdiv_EvaluatorInternal *openSubdiv_createEvaluatorInternal(
}
// Create OpenSubdiv's CPU side evaluator.
// TODO(sergey): Make it possible to use different evaluators.
- opensubdiv_capi::CpuEvalOutput *eval_output = new opensubdiv_capi::CpuEvalOutput(
+ blender::opensubdiv::CpuEvalOutput *eval_output = new blender::opensubdiv::CpuEvalOutput(
vertex_stencils, varying_stencils, all_face_varying_stencils, 2, patch_table);
OpenSubdiv::Far::PatchMap *patch_map = new PatchMap(*patch_table);
// Wrap everything we need into an object which we control from our side.
OpenSubdiv_EvaluatorInternal *evaluator_descr;
evaluator_descr = OBJECT_GUARDED_NEW(OpenSubdiv_EvaluatorInternal);
- evaluator_descr->eval_output = new opensubdiv_capi::CpuEvalOutputAPI(eval_output, patch_map);
+ evaluator_descr->eval_output = new blender::opensubdiv::CpuEvalOutputAPI(eval_output, patch_map);
evaluator_descr->patch_map = patch_map;
evaluator_descr->patch_table = patch_table;
// TOOD(sergey): Look into whether we've got duplicated stencils arrays.
diff --git a/intern/opensubdiv/internal/opensubdiv_evaluator_internal.h b/intern/opensubdiv/internal/opensubdiv_evaluator_internal.h
index 392633944c6..dbe4d88539f 100644
--- a/intern/opensubdiv/internal/opensubdiv_evaluator_internal.h
+++ b/intern/opensubdiv/internal/opensubdiv_evaluator_internal.h
@@ -29,7 +29,8 @@
struct OpenSubdiv_PatchCoord;
struct OpenSubdiv_TopologyRefiner;
-namespace opensubdiv_capi {
+namespace blender {
+namespace opensubdiv {
// Anonymous forward declaration of actual evaluator implementation.
class CpuEvalOutput;
@@ -132,14 +133,15 @@ class CpuEvalOutputAPI {
OpenSubdiv::Far::PatchMap *patch_map_;
};
-} // namespace opensubdiv_capi
+} // namespace opensubdiv
+} // namespace blender
struct OpenSubdiv_EvaluatorInternal {
public:
OpenSubdiv_EvaluatorInternal();
~OpenSubdiv_EvaluatorInternal();
- opensubdiv_capi::CpuEvalOutputAPI *eval_output;
+ blender::opensubdiv::CpuEvalOutputAPI *eval_output;
const OpenSubdiv::Far::PatchMap *patch_map;
const OpenSubdiv::Far::PatchTable *patch_table;
};
diff --git a/intern/opensubdiv/internal/opensubdiv_gl_mesh.cc b/intern/opensubdiv/internal/opensubdiv_gl_mesh.cc
deleted file mode 100644
index 6afd763a63e..00000000000
--- a/intern/opensubdiv/internal/opensubdiv_gl_mesh.cc
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright 2013 Blender Foundation. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-#include "opensubdiv_gl_mesh_capi.h"
-
-#ifdef _MSC_VER
-# include <iso646.h>
-#endif
-
-#include <opensubdiv/far/stencilTable.h>
-#include <opensubdiv/osd/glMesh.h>
-#include <opensubdiv/osd/glPatchTable.h>
-
-using OpenSubdiv::Far::StencilTable;
-using OpenSubdiv::Osd::GLMeshInterface;
-using OpenSubdiv::Osd::GLPatchTable;
-using OpenSubdiv::Osd::Mesh;
-using OpenSubdiv::Osd::MeshBitset;
-
-// CPU backend.
-#include <opensubdiv/osd/cpuEvaluator.h>
-#include <opensubdiv/osd/cpuGLVertexBuffer.h>
-using OpenSubdiv::Osd::CpuEvaluator;
-using OpenSubdiv::Osd::CpuGLVertexBuffer;
-typedef Mesh<CpuGLVertexBuffer, StencilTable, CpuEvaluator, GLPatchTable> OsdCpuMesh;
-// OpenMP backend.
-#ifdef OPENSUBDIV_HAS_OPENMP
-# include <opensubdiv/osd/ompEvaluator.h>
-using OpenSubdiv::Osd::OmpEvaluator;
-typedef Mesh<CpuGLVertexBuffer, StencilTable, OmpEvaluator, GLPatchTable> OsdOmpMesh;
-#endif
-// OpenCL backend.
-#ifdef OPENSUBDIV_HAS_OPENCL
-# include "opensubdiv_device_context_opencl.h"
-# include <opensubdiv/osd/clEvaluator.h>
-# include <opensubdiv/osd/clGLVertexBuffer.h>
-using OpenSubdiv::Osd::CLEvaluator;
-using OpenSubdiv::Osd::CLGLVertexBuffer;
-using OpenSubdiv::Osd::CLStencilTable;
-/* TODO(sergey): Use CLDeviceContext similar to OSD examples? */
-typedef Mesh<CLGLVertexBuffer, CLStencilTable, CLEvaluator, GLPatchTable, CLDeviceContext>
- OsdCLMesh;
-static CLDeviceContext g_cl_device_context;
-#endif
-// CUDA backend.
-#ifdef OPENSUBDIV_HAS_CUDA
-# include "opensubdiv_device_context_cuda.h"
-# include <opensubdiv/osd/cudaEvaluator.h>
-# include <opensubdiv/osd/cudaGLVertexBuffer.h>
-using OpenSubdiv::Osd::CudaEvaluator;
-using OpenSubdiv::Osd::CudaGLVertexBuffer;
-using OpenSubdiv::Osd::CudaStencilTable;
-typedef Mesh<CudaGLVertexBuffer, CudaStencilTable, CudaEvaluator, GLPatchTable> OsdCudaMesh;
-static CudaDeviceContext g_cuda_device_context;
-#endif
-// Transform feedback backend.
-#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
-# include <opensubdiv/osd/glVertexBuffer.h>
-# include <opensubdiv/osd/glXFBEvaluator.h>
-using OpenSubdiv::Osd::GLStencilTableTBO;
-using OpenSubdiv::Osd::GLVertexBuffer;
-using OpenSubdiv::Osd::GLXFBEvaluator;
-typedef Mesh<GLVertexBuffer, GLStencilTableTBO, GLXFBEvaluator, GLPatchTable>
- OsdGLSLTransformFeedbackMesh;
-#endif
-// GLSL compute backend.
-#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
-# include <opensubdiv/osd/glComputeEvaluator.h>
-# include <opensubdiv/osd/glVertexBuffer.h>
-using OpenSubdiv::Osd::GLComputeEvaluator;
-using OpenSubdiv::Osd::GLStencilTableSSBO;
-using OpenSubdiv::Osd::GLVertexBuffer;
-typedef Mesh<GLVertexBuffer, GLStencilTableSSBO, GLComputeEvaluator, GLPatchTable>
- OsdGLSLComputeMesh;
-#endif
-
-#include "MEM_guardedalloc.h"
-
-#include "internal/opensubdiv_gl_mesh_draw.h"
-#include "internal/opensubdiv_gl_mesh_fvar.h"
-#include "internal/opensubdiv_gl_mesh_internal.h"
-#include "internal/opensubdiv_topology_refiner_internal.h"
-#include "internal/opensubdiv_util.h"
-#include "opensubdiv_topology_refiner_capi.h"
-
-using opensubdiv_capi::vector;
-
-namespace {
-
-GLMeshInterface *createGLMeshInterface(OpenSubdiv::Far::TopologyRefiner *topology_refiner,
- const MeshBitset &bits,
- const int num_vertex_elements,
- const int num_varying_elements,
- const int level,
- eOpenSubdivEvaluator evaluator_type)
-{
- GLMeshInterface *mesh = NULL;
- switch (evaluator_type) {
-#define CHECK_EVALUATOR_TYPE(type, class) \
- case OPENSUBDIV_EVALUATOR_##type: \
- mesh = new class(topology_refiner, num_vertex_elements, num_varying_elements, level, bits); \
- break;
-
-#define CHECK_EVALUATOR_TYPE_STUB(type) \
- case OPENSUBDIV_EVALUATOR_##type: \
- mesh = NULL; \
- break;
-
- CHECK_EVALUATOR_TYPE(CPU, OsdCpuMesh)
-#ifdef OPENSUBDIV_HAS_OPENMP
- CHECK_EVALUATOR_TYPE(OPENMP, OsdOmpMesh)
-#else
- CHECK_EVALUATOR_TYPE_STUB(OPENMP)
-#endif
-#ifdef OPENSUBDIV_HAS_OPENCL
- CHECK_EVALUATOR_TYPE(OPENCL, OsdCLMesh)
-#else
- CHECK_EVALUATOR_TYPE_STUB(OPENCL)
-#endif
-#ifdef OPENSUBDIV_HAS_CUDA
- CHECK_EVALUATOR_TYPE(CUDA, OsdCudaMesh)
-#else
- CHECK_EVALUATOR_TYPE_STUB(CUDA)
-#endif
-#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
- CHECK_EVALUATOR_TYPE(GLSL_TRANSFORM_FEEDBACK, OsdGLSLTransformFeedbackMesh)
-#else
- CHECK_EVALUATOR_TYPE_STUB(GLSL_TRANSFORM_FEEDBACK)
-#endif
-#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
- CHECK_EVALUATOR_TYPE(GLSL_COMPUTE, OsdGLSLComputeMesh)
-#else
- CHECK_EVALUATOR_TYPE_STUB(GLSL_COMPUTE)
-#endif
-
-#undef CHECK_EVALUATOR_TYPE
-#undef CHECK_EVALUATOR_TYPE_STUB
- }
- return mesh;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// GLMesh structure "methods".
-
-opensubdiv_capi::GLMeshFVarData *createFVarData(OpenSubdiv::Far::TopologyRefiner *topology_refiner,
- GLMeshInterface *mesh,
- const float *fvar_src_buffer)
-{
- using opensubdiv_capi::GLMeshFVarData;
- GLMeshFVarData *fvar_data = new GLMeshFVarData();
- fvar_data->create(topology_refiner, mesh->GetFarPatchTable(), 2, fvar_src_buffer);
- return fvar_data;
-}
-
-unsigned int getPatchIndexBuffer(OpenSubdiv_GLMesh *gl_mesh)
-{
- return gl_mesh->internal->mesh_interface->GetPatchTable()->GetPatchIndexBuffer();
-}
-
-void bindVertexBuffer(OpenSubdiv_GLMesh *gl_mesh)
-{
- gl_mesh->internal->mesh_interface->BindVertexBuffer();
-}
-
-void setCoarsePositions(OpenSubdiv_GLMesh *gl_mesh,
- const float *positions,
- const int start_vertex,
- const int num_vertices)
-{
- gl_mesh->internal->mesh_interface->UpdateVertexBuffer(positions, start_vertex, num_vertices);
-}
-
-void refine(OpenSubdiv_GLMesh *gl_mesh)
-{
- gl_mesh->internal->mesh_interface->Refine();
-}
-
-void synchronize(struct OpenSubdiv_GLMesh *gl_mesh)
-{
- gl_mesh->internal->mesh_interface->Synchronize();
-}
-
-void assignFunctionPointers(OpenSubdiv_GLMesh *gl_mesh)
-{
- gl_mesh->getPatchIndexBuffer = getPatchIndexBuffer;
- gl_mesh->bindVertexBuffer = bindVertexBuffer;
- gl_mesh->setCoarsePositions = setCoarsePositions;
- gl_mesh->refine = refine;
- gl_mesh->synchronize = synchronize;
-
- gl_mesh->prepareDraw = opensubdiv_capi::GLMeshDisplayPrepare;
- gl_mesh->drawPatches = opensubdiv_capi::GLMeshDisplayDrawPatches;
-}
-
-} // namespace
-
-struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
- OpenSubdiv_TopologyRefiner *topology_refiner, eOpenSubdivEvaluator evaluator_type)
-{
- using OpenSubdiv::Far::TopologyRefiner;
- TopologyRefiner *osd_topology_refiner = topology_refiner->internal->osd_topology_refiner;
- // TODO(sergey): Query this from refiner.
- const bool is_adaptive = false;
- MeshBitset bits;
- bits.set(OpenSubdiv::Osd::MeshAdaptive, is_adaptive);
- bits.set(OpenSubdiv::Osd::MeshUseSingleCreasePatch, 0);
- bits.set(OpenSubdiv::Osd::MeshInterleaveVarying, 1);
- bits.set(OpenSubdiv::Osd::MeshFVarData, 1);
- bits.set(OpenSubdiv::Osd::MeshEndCapBSplineBasis, 1);
- const int num_vertex_elements = 3;
- const int num_varying_elements = 3;
- GLMeshInterface *mesh = createGLMeshInterface(osd_topology_refiner,
- bits,
- num_vertex_elements,
- num_varying_elements,
- osd_topology_refiner->GetMaxLevel(),
- evaluator_type);
- if (mesh == NULL) {
- return NULL;
- }
- OpenSubdiv_GLMesh *gl_mesh = OBJECT_GUARDED_NEW(OpenSubdiv_GLMesh);
- assignFunctionPointers(gl_mesh);
- gl_mesh->internal = new OpenSubdiv_GLMeshInternal();
- gl_mesh->internal->evaluator_type = evaluator_type;
- gl_mesh->internal->mesh_interface = mesh;
- // Face-varying support.
- // TODO(sergey): This part needs to be re-done.
- if (osd_topology_refiner->GetNumFVarChannels() > 0) {
- // TODO(sergey): This is a temporary stub to get things compiled. Need
- // to store base level UVs somewhere else.
- vector<float> uvs;
- vector<float> fvar_data_buffer;
- opensubdiv_capi::interpolateFVarData(*osd_topology_refiner, uvs, &fvar_data_buffer);
- gl_mesh->internal->fvar_data = createFVarData(
- osd_topology_refiner, mesh, &fvar_data_buffer[0]);
- }
- else {
- gl_mesh->internal->fvar_data = NULL;
- }
- return gl_mesh;
-}
-
-void openSubdiv_deleteOsdGLMesh(OpenSubdiv_GLMesh *gl_mesh)
-{
- delete gl_mesh->internal;
- OBJECT_GUARDED_DELETE(gl_mesh, OpenSubdiv_GLMesh);
-}
diff --git a/intern/opensubdiv/internal/opensubdiv_gl_mesh_draw.cc b/intern/opensubdiv/internal/opensubdiv_gl_mesh_draw.cc
deleted file mode 100644
index cbccf69e02d..00000000000
--- a/intern/opensubdiv/internal/opensubdiv_gl_mesh_draw.cc
+++ /dev/null
@@ -1,577 +0,0 @@
-// Copyright 2013 Blender Foundation. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-// Author: Sergey Sharybin
-
-#include "internal/opensubdiv_gl_mesh_draw.h"
-
-#ifdef _MSC_VER
-# include <iso646.h>
-#endif
-
-#include <GL/glew.h>
-#include <cmath>
-#include <cstdio>
-
-#include <opensubdiv/osd/glMesh.h>
-
-#ifdef OPENSUBDIV_HAS_CUDA
-# include <opensubdiv/osd/cudaGLVertexBuffer.h>
-#endif // OPENSUBDIV_HAS_CUDA
-
-#include <opensubdiv/osd/cpuEvaluator.h>
-#include <opensubdiv/osd/cpuGLVertexBuffer.h>
-
-#include "internal/opensubdiv_gl_mesh_fvar.h"
-#include "internal/opensubdiv_gl_mesh_internal.h"
-#include "internal/opensubdiv_util.h"
-#include "opensubdiv_capi.h"
-#include "opensubdiv_gl_mesh_capi.h"
-
-using OpenSubdiv::Osd::GLMeshInterface;
-
-extern "C" char datatoc_gpu_shader_opensubdiv_vertex_glsl[];
-extern "C" char datatoc_gpu_shader_opensubdiv_geometry_glsl[];
-extern "C" char datatoc_gpu_shader_opensubdiv_fragment_glsl[];
-
-// TODO(sergey): Those are a bit of bad level calls :S
-extern "C" {
-void copy_m3_m3(float m1[3][3], float m2[3][3]);
-void copy_m3_m4(float m1[3][3], float m2[4][4]);
-void adjoint_m3_m3(float m1[3][3], float m[3][3]);
-float determinant_m3_array(float m[3][3]);
-bool invert_m3_m3(float m1[3][3], float m2[3][3]);
-bool invert_m3(float m[3][3]);
-void transpose_m3(float mat[3][3]);
-}
-
-#define MAX_LIGHTS 8
-#define SUPPORT_COLOR_MATERIAL
-
-typedef struct Light {
- float position[4];
- float ambient[4];
- float diffuse[4];
- float specular[4];
- float spot_direction[4];
-#ifdef SUPPORT_COLOR_MATERIAL
- float constant_attenuation;
- float linear_attenuation;
- float quadratic_attenuation;
- float spot_cutoff;
- float spot_exponent;
- float spot_cos_cutoff;
- float pad, pad2;
-#endif
-} Light;
-
-typedef struct Lighting {
- Light lights[MAX_LIGHTS];
- int num_enabled;
-} Lighting;
-
-typedef struct Transform {
- float projection_matrix[16];
- float model_view_matrix[16];
- float normal_matrix[9];
-} Transform;
-
-static bool g_use_osd_glsl = false;
-static int g_active_uv_index = 0;
-
-static GLuint g_flat_fill_solid_program = 0;
-static GLuint g_flat_fill_texture2d_program = 0;
-static GLuint g_smooth_fill_solid_program = 0;
-static GLuint g_smooth_fill_texture2d_program = 0;
-
-static GLuint g_flat_fill_solid_shadeless_program = 0;
-static GLuint g_flat_fill_texture2d_shadeless_program = 0;
-static GLuint g_smooth_fill_solid_shadeless_program = 0;
-static GLuint g_smooth_fill_texture2d_shadeless_program = 0;
-
-static GLuint g_wireframe_program = 0;
-
-static GLuint g_lighting_ub = 0;
-static Lighting g_lighting_data;
-static Transform g_transform;
-
-namespace {
-
-GLuint compileShader(GLenum shaderType,
- const char *version,
- const char *define,
- const char *source)
-{
- const char *sources[] = {
- version,
- define,
-#ifdef SUPPORT_COLOR_MATERIAL
- "#define SUPPORT_COLOR_MATERIAL\n",
-#else
- "",
-#endif
- source,
- };
-
- GLuint shader = glCreateShader(shaderType);
- glShaderSource(shader, 4, sources, NULL);
- glCompileShader(shader);
-
- GLint status;
- glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
- if (status == GL_FALSE) {
- GLchar emsg[1024];
- glGetShaderInfoLog(shader, sizeof(emsg), 0, emsg);
- fprintf(stderr, "Error compiling GLSL: %s\n", emsg);
- fprintf(stderr, "Version: %s\n", version);
- fprintf(stderr, "Defines: %s\n", define);
- fprintf(stderr, "Source: %s\n", source);
- return 0;
- }
-
- return shader;
-}
-
-GLuint linkProgram(const char *version, const char *define)
-{
- GLuint vertexShader = compileShader(
- GL_VERTEX_SHADER, version, define, datatoc_gpu_shader_opensubdiv_vertex_glsl);
- if (vertexShader == 0) {
- return 0;
- }
- GLuint geometryShader = compileShader(
- GL_GEOMETRY_SHADER, version, define, datatoc_gpu_shader_opensubdiv_geometry_glsl);
- if (geometryShader == 0) {
- return 0;
- }
- GLuint fragmentShader = compileShader(
- GL_FRAGMENT_SHADER, version, define, datatoc_gpu_shader_opensubdiv_fragment_glsl);
- if (fragmentShader == 0) {
- return 0;
- }
-
- GLuint program = glCreateProgram();
-
- glAttachShader(program, vertexShader);
- glAttachShader(program, geometryShader);
- glAttachShader(program, fragmentShader);
-
- glBindAttribLocation(program, 0, "position");
- glBindAttribLocation(program, 1, "normal");
-
- glLinkProgram(program);
-
- glDeleteShader(vertexShader);
- glDeleteShader(geometryShader);
- glDeleteShader(fragmentShader);
-
- GLint status;
- glGetProgramiv(program, GL_LINK_STATUS, &status);
- if (status == GL_FALSE) {
- GLchar emsg[1024];
- glGetProgramInfoLog(program, sizeof(emsg), 0, emsg);
- fprintf(stderr, "Error linking GLSL program : %s\n", emsg);
- fprintf(stderr, "Defines: %s\n", define);
- glDeleteProgram(program);
- return 0;
- }
-
- glUniformBlockBinding(program, glGetUniformBlockIndex(program, "Lighting"), 0);
-
- if (GLEW_VERSION_4_1) {
- glProgramUniform1i(program, glGetUniformLocation(program, "texture_buffer"), 0);
- glProgramUniform1i(program, glGetUniformLocation(program, "FVarDataOffsetBuffer"), 30);
- glProgramUniform1i(program, glGetUniformLocation(program, "FVarDataBuffer"), 31);
- }
- else {
- glUseProgram(program);
- glUniform1i(glGetUniformLocation(program, "texture_buffer"), 0);
- glUniform1i(glGetUniformLocation(program, "FVarDataOffsetBuffer"), 30);
- glUniform1i(glGetUniformLocation(program, "FVarDataBuffer"), 31);
- glUseProgram(0);
- }
-
- return program;
-}
-
-void bindProgram(OpenSubdiv_GLMesh *gl_mesh, int program)
-{
- glUseProgram(program);
- // Matrices
- glUniformMatrix4fv(
- glGetUniformLocation(program, "modelViewMatrix"), 1, false, g_transform.model_view_matrix);
- glUniformMatrix4fv(
- glGetUniformLocation(program, "projectionMatrix"), 1, false, g_transform.projection_matrix);
- glUniformMatrix3fv(
- glGetUniformLocation(program, "normalMatrix"), 1, false, g_transform.normal_matrix);
- // Lighting.
- glBindBuffer(GL_UNIFORM_BUFFER, g_lighting_ub);
- glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(g_lighting_data), &g_lighting_data);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
- glBindBufferBase(GL_UNIFORM_BUFFER, 0, g_lighting_ub);
- // Color.
- {
- // TODO(sergey): Stop using glGetMaterial.
- float color[4];
- glGetMaterialfv(GL_FRONT, GL_DIFFUSE, color);
- glUniform4fv(glGetUniformLocation(program, "diffuse"), 1, color);
- glGetMaterialfv(GL_FRONT, GL_SPECULAR, color);
- glUniform4fv(glGetUniformLocation(program, "specular"), 1, color);
- glGetMaterialfv(GL_FRONT, GL_SHININESS, color);
- glUniform1f(glGetUniformLocation(program, "shininess"), color[0]);
- }
- // Face-vertex data.
- opensubdiv_capi::GLMeshFVarData *fvar_data = gl_mesh->internal->fvar_data;
- if (fvar_data != NULL) {
- if (fvar_data->texture_buffer) {
- glActiveTexture(GL_TEXTURE31);
- glBindTexture(GL_TEXTURE_BUFFER, fvar_data->texture_buffer);
- glActiveTexture(GL_TEXTURE0);
- }
- if (fvar_data->offset_buffer) {
- glActiveTexture(GL_TEXTURE30);
- glBindTexture(GL_TEXTURE_BUFFER, fvar_data->offset_buffer);
- glActiveTexture(GL_TEXTURE0);
- }
- glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), fvar_data->fvar_width);
- if (fvar_data->channel_offsets.size() > 0 && g_active_uv_index >= 0) {
- glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"),
- fvar_data->channel_offsets[g_active_uv_index]);
- }
- else {
- glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
- }
- }
- else {
- glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 0);
- glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
- }
-}
-
-} // namespace
-
-bool openSubdiv_initGLMeshDrawingResources(void)
-{
- static bool need_init = true;
- static bool init_success = false;
- if (!need_init) {
- return init_success;
- }
- // TODO(sergey): Update OSD drawing to OpenGL 3.3 core,
- // then remove following line.
- return false;
- const char *version = "";
- if (GLEW_VERSION_3_2) {
- version = "#version 150 compatibility\n";
- }
- else if (GLEW_VERSION_3_1) {
- version =
- "#version 140\n"
- "#extension GL_ARB_compatibility: enable\n";
- }
- else {
- version = "#version 130\n";
- // Minimum supported for OpenSubdiv.
- }
- g_flat_fill_solid_program = linkProgram(version,
- "#define USE_COLOR_MATERIAL\n"
- "#define USE_LIGHTING\n"
- "#define FLAT_SHADING\n");
- g_flat_fill_texture2d_program = linkProgram(version,
- "#define USE_COLOR_MATERIAL\n"
- "#define USE_LIGHTING\n"
- "#define USE_TEXTURE_2D\n"
- "#define FLAT_SHADING\n");
- g_smooth_fill_solid_program = linkProgram(version,
- "#define USE_COLOR_MATERIAL\n"
- "#define USE_LIGHTING\n"
- "#define SMOOTH_SHADING\n");
- g_smooth_fill_texture2d_program = linkProgram(version,
- "#define USE_COLOR_MATERIAL\n"
- "#define USE_LIGHTING\n"
- "#define USE_TEXTURE_2D\n"
- "#define SMOOTH_SHADING\n");
-
- g_flat_fill_solid_shadeless_program = linkProgram(version,
- "#define USE_COLOR_MATERIAL\n"
- "#define FLAT_SHADING\n");
- g_flat_fill_texture2d_shadeless_program = linkProgram(version,
- "#define USE_COLOR_MATERIAL\n"
- "#define USE_TEXTURE_2D\n"
- "#define FLAT_SHADING\n");
- g_smooth_fill_solid_shadeless_program = linkProgram(version,
- "#define USE_COLOR_MATERIAL\n"
- "#define SMOOTH_SHADING\n");
- g_smooth_fill_texture2d_shadeless_program = linkProgram(version,
- "#define USE_COLOR_MATERIAL\n"
- "#define USE_TEXTURE_2D\n"
- "#define SMOOTH_SHADING\n");
- g_wireframe_program = linkProgram(version, "#define WIREFRAME\n");
-
- glGenBuffers(1, &g_lighting_ub);
- glBindBuffer(GL_UNIFORM_BUFFER, g_lighting_ub);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(g_lighting_data), NULL, GL_STATIC_DRAW);
- need_init = false;
- init_success = g_flat_fill_solid_program != 0 && g_flat_fill_texture2d_program != 0 &&
- g_smooth_fill_solid_program != 0 && g_smooth_fill_texture2d_program != 0 &&
- g_wireframe_program;
- return init_success;
-}
-
-void openSubdiv_deinitGLMeshDrawingResources(void)
-{
- if (g_lighting_ub != 0) {
- glDeleteBuffers(1, &g_lighting_ub);
- }
-#define SAFE_DELETE_PROGRAM(program) \
- do { \
- if (program) { \
- glDeleteProgram(program); \
- } \
- } while (false)
-
- SAFE_DELETE_PROGRAM(g_flat_fill_solid_program);
- SAFE_DELETE_PROGRAM(g_flat_fill_texture2d_program);
- SAFE_DELETE_PROGRAM(g_smooth_fill_solid_program);
- SAFE_DELETE_PROGRAM(g_smooth_fill_texture2d_program);
- SAFE_DELETE_PROGRAM(g_flat_fill_solid_shadeless_program);
- SAFE_DELETE_PROGRAM(g_flat_fill_texture2d_shadeless_program);
- SAFE_DELETE_PROGRAM(g_smooth_fill_solid_shadeless_program);
- SAFE_DELETE_PROGRAM(g_smooth_fill_texture2d_shadeless_program);
- SAFE_DELETE_PROGRAM(g_wireframe_program);
-
-#undef SAFE_DELETE_PROGRAM
-}
-
-namespace opensubdiv_capi {
-
-namespace {
-
-GLuint prepare_patchDraw(OpenSubdiv_GLMesh *gl_mesh, bool fill_quads)
-{
- GLint program = 0;
- if (!g_use_osd_glsl) {
- glGetIntegerv(GL_CURRENT_PROGRAM, &program);
- if (program) {
- GLint model;
- glGetIntegerv(GL_SHADE_MODEL, &model);
- GLint location = glGetUniformLocation(program, "osd_flat_shading");
- if (location != -1) {
- glUniform1i(location, model == GL_FLAT);
- }
- // Face-vertex data.
- opensubdiv_capi::GLMeshFVarData *fvar_data = gl_mesh->internal->fvar_data;
- if (fvar_data != NULL) {
- if (fvar_data->texture_buffer) {
- glActiveTexture(GL_TEXTURE31);
- glBindTexture(GL_TEXTURE_BUFFER, fvar_data->texture_buffer);
- glActiveTexture(GL_TEXTURE0);
- }
- if (fvar_data->offset_buffer) {
- glActiveTexture(GL_TEXTURE30);
- glBindTexture(GL_TEXTURE_BUFFER, fvar_data->offset_buffer);
- glActiveTexture(GL_TEXTURE0);
- }
- GLint location = glGetUniformLocation(program, "osd_fvar_count");
- if (location != -1) {
- glUniform1i(location, fvar_data->fvar_width);
- }
- location = glGetUniformLocation(program, "osd_active_uv_offset");
- if (location != -1) {
- if (fvar_data->channel_offsets.size() > 0 && g_active_uv_index >= 0) {
- glUniform1i(location, fvar_data->channel_offsets[g_active_uv_index]);
- }
- else {
- glUniform1i(location, 0);
- }
- }
- }
- else {
- glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 0);
- glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
- }
- }
- return program;
- }
- if (fill_quads) {
- int model;
- GLboolean use_texture_2d;
- glGetIntegerv(GL_SHADE_MODEL, &model);
- glGetBooleanv(GL_TEXTURE_2D, &use_texture_2d);
- if (model == GL_FLAT) {
- if (use_texture_2d) {
- program = g_flat_fill_texture2d_program;
- }
- else {
- program = g_flat_fill_solid_program;
- }
- }
- else {
- if (use_texture_2d) {
- program = g_smooth_fill_texture2d_program;
- }
- else {
- program = g_smooth_fill_solid_program;
- }
- }
- }
- else {
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- program = g_wireframe_program;
- }
- bindProgram(gl_mesh, program);
- return program;
-}
-
-void perform_drawElements(GLuint program, int patch_index, int num_elements, int start_element)
-{
- if (program) {
- glUniform1i(glGetUniformLocation(program, "PrimitiveIdBase"), patch_index);
- }
- glDrawElements(GL_LINES_ADJACENCY,
- num_elements,
- GL_UNSIGNED_INT,
- reinterpret_cast<void *>(start_element * sizeof(unsigned int)));
-}
-
-void finishPatchDraw(bool fill_quads)
-{
- // TODO(sergey): Some of the stuff could be done once after the whole
- // mesh is displayed.
- /// Restore state.
- if (!fill_quads) {
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- }
- glBindVertexArray(0);
- if (g_use_osd_glsl) {
- // TODO(sergey): Store previously used program and roll back to it?
- glUseProgram(0);
- }
-}
-
-void drawPartitionPatchesRange(GLMeshInterface *mesh,
- GLuint program,
- int start_patch,
- int num_patches)
-{
- int traversed_patches = 0, num_remained_patches = num_patches;
- const OpenSubdiv::Osd::PatchArrayVector &patches = mesh->GetPatchTable()->GetPatchArrays();
- for (int i = 0; i < patches.size(); ++i) {
- const OpenSubdiv::Osd::PatchArray &patch = patches[i];
- OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
- OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
- if (patchType == OpenSubdiv::Far::PatchDescriptor::QUADS) {
- const int num_block_patches = patch.GetNumPatches();
- if (start_patch >= traversed_patches &&
- start_patch < traversed_patches + num_block_patches) {
- const int num_control_verts = desc.GetNumControlVertices();
- const int start_draw_patch = start_patch - traversed_patches;
- const int num_draw_patches = min(num_remained_patches,
- num_block_patches - start_draw_patch);
- perform_drawElements(program,
- i + start_draw_patch,
- num_draw_patches * num_control_verts,
- patch.GetIndexBase() + start_draw_patch * num_control_verts);
- num_remained_patches -= num_draw_patches;
- }
- if (num_remained_patches == 0) {
- break;
- }
- traversed_patches += num_block_patches;
- }
- }
-}
-
-static void drawAllPatches(GLMeshInterface *mesh, GLuint program)
-{
- const OpenSubdiv::Osd::PatchArrayVector &patches = mesh->GetPatchTable()->GetPatchArrays();
- for (int i = 0; i < patches.size(); ++i) {
- const OpenSubdiv::Osd::PatchArray &patch = patches[i];
- OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
- OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
-
- if (patchType == OpenSubdiv::Far::PatchDescriptor::QUADS) {
- perform_drawElements(
- program, i, patch.GetNumPatches() * desc.GetNumControlVertices(), patch.GetIndexBase());
- }
- }
-}
-
-} // namespace
-
-void GLMeshDisplayPrepare(struct OpenSubdiv_GLMesh * /*gl_mesh*/,
- const bool use_osd_glsl,
- const int active_uv_index)
-{
- g_active_uv_index = active_uv_index;
- g_use_osd_glsl = (use_osd_glsl != 0);
- // Update transformation matrices.
- glGetFloatv(GL_PROJECTION_MATRIX, g_transform.projection_matrix);
- glGetFloatv(GL_MODELVIEW_MATRIX, g_transform.model_view_matrix);
- copy_m3_m4((float(*)[3])g_transform.normal_matrix, (float(*)[4])g_transform.model_view_matrix);
- invert_m3((float(*)[3])g_transform.normal_matrix);
- transpose_m3((float(*)[3])g_transform.normal_matrix);
- // Update OpenGL lights positions, colors etc.
- g_lighting_data.num_enabled = 0;
- for (int i = 0; i < MAX_LIGHTS; ++i) {
- GLboolean enabled;
- glGetBooleanv(GL_LIGHT0 + i, &enabled);
- if (enabled) {
- g_lighting_data.num_enabled++;
- }
- // TODO(sergey): Stop using glGetLight.
- glGetLightfv(GL_LIGHT0 + i, GL_POSITION, g_lighting_data.lights[i].position);
- glGetLightfv(GL_LIGHT0 + i, GL_AMBIENT, g_lighting_data.lights[i].ambient);
- glGetLightfv(GL_LIGHT0 + i, GL_DIFFUSE, g_lighting_data.lights[i].diffuse);
- glGetLightfv(GL_LIGHT0 + i, GL_SPECULAR, g_lighting_data.lights[i].specular);
- glGetLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, g_lighting_data.lights[i].spot_direction);
-#ifdef SUPPORT_COLOR_MATERIAL
- glGetLightfv(
- GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &g_lighting_data.lights[i].constant_attenuation);
- glGetLightfv(
- GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &g_lighting_data.lights[i].linear_attenuation);
- glGetLightfv(
- GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &g_lighting_data.lights[i].quadratic_attenuation);
- glGetLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &g_lighting_data.lights[i].spot_cutoff);
- glGetLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &g_lighting_data.lights[i].spot_exponent);
- g_lighting_data.lights[i].spot_cos_cutoff = cos(g_lighting_data.lights[i].spot_cutoff);
-#endif
- }
-}
-
-void GLMeshDisplayDrawPatches(OpenSubdiv_GLMesh *gl_mesh,
- const bool fill_quads,
- const int start_patch,
- const int num_patches)
-{
- GLMeshInterface *mesh = gl_mesh->internal->mesh_interface;
- // Make sure all global invariants are initialized.
- if (!openSubdiv_initGLMeshDrawingResources()) {
- return;
- }
- /// Setup GLSL/OpenGL to draw patches in current context.
- GLuint program = prepare_patchDraw(gl_mesh, fill_quads != 0);
- if (start_patch != -1) {
- drawPartitionPatchesRange(mesh, program, start_patch, num_patches);
- }
- else {
- drawAllPatches(mesh, program);
- }
- // Finish patch drawing by restoring all changes to the OpenGL context.
- finishPatchDraw(fill_quads != 0);
-}
-
-} // namespace opensubdiv_capi
diff --git a/intern/opensubdiv/internal/opensubdiv_gl_mesh_draw.h b/intern/opensubdiv/internal/opensubdiv_gl_mesh_draw.h
deleted file mode 100644
index 599ab9550e7..00000000000
--- a/intern/opensubdiv/internal/opensubdiv_gl_mesh_draw.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2013 Blender Foundation. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-// Author: Sergey Sharybin
-
-#ifndef OPENSUBDIV_GL_MESH_DRAW_H_
-#define OPENSUBDIV_GL_MESH_DRAW_H_
-
-#include <stdint.h> // for bool
-
-struct OpenSubdiv_GLMesh;
-
-namespace opensubdiv_capi {
-
-void GLMeshDisplayPrepare(struct OpenSubdiv_GLMesh *gl_mesh,
- const bool use_osd_glsl,
- const int active_uv_index);
-
-void GLMeshDisplayDrawPatches(OpenSubdiv_GLMesh *gl_mesh,
- const bool fill_quads,
- const int start_patch,
- const int num_patches);
-
-} // namespace opensubdiv_capi
-
-#endif // OPENSUBDIV_GL_MESH_DRAW_H_
diff --git a/intern/opensubdiv/internal/opensubdiv_gl_mesh_fvar.cc b/intern/opensubdiv/internal/opensubdiv_gl_mesh_fvar.cc
deleted file mode 100644
index 6efbe93d2d8..00000000000
--- a/intern/opensubdiv/internal/opensubdiv_gl_mesh_fvar.cc
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright 2013 Blender Foundation. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-// Author: Sergey Sharybin
-
-#include "internal/opensubdiv_gl_mesh_fvar.h"
-
-#include <GL/glew.h>
-#include <opensubdiv/far/primvarRefiner.h>
-
-#include "internal/opensubdiv_util.h"
-
-namespace opensubdiv_capi {
-
-////////////////////////////////////////////////////////////////////////////////
-// GLMeshFVarData
-
-GLMeshFVarData::GLMeshFVarData() : texture_buffer(0), offset_buffer(0)
-{
-}
-
-GLMeshFVarData::~GLMeshFVarData()
-{
- release();
-}
-
-void GLMeshFVarData::release()
-{
- if (texture_buffer) {
- glDeleteTextures(1, &texture_buffer);
- }
- if (offset_buffer) {
- glDeleteTextures(1, &offset_buffer);
- }
- texture_buffer = 0;
- offset_buffer = 0;
- fvar_width = 0;
- channel_offsets.clear();
-}
-
-void GLMeshFVarData::create(const OpenSubdiv::Far::TopologyRefiner *topology_refiner,
- const OpenSubdiv::Far::PatchTable *patch_table,
- int fvar_width,
- const float *fvar_src_data)
-{
- release();
- this->fvar_width = fvar_width;
- /// Expand fvar data to per-patch array.
- const int max_level = topology_refiner->GetMaxLevel();
- const int num_channels = patch_table->GetNumFVarChannels();
- vector<float> data;
- int fvar_data_offset = 0;
- channel_offsets.resize(num_channels);
- for (int channel = 0; channel < num_channels; ++channel) {
- OpenSubdiv::Far::ConstIndexArray indices = patch_table->GetFVarValues(channel);
- channel_offsets[channel] = data.size();
- data.reserve(data.size() + indices.size() * fvar_width);
- for (int fvert = 0; fvert < indices.size(); ++fvert) {
- int index = indices[fvert] * fvar_width;
- for (int i = 0; i < fvar_width; ++i) {
- data.push_back(fvar_src_data[fvar_data_offset + index++]);
- }
- }
- if (topology_refiner->IsUniform()) {
- const int num_values_max = topology_refiner->GetLevel(max_level).GetNumFVarValues(channel);
- fvar_data_offset += num_values_max * fvar_width;
- }
- else {
- const int num_values_total = topology_refiner->GetNumFVarValuesTotal(channel);
- fvar_data_offset += num_values_total * fvar_width;
- }
- }
- GLuint buffer;
- glGenBuffers(1, &buffer);
- glBindBuffer(GL_ARRAY_BUFFER, buffer);
- glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(float), &data[0], GL_STATIC_DRAW);
- glGenTextures(1, &texture_buffer);
- glBindTexture(GL_TEXTURE_BUFFER, texture_buffer);
- glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, buffer);
- glDeleteBuffers(1, &buffer);
- glGenBuffers(1, &buffer);
- glBindBuffer(GL_ARRAY_BUFFER, buffer);
- glBufferData(
- GL_ARRAY_BUFFER, channel_offsets.size() * sizeof(int), &channel_offsets[0], GL_STATIC_DRAW);
- glGenTextures(1, &offset_buffer);
- glBindTexture(GL_TEXTURE_BUFFER, offset_buffer);
- glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, buffer);
- glBindTexture(GL_TEXTURE_BUFFER, 0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Helper functions.
-
-struct FVarVertex {
- float u, v;
-
- void Clear()
- {
- u = v = 0.0f;
- }
-
- void AddWithWeight(FVarVertex const &src, float weight)
- {
- u += weight * src.u;
- v += weight * src.v;
- }
-};
-
-void interpolateFVarData(const OpenSubdiv::Far::TopologyRefiner &refiner,
- const vector<float> &uvs,
- vector<float> *fvar_data)
-{
- const int fvar_width = 2;
- const int max_level = refiner.GetMaxLevel();
- size_t fvar_data_offset = 0, values_offset = 0;
- for (int channel = 0; channel < refiner.GetNumFVarChannels(); ++channel) {
- const int num_values = refiner.GetLevel(0).GetNumFVarValues(channel) * 2;
- const int num_values_max = refiner.GetLevel(max_level).GetNumFVarValues(channel);
- const int num_values_total = refiner.GetNumFVarValuesTotal(channel);
- if (num_values_total <= 0) {
- continue;
- }
- OpenSubdiv::Far::PrimvarRefiner primvar_refiner(refiner);
- if (refiner.IsUniform()) {
- // For uniform we only keep the highest level of refinement.
- fvar_data->resize(fvar_data->size() + num_values_max * fvar_width);
- vector<FVarVertex> buffer(num_values_total - num_values_max);
- FVarVertex *src = &buffer[0];
- memcpy(src, &uvs[values_offset], num_values * sizeof(float));
- // Defer the last level to treat separately with its alternate
- // destination.
- for (int level = 1; level < max_level; ++level) {
- FVarVertex *dst = src + refiner.GetLevel(level - 1).GetNumFVarValues(channel);
- primvar_refiner.InterpolateFaceVarying(level, src, dst, channel);
- src = dst;
- }
- FVarVertex *dst = reinterpret_cast<FVarVertex *>(&(*fvar_data)[fvar_data_offset]);
- primvar_refiner.InterpolateFaceVarying(max_level, src, dst, channel);
- fvar_data_offset += num_values_max * fvar_width;
- }
- else {
- // For adaptive we keep all levels.
- fvar_data->resize(fvar_data->size() + num_values_total * fvar_width);
- FVarVertex *src = reinterpret_cast<FVarVertex *>(&(*fvar_data)[fvar_data_offset]);
- memcpy(src, &uvs[values_offset], num_values * sizeof(float));
- for (int level = 1; level <= max_level; ++level) {
- FVarVertex *dst = src + refiner.GetLevel(level - 1).GetNumFVarValues(channel);
- primvar_refiner.InterpolateFaceVarying(level, src, dst, channel);
- src = dst;
- }
- fvar_data_offset += num_values_total * fvar_width;
- }
- values_offset += num_values;
- }
-}
-
-} // namespace opensubdiv_capi
diff --git a/intern/opensubdiv/internal/opensubdiv_gl_mesh_fvar.h b/intern/opensubdiv/internal/opensubdiv_gl_mesh_fvar.h
deleted file mode 100644
index 73a1af05605..00000000000
--- a/intern/opensubdiv/internal/opensubdiv_gl_mesh_fvar.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2013 Blender Foundation. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-// Author: Sergey Sharybin
-
-#ifndef OPENSUBDIV_GL_MESH_FVAR_H_
-#define OPENSUBDIV_GL_MESH_FVAR_H_
-
-// NOTE: This is a [sane(er)] port of previous ground work for getting UVs to
-// work. Still needs a lot of work to make it easy, correct and have proper
-// data ownership.
-
-#include <opensubdiv/far/patchTable.h>
-#include <opensubdiv/far/topologyRefiner.h>
-
-#include "internal/opensubdiv_util.h"
-
-namespace opensubdiv_capi {
-
-// The buffer which holds GPU resources for face-varying elements.
-class GLMeshFVarData {
- public:
- GLMeshFVarData();
- ~GLMeshFVarData();
-
- void release();
- void create(const OpenSubdiv::Far::TopologyRefiner *refiner,
- const OpenSubdiv::Far::PatchTable *patch_table,
- int fvar_width,
- const float *fvar_src_data);
-
- unsigned int texture_buffer;
- unsigned int offset_buffer;
- vector<int> channel_offsets;
- int fvar_width;
-};
-
-void interpolateFVarData(const OpenSubdiv::Far::TopologyRefiner &refiner,
- const vector<float> &uvs,
- vector<float> *fvar_data);
-
-} // namespace opensubdiv_capi
-
-#endif // OPENSUBDIV_GL_MESH_FVAR_H_
diff --git a/intern/opensubdiv/internal/opensubdiv_gl_mesh_internal.cc b/intern/opensubdiv/internal/opensubdiv_gl_mesh_internal.cc
deleted file mode 100644
index 57e56bad3fb..00000000000
--- a/intern/opensubdiv/internal/opensubdiv_gl_mesh_internal.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2018 Blender Foundation. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-// Author: Sergey Sharybin
-
-#include "internal/opensubdiv_gl_mesh_internal.h"
-
-#include "internal/opensubdiv_gl_mesh_fvar.h"
-
-OpenSubdiv_GLMeshInternal::OpenSubdiv_GLMeshInternal()
- : evaluator_type(OPENSUBDIV_EVALUATOR_CPU), mesh_interface(NULL), fvar_data(NULL)
-{
-}
-
-OpenSubdiv_GLMeshInternal::~OpenSubdiv_GLMeshInternal()
-{
- delete mesh_interface;
- delete fvar_data;
-}
diff --git a/intern/opensubdiv/internal/opensubdiv_gl_mesh_internal.h b/intern/opensubdiv/internal/opensubdiv_gl_mesh_internal.h
deleted file mode 100644
index cb92fb18362..00000000000
--- a/intern/opensubdiv/internal/opensubdiv_gl_mesh_internal.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2018 Blender Foundation. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-// Author: Sergey Sharybin
-
-#ifndef OPENSUBDIV_GL_MESH_INTERNAL_H_
-#define OPENSUBDIV_GL_MESH_INTERNAL_H_
-
-#ifdef _MSC_VER
-# include <iso646.h>
-#endif
-
-#include <opensubdiv/osd/glMesh.h>
-
-#include "opensubdiv_capi_type.h"
-
-namespace opensubdiv_capi {
-class GLMeshFVarData;
-} // namespace opensubdiv_capi
-
-typedef struct OpenSubdiv_GLMeshInternal {
- OpenSubdiv_GLMeshInternal();
- ~OpenSubdiv_GLMeshInternal();
-
- eOpenSubdivEvaluator evaluator_type;
- OpenSubdiv::Osd::GLMeshInterface *mesh_interface;
- opensubdiv_capi::GLMeshFVarData *fvar_data;
-} OpenSubdiv_GLMeshInternal;
-
-#endif // OPENSUBDIV_GL_MESH_INTERNAL_H_
diff --git a/intern/opensubdiv/internal/opensubdiv_topology_refiner.cc b/intern/opensubdiv/internal/opensubdiv_topology_refiner.cc
index ac27cbdefdc..6e2dae4533a 100644
--- a/intern/opensubdiv/internal/opensubdiv_topology_refiner.cc
+++ b/intern/opensubdiv/internal/opensubdiv_topology_refiner.cc
@@ -28,7 +28,7 @@
#include "internal/opensubdiv_topology_refiner_internal.h"
#include "internal/opensubdiv_util.h"
-using opensubdiv_capi::vector;
+using blender::opensubdiv::vector;
namespace {
@@ -182,7 +182,7 @@ int getNumFVarChannels(const struct OpenSubdiv_TopologyRefiner *topology_refiner
OpenSubdiv_FVarLinearInterpolation getFVarLinearInterpolation(
const struct OpenSubdiv_TopologyRefiner *topology_refiner)
{
- return opensubdiv_capi::getCAPIFVarLinearInterpolationFromOSD(
+ return blender::opensubdiv::getCAPIFVarLinearInterpolationFromOSD(
getOSDTopologyRefiner(topology_refiner)->GetFVarLinearInterpolation());
}
@@ -243,7 +243,7 @@ OpenSubdiv_TopologyRefiner *openSubdiv_createTopologyRefinerFromConverter(
OpenSubdiv_Converter *converter, const OpenSubdiv_TopologyRefinerSettings *settings)
{
OpenSubdiv::Far::TopologyRefiner *osd_topology_refiner =
- opensubdiv_capi::createOSDTopologyRefinerFromConverter(converter);
+ blender::opensubdiv::createOSDTopologyRefinerFromConverter(converter);
if (osd_topology_refiner == NULL) {
// Happens on empty or bad topology.
return NULL;
@@ -265,7 +265,8 @@ void openSubdiv_deleteTopologyRefiner(OpenSubdiv_TopologyRefiner *topology_refin
////////////////////////////////////////////////////////////////////////////////
// Comparison with converter.
-namespace opensubdiv_capi {
+namespace blender {
+namespace opensubdiv {
namespace {
///////////////////////////////////////////////////////////
@@ -274,8 +275,8 @@ namespace {
bool checkSchemeTypeMatches(const OpenSubdiv::Far::TopologyRefiner *topology_refiner,
const OpenSubdiv_Converter *converter)
{
- const OpenSubdiv::Sdc::SchemeType converter_scheme_type = opensubdiv_capi::getSchemeTypeFromCAPI(
- converter->getSchemeType(converter));
+ const OpenSubdiv::Sdc::SchemeType converter_scheme_type =
+ blender::opensubdiv::getSchemeTypeFromCAPI(converter->getSchemeType(converter));
return (converter_scheme_type == topology_refiner->GetSchemeType());
}
@@ -286,7 +287,7 @@ bool checkOptionsMatches(const OpenSubdiv::Far::TopologyRefiner *topology_refine
const Options options = topology_refiner->GetSchemeOptions();
const Options::FVarLinearInterpolation fvar_interpolation = options.GetFVarLinearInterpolation();
const Options::FVarLinearInterpolation converter_fvar_interpolation =
- opensubdiv_capi::getFVarLinearInterpolationFromCAPI(
+ blender::opensubdiv::getFVarLinearInterpolationFromCAPI(
converter->getFVarLinearInterpolation(converter));
if (fvar_interpolation != converter_fvar_interpolation) {
return false;
@@ -660,13 +661,14 @@ bool checkTopologyAttributesMatch(const OpenSubdiv::Far::TopologyRefiner *topolo
}
} // namespace
-} // namespace opensubdiv_capi
+} // namespace opensubdiv
+} // namespace blender
bool openSubdiv_topologyRefinerCompareWithConverter(
const OpenSubdiv_TopologyRefiner *topology_refiner, const OpenSubdiv_Converter *converter)
{
const OpenSubdiv::Far::TopologyRefiner *refiner = getOSDTopologyRefiner(topology_refiner);
- return (opensubdiv_capi::checkPreliminaryMatches(refiner, converter) &&
- opensubdiv_capi::checkGeometryMatches(refiner, converter) &&
- opensubdiv_capi::checkTopologyAttributesMatch(refiner, converter));
+ return (blender::opensubdiv::checkPreliminaryMatches(refiner, converter) &&
+ blender::opensubdiv::checkGeometryMatches(refiner, converter) &&
+ blender::opensubdiv::checkTopologyAttributesMatch(refiner, converter));
}
diff --git a/intern/opensubdiv/internal/opensubdiv_util.cc b/intern/opensubdiv/internal/opensubdiv_util.cc
index 6e6f3a0920f..ea61b21e5d0 100644
--- a/intern/opensubdiv/internal/opensubdiv_util.cc
+++ b/intern/opensubdiv/internal/opensubdiv_util.cc
@@ -23,7 +23,8 @@
# include <iso646.h>
#endif
-namespace opensubdiv_capi {
+namespace blender {
+namespace opensubdiv {
void stringSplit(vector<string> *tokens,
const string &str,
@@ -56,4 +57,5 @@ void stringSplit(vector<string> *tokens,
}
}
-} // namespace opensubdiv_capi
+} // namespace opensubdiv
+} // namespace blender
diff --git a/intern/opensubdiv/internal/opensubdiv_util.h b/intern/opensubdiv/internal/opensubdiv_util.h
index e515859b42f..3fcfdd4c32b 100644
--- a/intern/opensubdiv/internal/opensubdiv_util.h
+++ b/intern/opensubdiv/internal/opensubdiv_util.h
@@ -27,7 +27,8 @@
#include <utility>
#include <vector>
-namespace opensubdiv_capi {
+namespace blender {
+namespace opensubdiv {
using std::fill;
using std::make_pair;
@@ -51,6 +52,7 @@ void stringSplit(vector<string> *tokens,
const string &separators,
bool skip_empty);
-} // namespace opensubdiv_capi
+} // namespace opensubdiv
+} // namespace blender
#endif // OPENSUBDIV_UTIL_H_
diff --git a/intern/opensubdiv/opensubdiv_gl_mesh_capi.h b/intern/opensubdiv/opensubdiv_gl_mesh_capi.h
deleted file mode 100644
index f7dd6f83434..00000000000
--- a/intern/opensubdiv/opensubdiv_gl_mesh_capi.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2013 Blender Foundation. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-// Author: Sergey Sharybin
-
-#ifndef OPENSUBDIV_CAPI_GL_MESH_CAPI_H_
-#define OPENSUBDIV_CAPI_GL_MESH_CAPI_H_
-
-#include <stdint.h> // for bool
-
-#include "opensubdiv_capi_type.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct OpenSubdiv_GLMeshInternal;
-
-// Mesh which is displayable in OpenGL context.
-typedef struct OpenSubdiv_GLMesh {
- //////////////////////////////////////////////////////////////////////////////
- // Subdivision/topology part.
-
- // Returns the GL index buffer containing the patch control vertices.
- unsigned int (*getPatchIndexBuffer)(struct OpenSubdiv_GLMesh *gl_mesh);
-
- // Bind GL buffer which contains vertices (VBO).
- // TODO(sergey): Is this a coarse vertices?
- void (*bindVertexBuffer)(struct OpenSubdiv_GLMesh *gl_mesh);
-
- // Set coarse positions from a continuous array of coordinates.
- void (*setCoarsePositions)(struct OpenSubdiv_GLMesh *gl_mesh,
- const float *positions,
- const int start_vertex,
- const int num_vertices);
- // TODO(sergey): setCoarsePositionsFromBuffer().
-
- // Refine after coarse positions update.
- void (*refine)(struct OpenSubdiv_GLMesh *gl_mesh);
-
- // Synchronize after coarse positions update and refine.
- void (*synchronize)(struct OpenSubdiv_GLMesh *gl_mesh);
-
- //////////////////////////////////////////////////////////////////////////////
- // Drawing part.
-
- // Prepare mesh for display.
- void (*prepareDraw)(struct OpenSubdiv_GLMesh *gl_mesh,
- const bool use_osd_glsl,
- const int active_uv_index);
-
- // Draw given range of patches.
- //
- // If fill_quads is false, then patches are drawn in wireframe.
- void (*drawPatches)(struct OpenSubdiv_GLMesh *gl_mesh,
- const bool fill_quads,
- const int start_patch,
- const int num_patches);
-
- // Internal storage for the use in this module only.
- //
- // Tease: This contains an actual OpenSubdiv's Mesh object.
- struct OpenSubdiv_GLMeshInternal *internal;
-} OpenSubdiv_GLMesh;
-
-OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
- struct OpenSubdiv_TopologyRefiner *topology_refiner, eOpenSubdivEvaluator evaluator_type);
-
-void openSubdiv_deleteOsdGLMesh(OpenSubdiv_GLMesh *gl_mesh);
-
-// Global resources needed for GL mesh drawing.
-bool openSubdiv_initGLMeshDrawingResources(void);
-void openSubdiv_deinitGLMeshDrawingResources(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // OPENSUBDIV_CAPI_GL_MESH_CAPI_H_
diff --git a/intern/opensubdiv/shader/gpu_shader_opensubdiv_fragment.glsl b/intern/opensubdiv/shader/gpu_shader_opensubdiv_fragment.glsl
deleted file mode 100644
index 7f08182d78a..00000000000
--- a/intern/opensubdiv/shader/gpu_shader_opensubdiv_fragment.glsl
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2014 Blender Foundation.
- * All rights reserved.
- */
-
-struct VertexData {
- vec4 position;
- vec3 normal;
- vec2 uv;
-};
-
-#define MAX_LIGHTS 8
-#define NUM_SOLID_LIGHTS 3
-
-struct LightSource {
- vec4 position;
- vec4 ambient;
- vec4 diffuse;
- vec4 specular;
- vec4 spotDirection;
-#ifdef SUPPORT_COLOR_MATERIAL
- float constantAttenuation;
- float linearAttenuation;
- float quadraticAttenuation;
- float spotCutoff;
- float spotExponent;
- float spotCosCutoff;
- float pad, pad2;
-#endif
-};
-
-layout(std140) uniform Lighting
-{
- LightSource lightSource[MAX_LIGHTS];
- int num_enabled_lights;
-};
-
-uniform vec4 diffuse;
-uniform vec4 specular;
-uniform float shininess;
-
-uniform sampler2D texture_buffer;
-
-in block
-{
- VertexData v;
-}
-inpt;
-
-void main()
-{
-#ifdef WIREFRAME
- gl_FragColor = diffuse;
-#else
- vec3 N = inpt.v.normal;
-
- if (!gl_FrontFacing)
- N = -N;
-
- /* Compute diffuse and specular lighting. */
- vec3 L_diffuse = vec3(0.0);
- vec3 L_specular = vec3(0.0);
-
-# ifdef USE_LIGHTING
-# ifndef USE_COLOR_MATERIAL
- /* Assume NUM_SOLID_LIGHTS directional lights. */
- for (int i = 0; i < NUM_SOLID_LIGHTS; i++) {
- vec4 Plight = lightSource[i].position;
-# ifdef USE_DIRECTIONAL_LIGHT
- vec3 l = (Plight.w == 0.0) ? normalize(Plight.xyz) : normalize(inpt.v.position.xyz);
-# else /* USE_DIRECTIONAL_LIGHT */
- /* TODO(sergey): We can normalize it outside of the shader. */
- vec3 l = normalize(Plight.xyz);
-# endif /* USE_DIRECTIONAL_LIGHT */
- vec3 h = normalize(l + vec3(0, 0, 1));
- float d = max(0.0, dot(N, l));
- float s = pow(max(0.0, dot(N, h)), shininess);
- L_diffuse += d * lightSource[i].diffuse.rgb;
- L_specular += s * lightSource[i].specular.rgb;
- }
-# else /* USE_COLOR_MATERIAL */
- vec3 varying_position = inpt.v.position.xyz;
- vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(varying_position) : vec3(0.0, 0.0, -1.0);
- for (int i = 0; i < num_enabled_lights; i++) {
- /* todo: this is a slow check for disabled lights */
- if (lightSource[i].specular.a == 0.0)
- continue;
-
- float intensity = 1.0;
- vec3 light_direction;
-
- if (lightSource[i].position.w == 0.0) {
- /* directional light */
- light_direction = lightSource[i].position.xyz;
- }
- else {
- /* point light */
- vec3 d = lightSource[i].position.xyz - varying_position;
- light_direction = normalize(d);
-
- /* spot light cone */
- if (lightSource[i].spotCutoff < 90.0) {
- float cosine = max(dot(light_direction, -lightSource[i].spotDirection.xyz), 0.0);
- intensity = pow(cosine, lightSource[i].spotExponent);
- intensity *= step(lightSource[i].spotCosCutoff, cosine);
- }
-
- /* falloff */
- float distance = length(d);
-
- intensity /= lightSource[i].constantAttenuation +
- lightSource[i].linearAttenuation * distance +
- lightSource[i].quadraticAttenuation * distance * distance;
- }
-
- /* diffuse light */
- vec3 light_diffuse = lightSource[i].diffuse.rgb;
- float diffuse_bsdf = max(dot(N, light_direction), 0.0);
- L_diffuse += light_diffuse * diffuse_bsdf * intensity;
-
- /* specular light */
- vec3 light_specular = lightSource[i].specular.rgb;
- vec3 H = normalize(light_direction - V);
-
- float specular_bsdf = pow(max(dot(N, H), 0.0), gl_FrontMaterial.shininess);
- L_specular += light_specular * specular_bsdf * intensity;
- }
-# endif /* USE_COLOR_MATERIAL */
-# else /* USE_LIGHTING */
- L_diffuse = vec3(1.0);
-# endif
-
- /* Compute diffuse color. */
-# ifdef USE_TEXTURE_2D
- L_diffuse *= texture2D(texture_buffer, inpt.v.uv).rgb;
-# else
- L_diffuse *= diffuse.rgb;
-# endif
-
- /* Sum lighting. */
- vec3 L = L_diffuse;
- if (shininess != 0) {
- L += L_specular * specular.rgb;
- }
-
- /* Write out fragment color. */
- gl_FragColor = vec4(L, diffuse.a);
-#endif
-}
diff --git a/intern/opensubdiv/shader/gpu_shader_opensubdiv_geometry.glsl b/intern/opensubdiv/shader/gpu_shader_opensubdiv_geometry.glsl
deleted file mode 100644
index 37bc0720113..00000000000
--- a/intern/opensubdiv/shader/gpu_shader_opensubdiv_geometry.glsl
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2014 Blender Foundation.
- * All rights reserved.
- */
-
-struct VertexData {
- vec4 position;
- vec3 normal;
- vec2 uv;
-};
-
-layout(lines_adjacency) in;
-#ifdef WIREFRAME
-layout(line_strip, max_vertices = 8) out;
-#else
-layout(triangle_strip, max_vertices = 4) out;
-#endif
-
-uniform mat4 modelViewMatrix;
-uniform mat4 projectionMatrix;
-uniform int PrimitiveIdBase;
-uniform int osd_fvar_count;
-uniform int osd_active_uv_offset;
-
-in block
-{
- VertexData v;
-}
-inpt[];
-
-#define INTERP_FACE_VARYING_2(result, fvarOffset, tessCoord) \
- { \
- vec2 v[4]; \
- int primOffset = (gl_PrimitiveID + PrimitiveIdBase) * 4; \
- for (int i = 0; i < 4; ++i) { \
- int index = (primOffset + i) * osd_fvar_count + fvarOffset; \
- v[i] = vec2(texelFetch(FVarDataBuffer, index).s, texelFetch(FVarDataBuffer, index + 1).s); \
- } \
- result = mix(mix(v[0], v[1], tessCoord.s), mix(v[3], v[2], tessCoord.s), tessCoord.t); \
- }
-
-uniform samplerBuffer FVarDataBuffer;
-uniform isamplerBuffer FVarDataOffsetBuffer;
-
-out block
-{
- VertexData v;
-}
-outpt;
-
-#ifdef FLAT_SHADING
-void emit(int index, vec3 normal)
-{
- outpt.v.position = inpt[index].v.position;
- outpt.v.normal = normal;
-
- /* TODO(sergey): Only uniform subdivisions atm. */
- vec2 quadst[4] = vec2[](vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1));
- vec2 st = quadst[index];
-
- INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
-
- gl_Position = projectionMatrix * inpt[index].v.position;
- EmitVertex();
-}
-
-# ifdef WIREFRAME
-void emit_edge(int v0, int v1, vec3 normal)
-{
- emit(v0, normal);
- emit(v1, normal);
-}
-# endif
-
-#else
-void emit(int index)
-{
- outpt.v.position = inpt[index].v.position;
- outpt.v.normal = inpt[index].v.normal;
-
- /* TODO(sergey): Only uniform subdivisions atm. */
- vec2 quadst[4] = vec2[](vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1));
- vec2 st = quadst[index];
-
- INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
-
- gl_Position = projectionMatrix * inpt[index].v.position;
- EmitVertex();
-}
-
-# ifdef WIREFRAME
-void emit_edge(int v0, int v1)
-{
- emit(v0);
- emit(v1);
-}
-# endif
-
-#endif
-
-void main()
-{
- gl_PrimitiveID = gl_PrimitiveIDIn;
-
-#ifdef FLAT_SHADING
- vec3 A = (inpt[0].v.position - inpt[1].v.position).xyz;
- vec3 B = (inpt[3].v.position - inpt[1].v.position).xyz;
- vec3 flat_normal = normalize(cross(B, A));
-# ifndef WIREFRAME
- emit(0, flat_normal);
- emit(1, flat_normal);
- emit(3, flat_normal);
- emit(2, flat_normal);
-# else
- emit_edge(0, 1, flat_normal);
- emit_edge(1, 2, flat_normal);
- emit_edge(2, 3, flat_normal);
- emit_edge(3, 0, flat_normal);
-# endif
-#else
-# ifndef WIREFRAME
- emit(0);
- emit(1);
- emit(3);
- emit(2);
-# else
- emit_edge(0, 1);
- emit_edge(1, 2);
- emit_edge(2, 3);
- emit_edge(3, 0);
-# endif
-#endif
-
- EndPrimitive();
-}
diff --git a/intern/opensubdiv/shader/gpu_shader_opensubdiv_vertex.glsl b/intern/opensubdiv/shader/gpu_shader_opensubdiv_vertex.glsl
deleted file mode 100644
index 474a716e927..00000000000
--- a/intern/opensubdiv/shader/gpu_shader_opensubdiv_vertex.glsl
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2014 Blender Foundation.
- * All rights reserved.
- */
-
-struct VertexData {
- vec4 position;
- vec3 normal;
- vec2 uv;
-};
-
-in vec3 normal;
-in vec4 position;
-
-uniform mat4 modelViewMatrix;
-uniform mat3 normalMatrix;
-
-out block
-{
- VertexData v;
-}
-outpt;
-
-void main()
-{
- outpt.v.position = modelViewMatrix * position;
- outpt.v.normal = normalize(normalMatrix * normal);
-}
diff --git a/intern/opensubdiv/stub/opensubdiv_gl_mesh_stub.cc b/intern/opensubdiv/stub/opensubdiv_gl_mesh_stub.cc
deleted file mode 100644
index 91ac0676dbd..00000000000
--- a/intern/opensubdiv/stub/opensubdiv_gl_mesh_stub.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2018 Blender Foundation. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-// Author: Sergey Sharybin
-
-#include "opensubdiv_gl_mesh_capi.h"
-
-#include <cstddef>
-
-struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
- OpenSubdiv_TopologyRefiner * /*topology_refiner*/, eOpenSubdivEvaluator /*evaluator_type*/)
-{
- return NULL;
-}
-
-void openSubdiv_deleteOsdGLMesh(OpenSubdiv_GLMesh * /*gl_mesh*/)
-{
-}
-
-bool openSubdiv_initGLMeshDrawingResources(void)
-{
- return false;
-}
-
-void openSubdiv_deinitGLMeshDrawingResources(void)
-{
-}
diff --git a/intern/rigidbody/rb_bullet_api.cpp b/intern/rigidbody/rb_bullet_api.cpp
index a928aaca049..a8bf1420523 100644
--- a/intern/rigidbody/rb_bullet_api.cpp
+++ b/intern/rigidbody/rb_bullet_api.cpp
@@ -218,8 +218,8 @@ void RB_dworld_step_simulation(rbDynamicsWorld *world,
* Exports entire dynamics world to Bullet's "*.bullet" binary format
* which is similar to Blender's SDNA system.
*
- * \param world Dynamics world to write to file
- * \param filename Assumed to be a valid filename, with .bullet extension
+ * \param world: Dynamics world to write to file
+ * \param filename: Assumed to be a valid filename, with .bullet extension
*/
void RB_dworld_export(rbDynamicsWorld *world, const char *filename)
{
diff --git a/intern/string/CMakeLists.txt b/intern/string/CMakeLists.txt
deleted file mode 100644
index 8c400f320ae..00000000000
--- a/intern/string/CMakeLists.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# The Original Code is Copyright (C) 2006, Blender Foundation
-# All rights reserved.
-# ***** END GPL LICENSE BLOCK *****
-
-set(INC
- .
-)
-
-set(INC_SYS
-
-)
-
-set(SRC
- intern/STR_String.cpp
-
- STR_String.h
-)
-
-set(LIB
-)
-
-blender_add_lib(bf_intern_string "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/intern/string/STR_String.h b/intern/string/STR_String.h
deleted file mode 100644
index 97b23345f91..00000000000
--- a/intern/string/STR_String.h
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- */
-
-/** \file
- * \ingroup string
- */
-
-#ifndef __STR_STRING_H__
-#define __STR_STRING_H__
-
-#ifndef STR_NO_ASSERTD
-# undef assertd
-# define assertd(exp) ((void)NULL)
-#endif
-
-#include <limits.h>
-#include <vector>
-
-#include <cstdlib>
-#include <cstring>
-
-#ifdef WITH_CXX_GUARDEDALLOC
-# include "MEM_guardedalloc.h"
-#endif
-
-#ifdef _WIN32
-# define stricmp _stricmp
-#endif
-
-class STR_String;
-
-typedef unsigned long dword;
-typedef const STR_String &rcSTR_String;
-typedef unsigned char byte;
-
-/**
- * Smart String Value class. Is used by parser when an expression tree is build containing string.
- */
-
-class STR_String {
- public:
- // Initialization
- STR_String();
- STR_String(char c);
- STR_String(char c, int len);
- STR_String(const char *str);
- STR_String(const char *str, int len);
- STR_String(const STR_String &str);
- STR_String(const STR_String &str, int len);
- STR_String(const char *src1, int src1_len, const char *src2, int src2_len);
- explicit STR_String(int val);
- explicit STR_String(dword val);
- explicit STR_String(float val);
- explicit STR_String(double val);
- inline ~STR_String()
- {
- delete[] this->m_data;
- }
-
- // Operations
- STR_String &Format(const char *fmt, ...) // Set formatted text to string
-#ifdef __GNUC__
- __attribute__((format(printf, 2, 3)))
-#endif
- ;
- STR_String &FormatAdd(const char *fmt, ...) // Add formatted text to string
-#ifdef __GNUC__
- __attribute__((format(printf, 2, 3)))
-#endif
- ;
- inline void Clear()
- {
- this->m_len = this->m_data[0] = 0;
- }
- inline const STR_String &Reverse()
- {
- for (int i1 = 0, i2 = this->m_len - 1; i1 < i2; i1++, i2--) {
- std::swap(this->m_data[i1], this->m_data[i2]);
- }
- return *this;
- }
-
- // Properties
- bool IsUpper() const;
- bool IsLower() const;
- inline bool IsEmpty() const
- {
- return this->m_len == 0;
- }
- inline int Length() const
- {
- return this->m_len;
- }
-
- // Data access
- inline STR_String &SetLength(int len)
- {
- AllocBuffer(len, true);
- this->m_len = len;
- this->m_data[len] = 0;
- return *this;
- }
- inline char GetAt(int pos) const
- {
- assertd(pos < this->m_len);
- return this->m_data[pos];
- }
- inline void SetAt(int pos, char c)
- {
- assertd(pos < this->m_len);
- this->m_data[pos] = c;
- }
- inline void SetAt(int pos, rcSTR_String str);
- inline void SetAt(int pos, int num, rcSTR_String str);
- void Replace(int pos, rcSTR_String str);
- void Replace(int pos, int num, rcSTR_String str);
-
- // Substrings
- inline STR_String Left(int num) const
- {
- num = (num < this->m_len ? num : this->m_len);
- return STR_String(this->m_data, num);
- }
- inline STR_String Right(int num) const
- {
- num = (num < this->m_len ? num : this->m_len);
- return STR_String(this->m_data + this->m_len - num, num);
- }
- inline STR_String Mid(int pos, int num = INT_MAX) const
- {
- pos = (pos < this->m_len ? pos : this->m_len);
- num = (num < (this->m_len - pos) ? num : (this->m_len - pos));
- return STR_String(this->m_data + pos, num);
- }
-
- // Comparison
- int Compare(rcSTR_String rhs) const;
- int CompareNoCase(rcSTR_String rhs) const;
- inline bool IsEqual(rcSTR_String rhs) const
- {
- return (Compare(rhs) == 0);
- }
- inline bool IsEqualNoCase(rcSTR_String rhs) const
- {
- return (CompareNoCase(rhs) == 0);
- }
-
- // Search/replace
- int Find(char c, int pos = 0) const;
- int Find(const char *str, int pos = 0) const;
- int Find(rcSTR_String str, int pos = 0) const;
- int RFind(char c) const;
- int FindOneOf(const char *set, int pos = 0) const;
- int RFindOneOf(const char *set, int pos = 0) const;
-
- std::vector<STR_String> Explode(char c) const;
-
- // Formatting
- STR_String &Upper();
- STR_String &Lower();
- STR_String &Capitalize();
- STR_String &TrimLeft();
- STR_String &TrimLeft(char *set);
- STR_String &TrimRight();
- STR_String &TrimRight(char *set);
- STR_String &Trim();
- STR_String &Trim(char *set);
- STR_String &TrimQuotes();
-
- // Conversions
- // inline operator char*() { return this->m_data; }
- inline operator const char *() const
- {
- return this->m_data;
- }
- inline char *Ptr()
- {
- return this->m_data;
- }
- inline const char *ReadPtr() const
- {
- return this->m_data;
- }
- inline float ToFloat() const
- {
- float x = (float)(atof(this->m_data));
- return x;
- }
- inline int ToInt() const
- {
- return atoi(this->m_data);
- }
-
- // Operators
- inline rcSTR_String operator=(const byte *rhs)
- {
- return Copy((const char *)rhs, strlen((const char *)rhs));
- }
- inline rcSTR_String operator=(rcSTR_String rhs)
- {
- return Copy(rhs.ReadPtr(), rhs.Length());
- }
- inline rcSTR_String operator=(char rhs)
- {
- return Copy(&rhs, 1);
- }
- inline rcSTR_String operator=(const char *rhs)
- {
- return Copy(rhs, strlen(rhs));
- }
-
- inline rcSTR_String operator+=(const char *rhs)
- {
- return Concat(rhs, strlen(rhs));
- }
- inline rcSTR_String operator+=(rcSTR_String rhs)
- {
- return Concat(rhs.ReadPtr(), rhs.Length());
- }
- inline rcSTR_String operator+=(char rhs)
- {
- return Concat(&rhs, 1);
- }
-
- inline friend bool operator<(rcSTR_String lhs, rcSTR_String rhs)
- {
- return (strcmp(lhs, rhs) < 0);
- }
- inline friend bool operator<(rcSTR_String lhs, const char *rhs)
- {
- return (strcmp(lhs, rhs) < 0);
- }
- inline friend bool operator<(const char *lhs, rcSTR_String rhs)
- {
- return (strcmp(lhs, rhs) < 0);
- }
- inline friend bool operator>(rcSTR_String lhs, rcSTR_String rhs)
- {
- return (strcmp(lhs, rhs) > 0);
- }
- inline friend bool operator>(rcSTR_String lhs, const char *rhs)
- {
- return (strcmp(lhs, rhs) > 0);
- }
- inline friend bool operator>(const char *lhs, rcSTR_String rhs)
- {
- return (strcmp(lhs, rhs) > 0);
- }
- inline friend bool operator<=(rcSTR_String lhs, rcSTR_String rhs)
- {
- return (strcmp(lhs, rhs) <= 0);
- }
- inline friend bool operator<=(rcSTR_String lhs, const char *rhs)
- {
- return (strcmp(lhs, rhs) <= 0);
- }
- inline friend bool operator<=(const char *lhs, rcSTR_String rhs)
- {
- return (strcmp(lhs, rhs) <= 0);
- }
- inline friend bool operator>=(rcSTR_String lhs, rcSTR_String rhs)
- {
- return (strcmp(lhs, rhs) >= 0);
- }
- inline friend bool operator>=(rcSTR_String lhs, const char *rhs)
- {
- return (strcmp(lhs, rhs) >= 0);
- }
- inline friend bool operator>=(const char *lhs, rcSTR_String rhs)
- {
- return (strcmp(lhs, rhs) >= 0);
- }
- inline friend bool operator==(rcSTR_String lhs, rcSTR_String rhs)
- {
- return ((lhs.Length() == rhs.Length()) && (memcmp(lhs, rhs, lhs.Length()) == 0));
- }
- inline friend bool operator==(rcSTR_String lhs, const char *rhs)
- {
- return (strncmp(lhs, rhs, lhs.Length() + 1) == 0);
- }
- inline friend bool operator==(const char *lhs, rcSTR_String rhs)
- {
- return (strncmp(lhs, rhs, rhs.Length() + 1) == 0);
- }
- inline friend bool operator!=(rcSTR_String lhs, rcSTR_String rhs)
- {
- return ((lhs.Length() != rhs.Length()) || (memcmp(lhs, rhs, lhs.Length()) != 0));
- }
- inline friend bool operator!=(rcSTR_String lhs, const char *rhs)
- {
- return (strncmp(lhs, rhs, lhs.Length() + 1) != 0);
- }
- inline friend bool operator!=(const char *lhs, rcSTR_String rhs)
- {
- return (strncmp(lhs, rhs, rhs.Length() + 1) != 0);
- }
-
- // serializing
- // int Serialize(pCStream stream);
-
- protected:
- // Implementation
- void AllocBuffer(int len, bool keep_contents);
- rcSTR_String Copy(const char *src, int len);
- rcSTR_String Concat(const char *data, int len);
-
- static bool isLower(char c)
- {
- return !isUpper(c);
- }
- static bool isUpper(char c)
- {
- return (c >= 'A') && (c <= 'Z');
- }
- static bool isSpace(char c)
- {
- return (c == ' ') || (c == '\t');
- }
-
- char *m_data; // -> STR_String data
- int m_len; // z Data length
- int m_max; // Space in data buffer
-
-#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("CXX:STR_String")
-#endif
-};
-
-inline STR_String operator+(rcSTR_String lhs, rcSTR_String rhs)
-{
- return STR_String(lhs.ReadPtr(), lhs.Length(), rhs.ReadPtr(), rhs.Length());
-}
-inline STR_String operator+(rcSTR_String lhs, char rhs)
-{
- return STR_String(lhs.ReadPtr(), lhs.Length(), &rhs, 1);
-}
-inline STR_String operator+(char lhs, rcSTR_String rhs)
-{
- return STR_String(&lhs, 1, rhs.ReadPtr(), rhs.Length());
-}
-inline STR_String operator+(rcSTR_String lhs, const char *rhs)
-{
- return STR_String(lhs.ReadPtr(), lhs.Length(), rhs, strlen(rhs));
-}
-inline STR_String operator+(const char *lhs, rcSTR_String rhs)
-{
- return STR_String(lhs, strlen(lhs), rhs.ReadPtr(), rhs.Length());
-}
-
-#endif //__STR_STRING_H__
diff --git a/intern/string/intern/STR_String.cpp b/intern/string/intern/STR_String.cpp
deleted file mode 100644
index 306e786969b..00000000000
--- a/intern/string/intern/STR_String.cpp
+++ /dev/null
@@ -1,637 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- */
-
-/** \file
- * \ingroup string
- *
- * Copyright (C) 2001 NaN Technologies B.V.
- * This file was formerly known as: GEN_StdString.cpp.
- */
-
-#include "STR_String.h"
-#include <ctype.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/*-------------------------------------------------------------------------------------------------
- Construction / destruction
--------------------------------------------------------------------------------------------------*/
-
-#define STR_STRING_SIZE_DEFAULT_WORD 32 /* default size for a new word */
-#define STR_STRING_SIZE_DEFAULT_CHAR 9 /* default size for a new char */
-
-//
-// Construct an empty string
-//
-STR_String::STR_String()
- : m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_len(0), m_max(STR_STRING_SIZE_DEFAULT_WORD)
-{
- this->m_data[0] = 0;
-}
-
-//
-// Construct a string of one character
-//
-STR_String::STR_String(char c)
- : m_data(new char[STR_STRING_SIZE_DEFAULT_CHAR]), m_len(1), m_max(STR_STRING_SIZE_DEFAULT_CHAR)
-{
- this->m_data[0] = c;
- this->m_data[1] = 0;
-}
-
-//
-// Construct a string of multiple repeating characters
-//
-STR_String::STR_String(char c, int len) : m_data(new char[len + 8]), m_len(len), m_max(len + 8)
-{
- assertd(this->m_data != NULL);
- memset(this->m_data, c, len);
- this->m_data[len] = 0;
-}
-
-//
-// Construct a string from a pointer-to-ASCIIZ-string
-//
-// MAART: Changed to test for null strings
-STR_String::STR_String(const char *str)
-{
- if (str) {
- this->m_len = ::strlen(str);
- this->m_max = this->m_len + 8;
- this->m_data = new char[this->m_max];
- assertd(this->m_data != NULL);
- ::memcpy(this->m_data, str, this->m_len);
- this->m_data[this->m_len] = 0;
- }
- else {
- this->m_data = NULL;
- this->m_len = 0;
- this->m_max = 8;
- }
-}
-
-//
-// Construct a string from a pointer-to-ASCII-string and a length
-//
-STR_String::STR_String(const char *str, int len)
- : m_data(new char[len + 8]), m_len(len), m_max(len + 8)
-{
- assertd(this->m_data != NULL);
- memcpy(this->m_data, str, len);
- this->m_data[len] = 0;
-}
-
-//
-// Construct a string from another string
-//
-STR_String::STR_String(rcSTR_String str)
- : m_data(new char[str.Length() + 8]), m_len(str.Length()), m_max(str.Length() + 8)
-{
- assertd(this->m_data != NULL);
- assertd(str.this->m_data != NULL);
- memcpy(this->m_data, str.ReadPtr(), str.Length());
- this->m_data[str.Length()] = 0;
-}
-
-//
-// Construct a string from the first number of characters in another string
-//
-STR_String::STR_String(rcSTR_String str, int len)
- : m_data(new char[len + 8]), m_len(len), m_max(len + 8)
-{
- assertd(this->m_data != NULL);
- assertd(str.this->m_data != NULL);
- memcpy(this->m_data, str.ReadPtr(), str.Length());
- this->m_data[str.Length()] = 0;
-}
-
-//
-// Create a string by concatenating two sources
-//
-STR_String::STR_String(const char *src1, int len1, const char *src2, int len2)
- : m_data(new char[len1 + len2 + 8]), m_len(len1 + len2), m_max(len1 + len2 + 8)
-{
- assertd(this->m_data != NULL);
- memcpy(this->m_data, src1, len1);
- memcpy(this->m_data + len1, src2, len2);
- this->m_data[len1 + len2] = 0;
-}
-
-//
-// Create a string with an integer value
-//
-STR_String::STR_String(int val)
- : m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_max(STR_STRING_SIZE_DEFAULT_WORD)
-{
- assertd(this->m_data != NULL);
- this->m_len = sprintf(this->m_data, "%d", val);
-}
-
-//
-// Create a string with a dword value
-//
-STR_String::STR_String(dword val)
- : m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_max(STR_STRING_SIZE_DEFAULT_WORD)
-{
- assertd(this->m_data != NULL);
- this->m_len = sprintf(this->m_data, "%lu", val);
-}
-
-//
-// Create a string with a floating point value
-//
-STR_String::STR_String(float val)
- : m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_max(STR_STRING_SIZE_DEFAULT_WORD)
-{
- assertd(this->m_data != NULL);
- this->m_len = sprintf(this->m_data, "%g", val);
-}
-
-//
-// Create a string with a double value
-//
-STR_String::STR_String(double val)
- : m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_max(STR_STRING_SIZE_DEFAULT_WORD)
-{
- assertd(this->m_data != NULL);
- this->m_len = sprintf(this->m_data, "%g", val);
-}
-
-/*-------------------------------------------------------------------------------------------------
- Buffer management
--------------------------------------------------------------------------------------------------*/
-
-//
-// Make sure that the allocated buffer is at least <len> in size
-//
-void STR_String::AllocBuffer(int len, bool keep_contents)
-{
- // Check if we have enough space
- if (len + 1 <= this->m_max)
- return;
-
- // Reallocate string
- char *new_data = new char[len + 8];
- if (keep_contents) {
- memcpy(new_data, this->m_data, this->m_len);
- }
- delete[] this->m_data;
-
- // Accept new data
- this->m_max = len + 8;
- this->m_data = new_data;
- assertd(this->m_data != NULL);
-}
-
-/*-------------------------------------------------------------------------------------------------
- Basic string operations
--------------------------------------------------------------------------------------------------*/
-
-//
-// Format string (as does sprintf)
-//
-STR_String &STR_String::Format(const char *fmt, ...)
-{
- AllocBuffer(2048, false);
-
- assertd(this->m_data != NULL);
- // Expand arguments and format to string
- va_list args;
- va_start(args, fmt);
- this->m_len = vsprintf(this->m_data, fmt, args);
- assertd(this->m_len <= 2048);
- va_end(args);
-
- return *this;
-}
-
-//
-// Format string (as does sprintf)
-//
-STR_String &STR_String::FormatAdd(const char *fmt, ...)
-{
- AllocBuffer(2048, false);
-
- assertd(this->m_data != NULL);
- // Expand arguments and format to string
- va_list args;
- va_start(args, fmt);
- this->m_len += vsprintf(this->m_data + this->m_len, fmt, args);
- assertd(this->m_len <= 2048);
- va_end(args);
-
- return *this;
-}
-
-/*-------------------------------------------------------------------------------------------------
- Properties
--------------------------------------------------------------------------------------------------*/
-
-//
-// Check if string is entirely in UPPERCase
-//
-bool STR_String::IsUpper() const
-{
- for (int i = 0; i < this->m_len; i++)
- if (isLower(this->m_data[i]))
- return false;
-
- return true;
-}
-
-//
-// Check if string is entirely in lowerCase
-//
-bool STR_String::IsLower() const
-{
- for (int i = 0; i < this->m_len; i++)
- if (isUpper(this->m_data[i]))
- return false;
-
- return true;
-}
-
-/*-------------------------------------------------------------------------------------------------
- Search/Replace
--------------------------------------------------------------------------------------------------*/
-
-//
-// Find the first orccurence of <c> in the string
-//
-int STR_String::Find(char c, int pos) const
-{
- assertd(pos >= 0);
- assertd(this->m_len == 0 || pos < this->m_len);
- assertd(this->m_data != NULL);
- char *find_pos = strchr(this->m_data + pos, c);
- return (find_pos) ? (find_pos - this->m_data) : -1;
-}
-
-//
-// Find the first occurrence of <str> in the string
-//
-int STR_String::Find(const char *str, int pos) const
-{
- assertd(pos >= 0);
- assertd(this->m_len == 0 || pos < this->m_len);
- assertd(this->m_data != NULL);
- char *find_pos = strstr(this->m_data + pos, str);
- return (find_pos) ? (find_pos - this->m_data) : -1;
-}
-
-//
-// Find the first occurrence of <str> in the string
-//
-int STR_String::Find(rcSTR_String str, int pos) const
-{
- assertd(pos >= 0);
- assertd(this->m_len == 0 || pos < this->m_len);
- assertd(this->m_data != NULL);
- char *find_pos = strstr(this->m_data + pos, str.ReadPtr());
- return (find_pos) ? (find_pos - this->m_data) : -1;
-}
-
-//
-// Find the last occurrence of <c> in the string
-//
-int STR_String::RFind(char c) const
-{
- assertd(this->m_data != NULL);
- char *pos = strrchr(this->m_data, c);
- return (pos) ? (pos - this->m_data) : -1;
-}
-
-//
-// Find the first occurrence of any character in character set <set> in the string
-//
-int STR_String::FindOneOf(const char *set, int pos) const
-{
- assertd(pos >= 0);
- assertd(this->m_len == 0 || pos < this->m_len);
- assertd(this->m_data != NULL);
- char *find_pos = strpbrk(this->m_data + pos, set);
- return (find_pos) ? (find_pos - this->m_data) : -1;
-}
-
-//
-// Replace a character in this string with another string
-//
-void STR_String::Replace(int pos, rcSTR_String str)
-{
- // bounds(pos, 0, Length()-1);
-
- if (str.Length() < 1) {
- // Remove one character from the string
- memcpy(this->m_data + pos, this->m_data + pos + 1, this->m_len - pos);
- }
- else {
- // Insert zero or more characters into the string
- AllocBuffer(this->m_len + str.Length() - 1, true);
- if (str.Length() != 1)
- memcpy(this->m_data + pos + str.Length(), this->m_data + pos + 1, Length() - pos);
- memcpy(this->m_data + pos, str.ReadPtr(), str.Length());
- }
-
- this->m_len += str.Length() - 1;
-}
-
-//
-// Replace a substring of this string with another string
-//
-void STR_String::Replace(int pos, int num, rcSTR_String str)
-{
- // bounds(pos, 0, Length()-1);
- // bounds(pos+num, 0, Length());
- assertd(num >= 1);
-
- if (str.Length() < num) {
- // Remove some data from the string by replacement
- memcpy(
- this->m_data + pos + str.Length(), this->m_data + pos + num, this->m_len - pos - num + 1);
- memcpy(this->m_data + pos, str.ReadPtr(), str.Length());
- }
- else {
- // Insert zero or more characters into the string
- AllocBuffer(this->m_len + str.Length() - num, true);
- if (str.Length() != num)
- memcpy(
- this->m_data + pos + str.Length(), this->m_data + pos + num, Length() - pos - num + 1);
- memcpy(this->m_data + pos, str.ReadPtr(), str.Length());
- }
-
- this->m_len += str.Length() - num;
-}
-
-/*-------------------------------------------------------------------------------------------------
- Comparison
--------------------------------------------------------------------------------------------------*/
-
-//
-// Compare two strings and return the result,
-// <0 if *this<rhs, >0 if *this>rhs or 0 if *this==rhs
-//
-int STR_String::Compare(rcSTR_String rhs) const
-{
- return strcmp(this->ReadPtr(), rhs.ReadPtr());
-}
-
-//
-// Compare two strings without respecting case and return the result,
-// <0 if *this<rhs, >0 if *this>rhs or 0 if *this==rhs
-//
-int STR_String::CompareNoCase(rcSTR_String rhs) const
-{
-#ifdef WIN32
- return stricmp(this->ReadPtr(), rhs.ReadPtr());
-#else
- return strcasecmp(this->ReadPtr(), rhs.ReadPtr());
-#endif
-}
-
-/*-------------------------------------------------------------------------------------------------
- Formatting
--------------------------------------------------------------------------------------------------*/
-
-//
-// Capitalize string, "heLLo" -> "HELLO"
-//
-STR_String &STR_String::Upper()
-{
- assertd(this->m_data != NULL);
-#ifdef WIN32
- _strupr(this->m_data);
-#else
- for (int i = 0; i < this->m_len; i++)
- this->m_data[i] = (this->m_data[i] >= 'a' && this->m_data[i] <= 'z') ?
- this->m_data[i] + 'A' - 'a' :
- this->m_data[i];
-#endif
- return *this;
-}
-
-//
-// Lower string, "heLLo" -> "hello"
-//
-STR_String &STR_String::Lower()
-{
- assertd(this->m_data != NULL);
-#ifdef WIN32
- _strlwr(this->m_data);
-#else
- for (int i = 0; i < this->m_len; i++)
- this->m_data[i] = (this->m_data[i] >= 'A' && this->m_data[i] <= 'Z') ?
- this->m_data[i] + 'a' - 'A' :
- this->m_data[i];
-#endif
- return *this;
-}
-
-//
-// Capitalize string, "heLLo" -> "Hello"
-//
-STR_String &STR_String::Capitalize()
-{
- assertd(this->m_data != NULL);
-#ifdef WIN32
- if (this->m_len > 0)
- this->m_data[0] = toupper(this->m_data[0]);
- if (this->m_len > 1)
- _strlwr(this->m_data + 1);
-#else
- if (this->m_len > 0)
- this->m_data[0] = (this->m_data[0] >= 'a' && this->m_data[0] <= 'z') ?
- this->m_data[0] + 'A' - 'a' :
- this->m_data[0];
- for (int i = 1; i < this->m_len; i++)
- this->m_data[i] = (this->m_data[i] >= 'A' && this->m_data[i] <= 'Z') ?
- this->m_data[i] + 'a' - 'A' :
- this->m_data[i];
-#endif
- return *this;
-}
-
-//
-// Trim whitespace from the left side of the string
-//
-STR_String &STR_String::TrimLeft()
-{
- int skip;
- assertd(this->m_data != NULL);
- for (skip = 0; isSpace(this->m_data[skip]); skip++, this->m_len--) {
- /* pass */
- }
- memmove(this->m_data, this->m_data + skip, this->m_len + 1);
- return *this;
-}
-
-//
-// Trim whitespaces from the right side of the string
-//
-STR_String &STR_String::TrimRight()
-{
- assertd(this->m_data != NULL);
- while (this->m_len && isSpace(this->m_data[this->m_len - 1]))
- this->m_len--;
- this->m_data[this->m_len] = 0;
- return *this;
-}
-
-//
-// Trim spaces from both sides of the character set
-//
-STR_String &STR_String::Trim()
-{
- TrimRight();
- TrimLeft();
- return *this;
-}
-
-//
-// Trim characters from the character set <set> from the left side of the string
-//
-STR_String &STR_String::TrimLeft(char *set)
-{
- int skip;
- assertd(this->m_data != NULL);
- for (skip = 0; this->m_len && strchr(set, this->m_data[skip]); skip++, this->m_len--) {
- /* pass */
- }
- memmove(this->m_data, this->m_data + skip, this->m_len + 1);
- return *this;
-}
-
-//
-// Trim characters from the character set <set> from the right side of the string
-//
-STR_String &STR_String::TrimRight(char *set)
-{
- assertd(this->m_data != NULL);
- while (this->m_len && strchr(set, this->m_data[this->m_len - 1]))
- this->m_len--;
- this->m_data[this->m_len] = 0;
- return *this;
-}
-
-//
-// Trim characters from the character set <set> from both sides of the character set
-//
-STR_String &STR_String::Trim(char *set)
-{
- TrimRight(set);
- TrimLeft(set);
- return *this;
-}
-
-//
-// Trim quotes from both sides of the string
-//
-STR_String &STR_String::TrimQuotes()
-{
- // Trim quotes if they are on both sides of the string
- assertd(this->m_data != NULL);
- if ((this->m_len >= 2) && (this->m_data[0] == '\"') && (this->m_data[this->m_len - 1] == '\"')) {
- memmove(this->m_data, this->m_data + 1, this->m_len - 2 + 1);
- this->m_len -= 2;
- }
- return *this;
-}
-
-/*-------------------------------------------------------------------------------------------------
- Assignment/Concatenation
--------------------------------------------------------------------------------------------------*/
-
-//
-// Set the string's conents to a copy of <src> with length <len>
-//
-rcSTR_String STR_String::Copy(const char *src, int len)
-{
- assertd(len >= 0);
- assertd(src);
- assertd(this->m_data != NULL);
-
- AllocBuffer(len, false);
- this->m_len = len;
- memcpy(this->m_data, src, len);
- this->m_data[this->m_len] = 0;
-
- return *this;
-}
-
-//
-// Concate a number of bytes to the current string
-//
-rcSTR_String STR_String::Concat(const char *data, int len)
-{
- assertd(this->m_len >= 0);
- assertd(len >= 0);
- assertd(data);
- assertd(this->m_data != NULL);
-
- AllocBuffer(this->m_len + len, true);
- memcpy(this->m_data + this->m_len, data, len);
- this->m_len += len;
- this->m_data[this->m_len] = 0;
-
- return *this;
-}
-
-std::vector<STR_String> STR_String::Explode(char c) const
-{
- STR_String lcv = *this;
- std::vector<STR_String> uc;
-
- while (lcv.Length()) {
- int pos = lcv.Find(c);
- if (pos < 0) {
- uc.push_back(lcv);
- lcv.Clear();
- }
- else {
- uc.push_back(lcv.Left(pos));
- lcv = lcv.Mid(pos + 1);
- }
- }
-
- // uc. -= STR_String("");
-
- return uc;
-}
-
-#if 0
-
-int STR_String::Serialize(pCStream stream)
-{
- if (stream->GetAccess() == CStream::Access_Read) {
- int ln;
- stream->Read(&ln, sizeof(ln));
- AllocBuffer(ln, false);
- stream->Read(this->m_data, ln);
- this->m_data[ln] = '\0';
- this->m_len = ln;
- }
- else {
- stream->Write(&this->m_len, sizeof(this->m_len));
- stream->Write(this->m_data, this->m_len);
- }
-
- return this->m_len + sizeof(this->m_len);
-}
-#endif