Merge branch 'master' into refactor-mesh-position-generic

This commit is contained in:
Hans Goudey 2023-01-09 11:44:08 -05:00
commit f4739db682
347 changed files with 7003 additions and 3600 deletions

View File

@ -22,6 +22,14 @@ elseif(UNIX AND NOT APPLE)
)
endif()
# Boolean crashes with Arm assembly, see T103423.
if(BLENDER_PLATFORM_ARM)
set(GMP_OPTIONS
${GMP_OPTIONS}
--disable-assembly
)
endif()
ExternalProject_Add(external_gmp
URL file://${PACKAGE_DIR}/${GMP_FILE}
DOWNLOAD_DIR ${DOWNLOAD_DIR}

View File

@ -83,7 +83,7 @@ enum_use_layer_samples = (
enum_sampling_pattern = (
('SOBOL_BURLEY', "Sobol-Burley", "Use on-the-fly computed Owen-scrambled Sobol for random sampling", 0),
('TABULATED_SOBOL', "Tabulated Sobol", "Use precomputed tables of Owen-scrambled Sobol for random sampling", 1),
('TABULATED_SOBOL', "Tabulated Sobol", "Use pre-computed tables of Owen-scrambled Sobol for random sampling", 1),
)
enum_emission_sampling = (
@ -905,7 +905,8 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
use_fast_gi: BoolProperty(
name="Fast GI Approximation",
description="Approximate diffuse indirect light with background tinted ambient occlusion. This provides fast alternative to full global illumination, for interactive viewport rendering or final renders with reduced quality",
description="Approximate diffuse indirect light with background tinted ambient occlusion. "
"This provides fast alternative to full global illumination, for interactive viewport rendering or final renders with reduced quality",
default=False,
)
@ -1539,13 +1540,16 @@ class CyclesPreferences(bpy.types.AddonPreferences):
use_metalrt: BoolProperty(
name="MetalRT (Experimental)",
description="MetalRT for ray tracing uses less memory for scenes which use curves extensively, and can give better performance in specific cases. However this support is experimental and some scenes may render incorrectly",
description="MetalRT for ray tracing uses less memory for scenes which use curves extensively, and can give better "
"performance in specific cases. However this support is experimental and some scenes may render incorrectly",
default=False,
)
kernel_optimization_level: EnumProperty(
name="Kernel Optimization",
description="Kernels can be optimized based on scene content. Optimized kernels are requested at the start of a render. If optimized kernels are not available, rendering will proceed using generic kernels until the optimized set is available in the cache. This can result in additional CPU usage for a brief time (tens of seconds).",
description="Kernels can be optimized based on scene content. Optimized kernels are requested at the start of a render. "
"If optimized kernels are not available, rendering will proceed using generic kernels until the optimized set "
"is available in the cache. This can result in additional CPU usage for a brief time (tens of seconds)",
default='FULL',
items=(
('OFF', "Off", "Disable kernel optimization. Slowest rendering, no extra background CPU usage"),

View File

@ -377,7 +377,8 @@ bool MetalDevice::load_kernels(const uint _kernel_features)
/* Only request generic kernels if they aren't cached in memory. */
if (make_source_and_check_if_compile_needed(PSO_GENERIC)) {
/* If needed, load them asynchronously in order to responsively message progress to the user. */
/* If needed, load them asynchronously in order to responsively message progress to the user.
*/
int this_device_id = this->device_id;
auto compile_kernels_fn = ^() {
compile_and_load(this_device_id, PSO_GENERIC);

View File

@ -502,8 +502,15 @@ ccl_device_forceinline void integrate_surface_ao(KernelGlobals kg,
rng_state,
ccl_global float *ccl_restrict render_buffer)
{
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
if (!(kernel_data.kernel_features & KERNEL_FEATURE_AO_ADDITIVE) &&
!(INTEGRATOR_STATE(state, path, flag) & PATH_RAY_CAMERA)) {
!(path_flag & PATH_RAY_CAMERA)) {
return;
}
/* Skip AO for paths that were split off for shadow catchers to avoid double-counting. */
if (path_flag & PATH_RAY_SHADOW_CATCHER_PASS) {
return;
}

View File

@ -979,8 +979,10 @@ ccl_device_forceinline bool integrate_volume_phase_scatter(
INTEGRATOR_STATE_WRITE(state, path, throughput) = throughput_phase;
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_spectrum();
INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_spectrum();
if (INTEGRATOR_STATE(state, path, bounce) == 0) {
INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_spectrum();
INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_spectrum();
}
}
/* Update path state */

View File

@ -122,6 +122,7 @@ shader node_image_texture(int use_mapping = 0,
vector Nob = transform("world", "object", N);
/* project from direction vector to barycentric coordinates in triangles */
vector signed_Nob = Nob;
Nob = vector(fabs(Nob[0]), fabs(Nob[1]), fabs(Nob[2]));
Nob /= (Nob[0] + Nob[1] + Nob[2]);
@ -184,9 +185,10 @@ shader node_image_texture(int use_mapping = 0,
float tmp_alpha;
if (weight[0] > 0.0) {
point UV = point((signed_Nob[0] < 0.0) ? 1.0 - p[1] : p[1], p[2], 0.0);
Color += weight[0] * image_texture_lookup(filename,
p[1],
p[2],
UV[0],
UV[1],
tmp_alpha,
compress_as_srgb,
ignore_alpha,
@ -198,9 +200,10 @@ shader node_image_texture(int use_mapping = 0,
Alpha += weight[0] * tmp_alpha;
}
if (weight[1] > 0.0) {
point UV = point((signed_Nob[1] > 0.0) ? 1.0 - p[0] : p[0], p[2], 0.0);
Color += weight[1] * image_texture_lookup(filename,
p[0],
p[2],
UV[0],
UV[1],
tmp_alpha,
compress_as_srgb,
ignore_alpha,
@ -212,9 +215,10 @@ shader node_image_texture(int use_mapping = 0,
Alpha += weight[1] * tmp_alpha;
}
if (weight[2] > 0.0) {
point UV = point((signed_Nob[2] > 0.0) ? 1.0 - p[1] : p[1], p[0], 0.0);
Color += weight[2] * image_texture_lookup(filename,
p[1],
p[0],
UV[0],
UV[1],
tmp_alpha,
compress_as_srgb,
ignore_alpha,

View File

@ -32,7 +32,7 @@ static float shutter_curve_eval(float x, array<float> &shutter_curve)
return 1.0f;
}
x *= shutter_curve.size();
x = saturatef(x) * shutter_curve.size() - 1;
int index = (int)x;
float frac = x - index;
if (index < shutter_curve.size() - 1) {

View File

@ -289,19 +289,24 @@ RenderWork Session::run_update_for_next_iteration()
RenderWork render_work;
thread_scoped_lock scene_lock(scene->mutex);
thread_scoped_lock reset_lock(delayed_reset_.mutex);
bool have_tiles = true;
bool switched_to_new_tile = false;
bool did_reset = false;
const bool did_reset = delayed_reset_.do_reset;
if (delayed_reset_.do_reset) {
thread_scoped_lock buffers_lock(buffers_mutex_);
do_delayed_reset();
/* Perform delayed reset if requested. */
{
thread_scoped_lock reset_lock(delayed_reset_.mutex);
if (delayed_reset_.do_reset) {
did_reset = true;
/* After reset make sure the tile manager is at the first big tile. */
have_tiles = tile_manager_.next();
switched_to_new_tile = true;
thread_scoped_lock buffers_lock(buffers_mutex_);
do_delayed_reset();
/* After reset make sure the tile manager is at the first big tile. */
have_tiles = tile_manager_.next();
switched_to_new_tile = true;
}
}
/* Update number of samples in the integrator.

View File

@ -16,6 +16,7 @@ void util_cdf_invert(const int resolution,
const bool make_symmetric,
vector<float> &inv_cdf)
{
assert(cdf[0] == 0.0f && cdf[resolution] == 1.0f);
const float inv_resolution = 1.0f / (float)resolution;
const float range = to - from;
inv_cdf.resize(resolution);
@ -39,8 +40,8 @@ void util_cdf_invert(const int resolution,
}
else {
for (int i = 0; i < resolution; i++) {
float x = from + range * (float)i * inv_resolution;
int index = upper_bound(cdf.begin(), cdf.end(), x) - cdf.begin();
float x = (i + 0.5f) * inv_resolution;
int index = upper_bound(cdf.begin(), cdf.end(), x) - cdf.begin() - 1;
float t;
if (index < cdf.size() - 1) {
t = (x - cdf[index]) / (cdf[index + 1] - cdf[index]);
@ -49,7 +50,7 @@ void util_cdf_invert(const int resolution,
t = 0.0f;
index = resolution;
}
inv_cdf[i] = (index + t) * inv_resolution;
inv_cdf[i] = from + range * (index + t) * inv_resolution;
}
}
}

View File

@ -26,9 +26,11 @@ void util_cdf_evaluate(
cdf[i + 1] = cdf[i] + fabsf(y);
}
/* Normalize the CDF. */
float fac = (cdf[resolution] == 0.0f) ? 0.0f : 1.0f / cdf[resolution];
for (int i = 0; i <= resolution; i++) {
cdf[i] /= cdf[resolution];
cdf[i] *= fac;
}
cdf[resolution] = 1.0f;
}
/* Invert pre-calculated CDF function. */

View File

@ -412,6 +412,7 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
"selected",
"selected and lock unselected",
"selected and unlock unselected",
"screen",
"the lazy dog",
"this legacy pose library to pose assets",
"to the top level of the tree",

View File

@ -542,6 +542,7 @@ class SpellChecker:
"voronoi",
"voxel", "voxels",
"vsync",
"vulkan",
"wireframe",
"zmask",
"ztransp",

View File

@ -1342,7 +1342,7 @@ url_manual_mapping = (
("bpy.types.armature.layers_protected*", "animation/armatures/properties/skeleton.html#bpy-types-armature-layers-protected"),
("bpy.types.assetmetadata.description*", "editors/asset_browser.html#bpy-types-assetmetadata-description"),
("bpy.types.bakesettings.normal_space*", "render/cycles/baking.html#bpy-types-bakesettings-normal-space"),
("bpy.types.brush.crease_pinch_factor*", "sculpt_paint/sculpting/tools/snake_hook.html#bpy-types-brush-crease-pinch-factor"),
("bpy.types.brush.crease_pinch_factor*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-crease-pinch-factor"),
("bpy.types.brush.elastic_deform_type*", "sculpt_paint/sculpting/tools/elastic_deform.html#bpy-types-brush-elastic-deform-type"),
("bpy.types.brush.texture_sample_bias*", "sculpt_paint/brush/texture.html#bpy-types-brush-texture-sample-bias"),
("bpy.types.brush.use_cloth_collision*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-use-cloth-collision"),
@ -1468,6 +1468,7 @@ url_manual_mapping = (
("bpy.types.bakesettings.cage_object*", "render/cycles/baking.html#bpy-types-bakesettings-cage-object"),
("bpy.types.bakesettings.margin_type*", "render/cycles/baking.html#bpy-types-bakesettings-margin-type"),
("bpy.types.bone.use_relative_parent*", "animation/armatures/bones/properties/relations.html#bpy-types-bone-use-relative-parent"),
("bpy.types.brush.area_radius_factor*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-area-radius-factor"),
("bpy.types.brush.auto_smooth_factor*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-auto-smooth-factor"),
("bpy.types.brush.smooth_deform_type*", "sculpt_paint/sculpting/tools/smooth.html#bpy-types-brush-smooth-deform-type"),
("bpy.types.brush.use_connected_only*", "sculpt_paint/sculpting/tools/pose.html#bpy-types-brush-use-connected-only"),
@ -1781,6 +1782,7 @@ url_manual_mapping = (
("bpy.types.functionnodefloattoint*", "modeling/geometry_nodes/utilities/float_to_integer.html#bpy-types-functionnodefloattoint"),
("bpy.types.functionnodeinputcolor*", "modeling/geometry_nodes/input/color.html#bpy-types-functionnodeinputcolor"),
("bpy.types.geometrynodeconvexhull*", "modeling/geometry_nodes/geometry/convex_hull.html#bpy-types-geometrynodeconvexhull"),
("bpy.types.geometrynodeimageinput*", "modeling/geometry_nodes/input/image_input.html#bpy-types-geometrynodeimageinput"),
("bpy.types.geometrynodeinputindex*", "modeling/geometry_nodes/input/input_index.html#bpy-types-geometrynodeinputindex"),
("bpy.types.geometrynodeisviewport*", "modeling/geometry_nodes/input/is_viewport.html#bpy-types-geometrynodeisviewport"),
("bpy.types.geometrynodemeshcircle*", "modeling/geometry_nodes/mesh_primitives/mesh_circle.html#bpy-types-geometrynodemeshcircle"),
@ -2172,10 +2174,11 @@ url_manual_mapping = (
("bpy.types.bakesettings.margin*", "render/cycles/baking.html#bpy-types-bakesettings-margin"),
("bpy.types.bakesettings.target*", "render/cycles/baking.html#bpy-types-bakesettings-target"),
("bpy.types.brush.cloth_damping*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-damping"),
("bpy.types.brush.deform_target*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-deform-target"),
("bpy.types.brush.falloff_shape*", "sculpt_paint/brush/falloff.html#bpy-types-brush-falloff-shape"),
("bpy.types.brush.icon_filepath*", "sculpt_paint/brush/brush.html#bpy-types-brush-icon-filepath"),
("bpy.types.brush.stroke_method*", "sculpt_paint/brush/stroke.html#bpy-types-brush-stroke-method"),
("bpy.types.brush.tip_roundness*", "sculpt_paint/sculpting/tools/clay_strips.html#bpy-types-brush-tip-roundness"),
("bpy.types.brush.tip_roundness*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-tip-roundness"),
("bpy.types.camera.display_size*", "render/cameras.html#bpy-types-camera-display-size"),
("bpy.types.camera.sensor_width*", "render/cameras.html#bpy-types-camera-sensor-width"),
("bpy.types.compositornodedblur*", "compositing/types/filter/directional_blur.html#bpy-types-compositornodedblur"),
@ -2705,6 +2708,7 @@ url_manual_mapping = (
("bpy.types.armature.rigify*", "addons/rigging/rigify/basics.html#bpy-types-armature-rigify"),
("bpy.types.bone.use_deform*", "animation/armatures/bones/properties/deform.html#bpy-types-bone-use-deform"),
("bpy.types.booleanmodifier*", "modeling/modifiers/generate/booleans.html#bpy-types-booleanmodifier"),
("bpy.types.brush.direction*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-direction"),
("bpy.types.brush.mask_tool*", "sculpt_paint/sculpting/tools/mask.html#bpy-types-brush-mask-tool"),
("bpy.types.constraint.mute*", "animation/constraints/interface/header.html#bpy-types-constraint-mute"),
("bpy.types.constraint.name*", "animation/constraints/interface/header.html#bpy-types-constraint-name"),
@ -2798,6 +2802,7 @@ url_manual_mapping = (
("bpy.ops.wm.save_mainfile*", "files/blend/open_save.html#bpy-ops-wm-save-mainfile"),
("bpy.types.bone.show_wire*", "animation/armatures/bones/properties/display.html#bpy-types-bone-show-wire"),
("bpy.types.brush.hardness*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-hardness"),
("bpy.types.brush.strength*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-strength"),
("bpy.types.curves.surface*", "modeling/curves/primitives.html#bpy-types-curves-surface"),
("bpy.types.curvesmodifier*", "editors/video_sequencer/sequencer/sidebar/modifiers.html#bpy-types-curvesmodifier"),
("bpy.types.ffmpegsettings*", "render/output/properties/output.html#bpy-types-ffmpegsettings"),
@ -3111,6 +3116,7 @@ url_manual_mapping = (
("bpy.types.bonegroups*", "animation/armatures/properties/bone_groups.html#bpy-types-bonegroups"),
("bpy.types.bpy_struct*", "files/data_blocks.html#bpy-types-bpy-struct"),
("bpy.types.brush.rate*", "sculpt_paint/brush/stroke.html#bpy-types-brush-rate"),
("bpy.types.brush.size*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-size"),
("bpy.types.collection*", "scene_layout/collections/collections.html#bpy-types-collection"),
("bpy.types.compositor*", "compositing/index.html#bpy-types-compositor"),
("bpy.types.constraint*", "animation/constraints/index.html#bpy-types-constraint"),

View File

@ -605,7 +605,7 @@ class USERPREF_PT_system_cycles_devices(SystemPanel, CenterAlignMixIn, Panel):
class USERPREF_PT_system_gpu_backend(SystemPanel, CenterAlignMixIn, Panel):
bl_label = "GPU Backend"
bl_label = "GPU Back end"
@classmethod
def poll(cls, _context):
@ -622,7 +622,7 @@ class USERPREF_PT_system_gpu_backend(SystemPanel, CenterAlignMixIn, Panel):
col.prop(system, "gpu_backend")
if system.gpu_backend != gpu.platform.backend_type_get():
layout.label(text="Requires a restart of Blender to take effect.", icon='INFO')
layout.label(text="Requires a restart of Blender to take effect", icon='INFO')
class USERPREF_PT_system_os_settings(SystemPanel, CenterAlignMixIn, Panel):

View File

@ -6224,7 +6224,7 @@ class VIEW3D_PT_shading_compositor(Panel):
row.active = not is_macos
row.prop(shading, "use_compositor", expand=True)
if is_macos and shading.use_compositor != "DISABLED":
self.layout.label(text="Compositor not supported on MacOS.", icon='ERROR')
self.layout.label(text="Compositor not supported on MacOS", icon='ERROR')
class VIEW3D_PT_gizmo_display(Panel):

View File

@ -47,6 +47,8 @@ class AnonymousAttributeID {
return name_;
}
virtual std::string user_name() const;
void user_add() const
{
users_.fetch_add(1);

View File

@ -8,7 +8,7 @@
#include "BLI_function_ref.hh"
#include "BLI_generic_span.hh"
#include "BLI_generic_virtual_array.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_set.hh"
#include "BKE_anonymous_attribute_id.hh"
@ -17,7 +17,9 @@
struct Mesh;
struct PointCloud;
namespace blender::fn {
namespace multi_function {
class MultiFunction;
}
class GField;
} // namespace blender::fn
@ -174,7 +176,7 @@ struct AttributeValidator {
/**
* Single input, single output function that corrects attribute values if necessary.
*/
const fn::MultiFunction *function;
const fn::multi_function::MultiFunction *function;
operator bool() const
{

View File

@ -7,7 +7,7 @@
#pragma once
#include "BLI_float3x3.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
struct Depsgraph;

View File

@ -17,7 +17,7 @@
#include "BLI_float4x4.hh"
#include "BLI_generic_virtual_array.hh"
#include "BLI_index_mask.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_shared_cache.hh"
#include "BLI_span.hh"
#include "BLI_task.hh"

View File

@ -268,7 +268,7 @@ class AnonymousAttributeFieldInput : public GeometryFieldInput {
AnonymousAttributeFieldInput(AutoAnonymousAttributeID anonymous_id,
const CPPType &type,
std::string producer_name)
: GeometryFieldInput(type, anonymous_id->name()),
: GeometryFieldInput(type, anonymous_id->user_name()),
anonymous_id_(std::move(anonymous_id)),
producer_name_(producer_name)
{

View File

@ -14,7 +14,7 @@
#include "BLI_function_ref.hh"
#include "BLI_hash.hh"
#include "BLI_map.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_set.hh"
#include "BLI_user_counter.hh"
#include "BLI_vector_set.hh"

View File

@ -9,7 +9,7 @@
#include "DNA_image_types.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
namespace blender::bke::image {

View File

@ -401,7 +401,7 @@ bool BKE_lib_override_library_status_check_reference(struct Main *bmain, struct
* Compare local and reference data-blocks and create new override operations as needed,
* or reset to reference values if overriding is not allowed.
*
* \param r_report_flags #eRNAOverrideMatchResult flags giving info about the result of this call.
* \param r_report_flags: #eRNAOverrideMatchResult flags giving info about the result of this call.
*
* \note Defining override operations is only mandatory before saving a `.blend` file on disk
* (not for undo!).
@ -417,7 +417,7 @@ void BKE_lib_override_library_operations_create(struct Main *bmain,
/**
* Check all overrides from given \a bmain and create/update overriding operations as needed.
*
* \param r_report_flags #eRNAOverrideMatchResult flags giving info about the result of this call.
* \param r_report_flags: #eRNAOverrideMatchResult flags giving info about the result of this call.
*/
void BKE_lib_override_library_main_operations_create(struct Main *bmain,
bool force_auto,
@ -427,7 +427,7 @@ void BKE_lib_override_library_main_operations_create(struct Main *bmain,
* Restore forbidden modified override properties to the values of their matching properties in the
* linked reference ID.
*
* \param r_report_flags #eRNAOverrideMatchResult flags giving info about the result of this call.
* \param r_report_flags: #eRNAOverrideMatchResult flags giving info about the result of this call.
*
* \note Typically used as part of BKE_lib_override_library_main_operations_create process, since
* modifying RNA properties from non-main threads is not safe.
@ -439,7 +439,7 @@ void BKE_lib_override_library_operations_restore(struct Main *bmain,
* Restore forbidden modified override properties to the values of their matching properties in the
* linked reference ID, for all liboverride IDs tagged as needing such process in given `bmain`.
*
* \param r_report_flags #eRNAOverrideMatchResult flags giving info about the result of this call.
* \param r_report_flags: #eRNAOverrideMatchResult flags giving info about the result of this call.
*
* \note Typically used as part of BKE_lib_override_library_main_operations_create process, since
* modifying RNA properties from non-main threads is not safe.

View File

@ -8,7 +8,7 @@
#include "BLI_function_ref.hh"
#include "BLI_generic_virtual_array.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "DNA_meshdata_types.h"

View File

@ -16,7 +16,7 @@
# include "BLI_array.hh"
# include "BLI_bit_vector.hh"
# include "BLI_bounds_types.hh"
# include "BLI_math_vec_types.hh"
# include "BLI_math_vector_types.hh"
# include "BLI_shared_cache.hh"
# include "BLI_span.hh"

View File

@ -107,9 +107,6 @@ class GeoNodeExecParams;
class NodeDeclarationBuilder;
class GatherLinkSearchOpParams;
} // namespace nodes
namespace fn {
class MFDataType;
} // namespace fn
namespace realtime_compositor {
class Context;
class NodeOperation;

View File

@ -4,7 +4,7 @@
#pragma once
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_rect.h"
#include "BLI_vector.hh"

View File

@ -11,7 +11,7 @@
# include <mutex>
# include "BLI_bounds_types.hh"
# include "BLI_math_vec_types.hh"
# include "BLI_math_vector_types.hh"
# include "BLI_shared_cache.hh"
#endif

View File

@ -8,19 +8,19 @@
namespace blender::bke {
struct ConversionFunctions {
const fn::MultiFunction *multi_function;
const mf::MultiFunction *multi_function;
void (*convert_single_to_initialized)(const void *src, void *dst);
void (*convert_single_to_uninitialized)(const void *src, void *dst);
};
class DataTypeConversions {
private:
Map<std::pair<fn::MFDataType, fn::MFDataType>, ConversionFunctions> conversions_;
Map<std::pair<mf::DataType, mf::DataType>, ConversionFunctions> conversions_;
public:
void add(fn::MFDataType from_type,
fn::MFDataType to_type,
const fn::MultiFunction &fn,
void add(mf::DataType from_type,
mf::DataType to_type,
const mf::MultiFunction &fn,
void (*convert_single_to_initialized)(const void *src, void *dst),
void (*convert_single_to_uninitialized)(const void *src, void *dst))
{
@ -28,19 +28,18 @@ class DataTypeConversions {
{&fn, convert_single_to_initialized, convert_single_to_uninitialized});
}
const ConversionFunctions *get_conversion_functions(fn::MFDataType from, fn::MFDataType to) const
const ConversionFunctions *get_conversion_functions(mf::DataType from, mf::DataType to) const
{
return conversions_.lookup_ptr({from, to});
}
const ConversionFunctions *get_conversion_functions(const CPPType &from, const CPPType &to) const
{
return this->get_conversion_functions(fn::MFDataType::ForSingle(from),
fn::MFDataType::ForSingle(to));
return this->get_conversion_functions(mf::DataType::ForSingle(from),
mf::DataType::ForSingle(to));
}
const fn::MultiFunction *get_conversion_multi_function(fn::MFDataType from,
fn::MFDataType to) const
const mf::MultiFunction *get_conversion_multi_function(mf::DataType from, mf::DataType to) const
{
const ConversionFunctions *functions = this->get_conversion_functions(from, to);
return functions ? functions->multi_function : nullptr;
@ -49,7 +48,7 @@ class DataTypeConversions {
bool is_convertible(const CPPType &from_type, const CPPType &to_type) const
{
return conversions_.contains(
{fn::MFDataType::ForSingle(from_type), fn::MFDataType::ForSingle(to_type)});
{mf::DataType::ForSingle(from_type), mf::DataType::ForSingle(to_type)});
}
void convert_to_uninitialized(const CPPType &from_type,

View File

@ -160,7 +160,7 @@ bool BKE_volume_save(const struct Volume *volume,
#ifdef __cplusplus
# include "BLI_float4x4.hh"
# include "BLI_math_vec_types.hh"
# include "BLI_math_vector_types.hh"
# include "BLI_string_ref.hh"
bool BKE_volume_min_max(const Volume *volume, blender::float3 &r_min, blender::float3 &r_max);

View File

@ -24,7 +24,7 @@
#include "BLI_blenlib.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_task.h"
#include "BLI_task.hh"
#include "BLI_utildefines.h"
@ -287,7 +287,7 @@ void DM_ensure_looptri_data(DerivedMesh *dm)
BLI_assert(dm->looptris.array_wip == nullptr);
SWAP(MLoopTri *, dm->looptris.array, dm->looptris.array_wip);
std::swap(dm->looptris.array, dm->looptris.array_wip);
if ((looptris_num > dm->looptris.num_alloc) || (looptris_num < dm->looptris.num_alloc * 2) ||
(totpoly == 0)) {

View File

@ -4,6 +4,11 @@
namespace blender::bke {
std::string AnonymousAttributeID::user_name() const
{
return this->name();
}
bool AnonymousAttributePropagationInfo::propagate(const AnonymousAttributeID &anonymous_id) const
{
if (this->propagate_all) {

View File

@ -615,7 +615,7 @@ static void get_domains_types(eAttrDomain domains[ATTR_DOMAIN_NUM])
}
/* Swap corner and face. */
SWAP(eAttrDomain, domains[ATTR_DOMAIN_FACE], domains[ATTR_DOMAIN_CORNER]);
std::swap(domains[ATTR_DOMAIN_FACE], domains[ATTR_DOMAIN_CORNER]);
}
int BKE_id_attribute_to_index(const ID *id,

View File

@ -16,7 +16,7 @@
#include "BLI_array_utils.hh"
#include "BLI_color.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
#include "FN_field.hh"

View File

@ -407,7 +407,7 @@ static void brush_undo_preserve(BlendLibReader *reader, ID *id_new, ID *id_old)
/* NOTE: We do not swap IDProperties, as dealing with potential ID pointers in those would be
* fairly delicate. */
SWAP(IDProperty *, id_new->properties, id_old->properties);
std::swap(id_new->properties, id_old->properties);
}
IDTypeInfo IDType_ID_BR = {

View File

@ -1119,6 +1119,9 @@ float BKE_camera_multiview_shift_x(const RenderData *rd,
if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW) {
return data->shiftx;
}
if (data->type == CAM_PANO) {
return data->shiftx;
}
/* SCE_VIEWS_SETUP_BASIC */
return camera_stereo3d_shift_x(camera, viewname);
}

View File

@ -16,7 +16,7 @@
#include "BLI_ghash.h"
#include "BLI_index_range.hh"
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@ -704,7 +704,7 @@ Nurb *BKE_nurb_copy(Nurb *src, int pntsu, int pntsv)
*newnu = blender::dna::shallow_copy(*src);
if (pntsu == 1) {
SWAP(int, pntsu, pntsv);
std::swap(pntsu, pntsv);
}
newnu->pntsu = pntsu;
newnu->pntsv = pntsv;
@ -3048,7 +3048,7 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
bevp2 = bevp1 + (bl->nr - 1);
nr = bl->nr / 2;
while (nr--) {
SWAP(BevPoint, *bevp1, *bevp2);
std::swap( *bevp1, *bevp2);
bevp1++;
bevp2--;
}
@ -4437,7 +4437,7 @@ void BKE_nurb_direction_switch(Nurb *nu)
a /= 2;
while (a > 0) {
if (bezt1 != bezt2) {
SWAP(BezTriple, *bezt1, *bezt2);
std::swap(*bezt1, *bezt2);
}
swap_v3_v3(bezt1->vec[0], bezt1->vec[2]);
@ -4446,12 +4446,12 @@ void BKE_nurb_direction_switch(Nurb *nu)
swap_v3_v3(bezt2->vec[0], bezt2->vec[2]);
}
SWAP(uint8_t, bezt1->h1, bezt1->h2);
SWAP(uint8_t, bezt1->f1, bezt1->f3);
std::swap( bezt1->h1, bezt1->h2);
std::swap( bezt1->f1, bezt1->f3);
if (bezt1 != bezt2) {
SWAP(uint8_t, bezt2->h1, bezt2->h2);
SWAP(uint8_t, bezt2->f1, bezt2->f3);
std::swap( bezt2->h1, bezt2->h2);
std::swap( bezt2->f1, bezt2->f3);
bezt1->tilt = -bezt1->tilt;
bezt2->tilt = -bezt2->tilt;
}
@ -4469,7 +4469,7 @@ void BKE_nurb_direction_switch(Nurb *nu)
bp2 = bp1 + (a - 1);
a /= 2;
while (bp1 != bp2 && a > 0) {
SWAP(BPoint, *bp1, *bp2);
std::swap( *bp1, *bp2);
a--;
bp1->tilt = -bp1->tilt;
bp2->tilt = -bp2->tilt;
@ -4491,7 +4491,7 @@ void BKE_nurb_direction_switch(Nurb *nu)
fp2 = fp1 + (a - 1);
a /= 2;
while (fp1 != fp2 && a > 0) {
SWAP(float, *fp1, *fp2);
std::swap( *fp1, *fp2);
a--;
fp1++;
fp2--;
@ -4530,7 +4530,7 @@ void BKE_nurb_direction_switch(Nurb *nu)
a /= 2;
while (bp1 != bp2 && a > 0) {
SWAP(BPoint, *bp1, *bp2);
std::swap( *bp1, *bp2);
a--;
bp1++;
bp2--;

View File

@ -1,7 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_array.hh"
#include "BLI_devirtualize_parameters.hh"
#include "BLI_set.hh"
#include "BLI_task.hh"

View File

@ -1090,7 +1090,7 @@ static void calc_bevfac_mapping(const Curve *cu,
}
if (end < *r_start || (end == *r_start && *r_lastblend < 1.0f - *r_firstblend)) {
SWAP(int, *r_start, end);
std::swap(*r_start, end);
tmpf = *r_lastblend;
*r_lastblend = 1.0f - *r_firstblend;
*r_firstblend = 1.0f - tmpf;

View File

@ -440,12 +440,12 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
make_array_write_attribute<float3>,
tag_component_positions_changed);
static const fn::CustomMF_SI_SO<int8_t, int8_t> handle_type_clamp{
static auto handle_type_clamp = mf::build::SI1_SO<int8_t, int8_t>(
"Handle Type Validate",
[](int8_t value) {
return std::clamp<int8_t>(value, BEZIER_HANDLE_FREE, BEZIER_HANDLE_ALIGN);
},
fn::CustomMF_presets::AllSpanOrSingle()};
mf::build::exec_presets::AllSpanOrSingle());
static BuiltinCustomDataLayerProvider handle_type_right("handle_type_right",
ATTR_DOMAIN_POINT,
CD_PROP_INT8,
@ -484,10 +484,10 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
make_array_write_attribute<float>,
tag_component_positions_changed);
static const fn::CustomMF_SI_SO<int8_t, int8_t> nurbs_order_clamp{
static const auto nurbs_order_clamp = mf::build::SI1_SO<int8_t, int8_t>(
"NURBS Order Validate",
[](int8_t value) { return std::max<int8_t>(value, 0); },
fn::CustomMF_presets::AllSpanOrSingle()};
mf::build::exec_presets::AllSpanOrSingle());
static BuiltinCustomDataLayerProvider nurbs_order("nurbs_order",
ATTR_DOMAIN_CURVE,
CD_PROP_INT8,
@ -501,12 +501,12 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
tag_component_topology_changed,
AttributeValidator{&nurbs_order_clamp});
static const fn::CustomMF_SI_SO<int8_t, int8_t> normal_mode_clamp{
static const auto normal_mode_clamp = mf::build::SI1_SO<int8_t, int8_t>(
"Normal Mode Validate",
[](int8_t value) {
return std::clamp<int8_t>(value, NORMAL_MODE_MINIMUM_TWIST, NORMAL_MODE_Z_UP);
},
fn::CustomMF_presets::AllSpanOrSingle()};
mf::build::exec_presets::AllSpanOrSingle());
static BuiltinCustomDataLayerProvider normal_mode("normal_mode",
ATTR_DOMAIN_CURVE,
CD_PROP_INT8,
@ -520,12 +520,12 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
tag_component_normals_changed,
AttributeValidator{&normal_mode_clamp});
static const fn::CustomMF_SI_SO<int8_t, int8_t> knots_mode_clamp{
static const auto knots_mode_clamp = mf::build::SI1_SO<int8_t, int8_t>(
"Knots Mode Validate",
[](int8_t value) {
return std::clamp<int8_t>(value, NURBS_KNOT_MODE_NORMAL, NURBS_KNOT_MODE_ENDPOINT_BEZIER);
},
fn::CustomMF_presets::AllSpanOrSingle()};
mf::build::exec_presets::AllSpanOrSingle());
static BuiltinCustomDataLayerProvider nurbs_knots_mode("knots_mode",
ATTR_DOMAIN_CURVE,
CD_PROP_INT8,
@ -539,12 +539,12 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
tag_component_topology_changed,
AttributeValidator{&knots_mode_clamp});
static const fn::CustomMF_SI_SO<int8_t, int8_t> curve_type_clamp{
static const auto curve_type_clamp = mf::build::SI1_SO<int8_t, int8_t>(
"Curve Type Validate",
[](int8_t value) {
return std::clamp<int8_t>(value, CURVE_TYPE_CATMULL_ROM, CURVE_TYPES_NUM);
},
fn::CustomMF_presets::AllSpanOrSingle()};
mf::build::exec_presets::AllSpanOrSingle());
static BuiltinCustomDataLayerProvider curve_type("curve_type",
ATTR_DOMAIN_CURVE,
CD_PROP_INT8,
@ -558,10 +558,10 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
tag_component_curve_types_changed,
AttributeValidator{&curve_type_clamp});
static const fn::CustomMF_SI_SO<int, int> resolution_clamp{
static const auto resolution_clamp = mf::build::SI1_SO<int, int>(
"Resolution Validate",
[](int value) { return std::max<int>(value, 1); },
fn::CustomMF_presets::AllSpanOrSingle()};
mf::build::exec_presets::AllSpanOrSingle());
static BuiltinCustomDataLayerProvider resolution("resolution",
ATTR_DOMAIN_CURVE,
CD_PROP_INT32,

View File

@ -1253,13 +1253,13 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
make_array_write_attribute<int>,
nullptr);
static const fn::CustomMF_SI_SO<int, int> material_index_clamp{
static const auto material_index_clamp = mf::build::SI1_SO<int, int>(
"Material Index Validate",
[](int value) {
/* Use #short for the maximum since many areas still use that type for indices. */
return std::clamp<int>(value, 0, std::numeric_limits<short>::max());
},
fn::CustomMF_presets::AllSpanOrSingle()};
mf::build::exec_presets::AllSpanOrSingle());
static BuiltinCustomDataLayerProvider material_index("material_index",
ATTR_DOMAIN_FACE,
CD_PROP_INT32,

View File

@ -20,8 +20,8 @@
#include "BLI_ghash.h"
#include "BLI_hash.h"
#include "BLI_heap.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector.h"
#include "BLI_math_vector_types.hh"
#include "BLI_polyfill_2d.h"
#include "BLI_span.hh"

View File

@ -2531,7 +2531,7 @@ bool BKE_keyblock_move(Object *ob, int org_index, int new_index)
BLI_listbase_swaplinks(&key->block, kb, other_kb);
/* Swap absolute positions. */
SWAP(float, kb->pos, other_kb->pos);
std::swap(kb->pos, other_kb->pos);
kb = other_kb;
}

View File

@ -181,7 +181,7 @@ static uint partition_mainb(MetaElem **mainb, uint start, uint end, uint s, floa
break;
}
SWAP(MetaElem *, mainb[i], mainb[j]);
std::swap(mainb[i], mainb[j]);
i++;
j--;
}

View File

@ -1726,7 +1726,7 @@ void BKE_mesh_mselect_active_set(Mesh *me, int index, int type)
}
else if (msel_index != me->totselect - 1) {
/* move to the end */
SWAP(MSelect, me->mselect[msel_index], me->mselect[me->totselect - 1]);
std::swap(me->mselect[msel_index], me->mselect[me->totselect - 1]);
}
BLI_assert((me->mselect[me->totselect - 1].index == index) &&

View File

@ -19,7 +19,7 @@
#include "BLI_array.hh"
#include "BLI_float4x4.hh"
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_mesh_boolean.hh"
#include "BLI_mesh_intersect.hh"
#include "BLI_span.hh"

View File

@ -545,8 +545,8 @@ void BKE_mesh_mdisp_flip(MDisps *md, const bool use_loop_mdisp_flip)
co_b = co[x * sides + y];
swap_v3_v3(co_a, co_b);
SWAP(float, co_a[0], co_a[1]);
SWAP(float, co_b[0], co_b[1]);
std::swap(co_a[0], co_a[1]);
std::swap(co_b[0], co_b[1]);
if (use_loop_mdisp_flip) {
co_a[2] *= -1.0f;
@ -556,7 +556,7 @@ void BKE_mesh_mdisp_flip(MDisps *md, const bool use_loop_mdisp_flip)
co_a = co[x * sides + x];
SWAP(float, co_a[0], co_a[1]);
std::swap(co_a[0], co_a[1]);
if (use_loop_mdisp_flip) {
co_a[2] *= -1.0f;
@ -591,10 +591,10 @@ void BKE_mesh_polygon_flip_ex(const MPoly *mpoly,
for (loopstart++; loopend > loopstart; loopstart++, loopend--) {
mloop[loopend].e = mloop[loopend - 1].e;
SWAP(uint, mloop[loopstart].e, prev_edge_index);
std::swap(mloop[loopstart].e, prev_edge_index);
if (!loops_in_ldata) {
SWAP(MLoop, mloop[loopstart], mloop[loopend]);
std::swap(mloop[loopstart], mloop[loopend]);
}
if (lnors) {
swap_v3_v3(lnors[loopstart], lnors[loopend]);

View File

@ -163,7 +163,7 @@ static void mesh_calc_edges_mdata(const MVert * /*allvert*/,
/* order is swapped so extruding this edge as a surface won't flip face normals
* with cyclic curves */
if (ed->v1 + 1 != ed->v2) {
SWAP(uint, med->v1, med->v2);
std::swap(med->v1, med->v2);
}
med++;
}
@ -919,8 +919,8 @@ int BKE_mesh_mface_index_validate(MFace *mface, CustomData *fdata, int mfindex,
if (mface->v3 == 0) {
static int corner_indices[4] = {1, 2, 0, 3};
SWAP(uint, mface->v1, mface->v2);
SWAP(uint, mface->v2, mface->v3);
std::swap(mface->v1, mface->v2);
std::swap(mface->v2, mface->v3);
if (fdata) {
CustomData_swap_corners(fdata, mfindex, corner_indices);
@ -931,8 +931,8 @@ int BKE_mesh_mface_index_validate(MFace *mface, CustomData *fdata, int mfindex,
if (mface->v3 == 0 || mface->v4 == 0) {
static int corner_indices[4] = {2, 3, 0, 1};
SWAP(uint, mface->v1, mface->v3);
SWAP(uint, mface->v2, mface->v4);
std::swap(mface->v1, mface->v3);
std::swap(mface->v2, mface->v4);
if (fdata) {
CustomData_swap_corners(fdata, mfindex, corner_indices);

View File

@ -21,7 +21,7 @@
#include "BLI_linklist.h"
#include "BLI_linklist_stack.h"
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_memarena.h"
#include "BLI_span.hh"
#include "BLI_stack.h"

View File

@ -16,8 +16,8 @@
#include "BLI_array.hh"
#include "BLI_index_range.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector.h"
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
#include "BLI_task.hh"

View File

@ -14,6 +14,11 @@ namespace blender::bke::anonymous_attribute_inferencing {
namespace aal = nodes::aal;
using nodes::NodeDeclaration;
static bool socket_is_field(const bNodeSocket &socket)
{
return socket.display_shape == SOCK_DISPLAY_SHAPE_DIAMOND;
}
static const aal::RelationsInNode &get_relations_in_node(const bNode &node, ResourceScope &scope)
{
if (node.is_group()) {
@ -22,6 +27,25 @@ static const aal::RelationsInNode &get_relations_in_node(const bNode &node, Reso
return *group->runtime->anonymous_attribute_relations;
}
}
if (node.is_reroute()) {
const bNodeSocket &socket = node.input_socket(0);
if (socket_is_field(socket)) {
static const aal::RelationsInNode field_relations = []() {
aal::RelationsInNode relations;
relations.reference_relations.append({0, 0});
return relations;
}();
return field_relations;
}
if (socket.type == SOCK_GEOMETRY) {
static const aal::RelationsInNode geometry_relations = []() {
aal::RelationsInNode relations;
relations.propagate_relations.append({0, 0});
return relations;
}();
return geometry_relations;
}
}
if (const NodeDeclaration *node_decl = node.declaration()) {
if (const aal::RelationsInNode *relations = node_decl->anonymous_attribute_relations()) {
return *relations;
@ -41,11 +65,6 @@ Array<const aal::RelationsInNode *> get_relations_by_node(const bNodeTree &tree,
return relations_by_node;
}
static bool socket_is_field(const bNodeSocket &socket)
{
return socket.display_shape == SOCK_DISPLAY_SHAPE_DIAMOND;
}
/**
* Start at a group output socket and find all linked group inputs.
*/

View File

@ -54,7 +54,7 @@
#include "BLI_linklist.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_threads.h"
#include "BLI_utildefines.h"

View File

@ -17,7 +17,7 @@
#include "BLI_array.hh"
#include "BLI_float4x4.hh"
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_rand.h"
#include "BLI_span.hh"
#include "BLI_vector.hh"

View File

@ -129,7 +129,7 @@ static void palette_undo_preserve(BlendLibReader * /*reader*/, ID *id_new, ID *i
/* NOTE: We do not swap IDProperties, as dealing with potential ID pointers in those would be
* fairly delicate. */
BKE_lib_id_swap(nullptr, id_new, id_old);
SWAP(IDProperty *, id_new->properties, id_old->properties);
std::swap(id_new->properties, id_old->properties);
}
IDTypeInfo IDType_ID_PAL = {
@ -1081,7 +1081,7 @@ bool BKE_paint_ensure(ToolSettings *ts, Paint **r_paint)
Paint paint_test = **r_paint;
BKE_paint_runtime_init(ts, *r_paint);
/* Swap so debug doesn't hide errors when release fails. */
SWAP(Paint, **r_paint, paint_test);
std::swap(**r_paint, paint_test);
BLI_assert(paint_test.runtime.ob_mode == (*r_paint)->runtime.ob_mode);
BLI_assert(paint_test.runtime.tool_offset == (*r_paint)->runtime.tool_offset);
#endif

View File

@ -27,7 +27,7 @@
#include "BLI_float3x3.hh"
#include "BLI_map.hh"
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_rect.h"
#include "BLI_vector.hh"
#include "BLI_vector_list.hh"

View File

@ -510,12 +510,12 @@ static void scene_foreach_toolsettings_id_pointer_process(
}
/* We failed to find a new valid pointer for the previous ID, just keep the current one as
* if we had been under SCENE_FOREACH_UNDO_NO_RESTORE case. */
SWAP(ID *, *id_p, *id_old_p);
std::swap(*id_p, *id_old_p);
break;
}
case SCENE_FOREACH_UNDO_NO_RESTORE:
/* Counteract the swap of the whole ToolSettings container struct. */
SWAP(ID *, *id_p, *id_old_p);
std::swap(*id_p, *id_old_p);
break;
}
}
@ -1686,14 +1686,14 @@ static void scene_undo_preserve(BlendLibReader *reader, ID *id_new, ID *id_old)
Scene *scene_new = (Scene *)id_new;
Scene *scene_old = (Scene *)id_old;
SWAP(View3DCursor, scene_old->cursor, scene_new->cursor);
std::swap( scene_old->cursor, scene_new->cursor);
if (scene_new->toolsettings != nullptr && scene_old->toolsettings != nullptr) {
/* First try to restore ID pointers that can be and should be preserved (like brushes or
* palettes), and counteract the swap of the whole ToolSettings structs below for the others
* (like object ones). */
scene_foreach_toolsettings(
nullptr, scene_new->toolsettings, true, reader, scene_old->toolsettings);
SWAP(ToolSettings, *scene_old->toolsettings, *scene_new->toolsettings);
std::swap( *scene_old->toolsettings, *scene_new->toolsettings);
}
}

View File

@ -16,7 +16,7 @@
#include "BLI_compiler_compat.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_rand.h"
#include "BLI_span.hh"
#include "BLI_string.h"

View File

@ -5,8 +5,8 @@
#include "DNA_tracking_types.h"
#include "BKE_tracking.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector.h"
#include "BLI_math_vector_types.hh"
namespace blender {

View File

@ -11,7 +11,7 @@
namespace blender::bke {
using fn::MFDataType;
using mf::DataType;
template<typename From, typename To, To (*ConversionF)(const From &)>
static void add_implicit_conversion(DataTypeConversions &conversions)
@ -20,20 +20,20 @@ static void add_implicit_conversion(DataTypeConversions &conversions)
static const CPPType &to_type = CPPType::get<To>();
static const std::string conversion_name = from_type.name() + " to " + to_type.name();
static fn::CustomMF_SI_SO<From, To> multi_function{
static auto multi_function = mf::build::SI1_SO<From, To>(
conversion_name.c_str(),
/* Use lambda instead of passing #ConversionF directly, because otherwise the compiler won't
* inline the function. */
[](const From &a) { return ConversionF(a); },
fn::CustomMF_presets::AllSpanOrSingle()};
mf::build::exec_presets::AllSpanOrSingle());
static auto convert_single_to_initialized = [](const void *src, void *dst) {
*(To *)dst = ConversionF(*(const From *)src);
};
static auto convert_single_to_uninitialized = [](const void *src, void *dst) {
new (dst) To(ConversionF(*(const From *)src));
};
conversions.add(fn::MFDataType::ForSingle<From>(),
fn::MFDataType::ForSingle<To>(),
conversions.add(mf::DataType::ForSingle<From>(),
mf::DataType::ForSingle<To>(),
multi_function,
convert_single_to_initialized,
convert_single_to_uninitialized);
@ -361,26 +361,26 @@ void DataTypeConversions::convert_to_uninitialized(const CPPType &from_type,
}
const ConversionFunctions *functions = this->get_conversion_functions(
MFDataType::ForSingle(from_type), MFDataType::ForSingle(to_type));
DataType::ForSingle(from_type), DataType::ForSingle(to_type));
BLI_assert(functions != nullptr);
functions->convert_single_to_uninitialized(from_value, to_value);
}
static void call_convert_to_uninitialized_fn(const GVArray &from,
const fn::MultiFunction &fn,
const mf::MultiFunction &fn,
const IndexMask mask,
GMutableSpan to)
{
fn::MFParamsBuilder params{fn, mask.min_array_size()};
mf::ParamsBuilder params{fn, mask.min_array_size()};
params.add_readonly_single_input(from);
params.add_uninitialized_single_output(to);
fn::MFContextBuilder context;
mf::ContextBuilder context;
fn.call_auto(mask, params, context);
}
static void call_convert_to_uninitialized_fn(const GVArray &from,
const fn::MultiFunction &fn,
const mf::MultiFunction &fn,
GMutableSpan to)
{
call_convert_to_uninitialized_fn(from, fn, IndexMask(from.size()), to);
@ -394,8 +394,8 @@ void DataTypeConversions::convert_to_initialized_n(GSpan from_span, GMutableSpan
BLI_assert(from_span.size() == to_span.size());
BLI_assert(this->is_convertible(from_type, to_type));
const fn::MultiFunction *fn = this->get_conversion_multi_function(
MFDataType::ForSingle(from_type), MFDataType::ForSingle(to_type));
const mf::MultiFunction *fn = this->get_conversion_multi_function(DataType::ForSingle(from_type),
DataType::ForSingle(to_type));
to_type.destruct_n(to_span.data(), to_span.size());
call_convert_to_uninitialized_fn(GVArray::ForSpan(from_span), *fn, to_span);
@ -541,8 +541,8 @@ fn::GField DataTypeConversions::try_convert(fn::GField field, const CPPType &to_
if (!this->is_convertible(from_type, to_type)) {
return {};
}
const fn::MultiFunction &fn = *this->get_conversion_multi_function(
fn::MFDataType::ForSingle(from_type), fn::MFDataType::ForSingle(to_type));
const mf::MultiFunction &fn = *this->get_conversion_multi_function(
mf::DataType::ForSingle(from_type), mf::DataType::ForSingle(to_type));
return {std::make_shared<fn::FieldOperation>(fn, Vector<fn::GField>{std::move(field)})};
}

View File

@ -19,7 +19,7 @@
#include "BLI_index_range.hh"
#include "BLI_map.hh"
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_string_ref.hh"

View File

@ -8,8 +8,8 @@
#include "BLI_array.hh"
#include "BLI_math_matrix.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector.h"
#include "BLI_math_vector_types.hh"
#include "BLI_vector.hh"
#include "DNA_volume_types.h"

View File

@ -2,7 +2,7 @@
#include <vector>
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
#include "BLI_utildefines.h"

View File

@ -202,8 +202,8 @@ void BLI_delaunay_2d_cdt_free(CDT_result *result);
# include "BLI_array.hh"
# include "BLI_math_mpq.hh"
# include "BLI_math_vec_mpq_types.hh"
# include "BLI_math_vec_types.hh"
# include "BLI_math_vector_mpq_types.hh"
# include "BLI_math_vector_types.hh"
# include "BLI_vector.hh"
namespace blender::meshintersect {

View File

@ -26,302 +26,139 @@
* times and binary sizes, depending on the number of parameters that are devirtualized separately.
* So there is always a trade-off between run-time performance and compile-time/binary-size.
*
* This file provides a utility to devirtualize array parameters to a function using a high level
* API. This makes it easy to experiment with different extremes of the mentioned trade-off and
* allows finding a good compromise for each function.
* This file provides a utility to devirtualize function parameters using a high level API. This
* makes it easy to experiment with different extremes of the mentioned trade-off and allows
* finding a good compromise for each function.
*/
#include "BLI_parameter_pack_utils.hh"
#include "BLI_virtual_array.hh"
namespace blender::devirtualize_parameters {
/**
* Bit flag that specifies how an individual parameter is or can be devirtualized.
*/
enum class DeviMode {
/* This is used as zero-value to compare to, to avoid casting to int. */
None = 0,
/* Don't use devirtualization for that parameter, just pass it along. */
Keep = (1 << 0),
/* Devirtualize #Varray as #Span. */
Span = (1 << 1),
/* Devirtualize #VArray as #SingleAsSpan. */
Single = (1 << 2),
/* Devirtualize #IndexMask as #IndexRange. */
Range = (1 << 3),
};
ENUM_OPERATORS(DeviMode, DeviMode::Range);
/** Utility to encode multiple #DeviMode in a type. */
template<DeviMode... Mode> using DeviModeSequence = ValueSequence<DeviMode, Mode...>;
/**
* Main class that performs the devirtualization.
*/
template<typename Fn, typename... SourceTypes> class Devirtualizer {
private:
/** Utility to get the tag of the I-th source type. */
template<size_t I>
using type_at_index = typename TypeSequence<SourceTypes...>::template at_index<I>;
static constexpr size_t SourceTypesNum = sizeof...(SourceTypes);
/** Function to devirtualize. */
Fn fn_;
/**
* Source values that will be devirtualized. Note that these are stored as pointers to avoid
* unnecessary copies. The caller is responsible for keeping the memory alive.
*/
std::tuple<const SourceTypes *...> sources_;
/** Keeps track of whether #fn_ has been called already to avoid calling it twice. */
bool executed_ = false;
public:
Devirtualizer(Fn fn, const SourceTypes *...sources) : fn_(std::move(fn)), sources_{sources...}
{
}
/**
* Return true when the function passed to the constructor has been called already.
*/
bool executed() const
{
return executed_;
}
/**
* At compile time, generates multiple variants of the function, each optimized for a different
* combination of devirtualized parameters. For every parameter, a bit flag is passed that
* determines how it will be devirtualized. At run-time, if possible, one of the generated
* functions is picked and executed.
*
* To check whether the function was called successfully, call #executed() afterwards.
*
* \note This generates an exponential amount of code in the final binary, depending on how many
* to-be-virtualized parameters there are.
*/
template<DeviMode... AllowedModes>
void try_execute_devirtualized(DeviModeSequence<AllowedModes...> /* allowed_modes */)
{
BLI_assert(!executed_);
static_assert(sizeof...(AllowedModes) == SourceTypesNum);
this->try_execute_devirtualized_impl(DeviModeSequence<>(),
DeviModeSequence<AllowedModes...>());
}
/**
* Execute the function and pass in the original parameters without doing any devirtualization.
*/
void execute_without_devirtualization()
{
BLI_assert(!executed_);
this->try_execute_devirtualized_impl_call(
make_value_sequence<DeviMode, DeviMode::Keep, SourceTypesNum>(),
std::make_index_sequence<SourceTypesNum>());
}
private:
/**
* A recursive method that generates all the combinations of devirtualized parameters that the
* caller requested. A recursive function is necessary to achieve generating an exponential
* number of function calls (which has to be used with care, but is expected here).
*
* At every recursive step, the #DeviMode of one parameter is determined. This is achieved by
* extending #DeviModeSequence<Mode...> by one element in each step. The recursion ends once all
* parameters are handled.
*
* \return True when the function has been executed.
*/
template<DeviMode... Mode, DeviMode... AllowedModes>
bool try_execute_devirtualized_impl(
/* Initially empty, but then extended by one element in each recursive step. */
DeviModeSequence<Mode...> /* modes */,
/* Bit flag for every parameter. */
DeviModeSequence<AllowedModes...> /* allowed_modes */)
{
static_assert(SourceTypesNum == sizeof...(AllowedModes));
if constexpr (SourceTypesNum == sizeof...(Mode)) {
/* End of recursion, now call the function with the determined #DeviModes. */
this->try_execute_devirtualized_impl_call(DeviModeSequence<Mode...>(),
std::make_index_sequence<SourceTypesNum>());
return true;
}
else {
/* Index of the parameter that is checked in the current recursive step. */
constexpr size_t I = sizeof...(Mode);
/* Non-devirtualized parameter type. */
using SourceType = type_at_index<I>;
/* A bit flag indicating what devirtualizations are allowed in this step. */
[[maybe_unused]] constexpr DeviMode allowed_modes =
DeviModeSequence<AllowedModes...>::template at_index<I>();
/* Handle #VArray types. */
if constexpr (is_VArray_v<SourceType>) {
/* The actual virtual array, used for dynamic dispatch at run-time. */
const SourceType &varray = *std::get<I>(sources_);
/* Check if the virtual array is a single value. */
if constexpr ((allowed_modes & DeviMode::Single) != DeviMode::None) {
if (varray.is_single()) {
if (this->try_execute_devirtualized_impl(DeviModeSequence<Mode..., DeviMode::Single>(),
DeviModeSequence<AllowedModes...>())) {
return true;
}
}
}
/* Check if the virtual array is a span. */
if constexpr ((allowed_modes & DeviMode::Span) != DeviMode::None) {
if (varray.is_span()) {
if (this->try_execute_devirtualized_impl(DeviModeSequence<Mode..., DeviMode::Span>(),
DeviModeSequence<AllowedModes...>())) {
return true;
}
}
}
/* Check if it is ok if the virtual array is not devirtualized. */
if constexpr ((allowed_modes & DeviMode::Keep) != DeviMode::None) {
if (this->try_execute_devirtualized_impl(DeviModeSequence<Mode..., DeviMode::Keep>(),
DeviModeSequence<AllowedModes...>())) {
return true;
}
}
}
/* Handle #IndexMask. */
else if constexpr (std::is_same_v<IndexMask, SourceType>) {
/* Check if the mask is actually a contiguous range. */
if constexpr ((allowed_modes & DeviMode::Range) != DeviMode::None) {
/* The actual mask used for dynamic dispatch at run-time. */
const IndexMask &mask = *std::get<I>(sources_);
if (mask.is_range()) {
if (this->try_execute_devirtualized_impl(DeviModeSequence<Mode..., DeviMode::Range>(),
DeviModeSequence<AllowedModes...>())) {
return true;
}
}
}
/* Check if mask is also allowed to stay a span. */
if constexpr ((allowed_modes & DeviMode::Span) != DeviMode::None) {
if (this->try_execute_devirtualized_impl(DeviModeSequence<Mode..., DeviMode::Span>(),
DeviModeSequence<AllowedModes...>())) {
return true;
}
}
}
/* Handle unknown types. */
else {
if (this->try_execute_devirtualized_impl(DeviModeSequence<Mode..., DeviMode::Keep>(),
DeviModeSequence<AllowedModes...>())) {
return true;
}
}
}
return false;
}
/**
* Actually call the function with devirtualized parameters.
*/
template<DeviMode... Mode, size_t... I>
void try_execute_devirtualized_impl_call(DeviModeSequence<Mode...> /* modes */,
std::index_sequence<I...> /* indices */)
{
BLI_assert(!executed_);
fn_(this->get_devirtualized_parameter<I, Mode>()...);
executed_ = true;
}
/**
* Return the I-th parameter devirtualized using the passed in #DeviMode. This has different
* return types based on the template parameters.
*
* \note It is expected that the caller already knows that the parameter can be devirtualized
* with the given mode.
*/
template<size_t I, DeviMode Mode> decltype(auto) get_devirtualized_parameter()
{
using SourceType = type_at_index<I>;
static_assert(Mode != DeviMode::None);
if constexpr (Mode == DeviMode::Keep) {
/* Don't change the original parameter at all. */
return *std::get<I>(sources_);
}
if constexpr (is_VArray_v<SourceType>) {
const SourceType &varray = *std::get<I>(sources_);
if constexpr (Mode == DeviMode::Single) {
/* Devirtualize virtual array as single value. */
return SingleAsSpan(varray);
}
else if constexpr (Mode == DeviMode::Span) {
/* Devirtualize virtual array as span. */
return varray.get_internal_span();
}
}
else if constexpr (std::is_same_v<IndexMask, SourceType>) {
const IndexMask &mask = *std::get<I>(sources_);
if constexpr (ELEM(Mode, DeviMode::Span)) {
/* Don't devirtualize mask, it's still a span. */
return mask;
}
else if constexpr (Mode == DeviMode::Range) {
/* Devirtualize the mask as range. */
return mask.as_range();
}
}
}
};
} // namespace blender::devirtualize_parameters
namespace blender {
/**
* Generate multiple versions of the given function optimized for different virtual arrays.
* One has to be careful with nesting multiple devirtualizations, because that results in an
* exponential number of function instantiations (increasing compile time and binary size).
* Calls the given function with devirtualized parameters if possible. Note that using many
* non-trivial devirtualizers results in exponential code growth.
*
* Generally, this function should only be used when the virtual method call overhead to get an
* element from a virtual array is significant.
* \return True if the function has been called.
*
* Every devirtualizer is expected to have a `devirtualize(auto fn) -> bool` method.
* This method is expected to do one of two things:
* - Call `fn` with the devirtualized argument and return what `fn` returns.
* - Don't call `fn` (because the devirtualization failed) and return false.
*
* Examples for devirtualizers: #BasicDevirtualizer, #IndexMaskDevirtualizer, #VArrayDevirtualizer.
*/
template<typename T, typename Func>
inline void devirtualize_varray(const VArray<T> &varray, const Func &func, bool enable = true)
template<typename Fn, typename... Devirtualizers>
inline bool call_with_devirtualized_parameters(const std::tuple<Devirtualizers...> &devis,
const Fn &fn)
{
using namespace devirtualize_parameters;
if (enable) {
Devirtualizer<decltype(func), VArray<T>> devirtualizer(func, &varray);
constexpr DeviMode devi_mode = DeviMode::Single | DeviMode::Span;
devirtualizer.try_execute_devirtualized(DeviModeSequence<devi_mode>());
if (devirtualizer.executed()) {
return;
}
/* In theory the code below could be generalized to avoid code duplication. However, the maximum
* number of parameters is expected to be relatively low. Explicitly implementing the different
* cases makes it more obvious to see what is going on and also makes inlining everything easier
* for the compiler. */
constexpr size_t DeviNum = sizeof...(Devirtualizers);
if constexpr (DeviNum == 0) {
fn();
return true;
}
func(varray);
if constexpr (DeviNum == 1) {
return std::get<0>(devis).devirtualize([&](auto param0) {
fn(param0);
return true;
});
}
if constexpr (DeviNum == 2) {
return std::get<0>(devis).devirtualize([&](auto &&param0) {
return std::get<1>(devis).devirtualize([&](auto &&param1) {
fn(param0, param1);
return true;
});
});
}
if constexpr (DeviNum == 3) {
return std::get<0>(devis).devirtualize([&](auto &&param0) {
return std::get<1>(devis).devirtualize([&](auto &&param1) {
return std::get<2>(devis).devirtualize([&](auto &&param2) {
fn(param0, param1, param2);
return true;
});
});
});
}
if constexpr (DeviNum == 4) {
return std::get<0>(devis).devirtualize([&](auto &&param0) {
return std::get<1>(devis).devirtualize([&](auto &&param1) {
return std::get<2>(devis).devirtualize([&](auto &&param2) {
return std::get<3>(devis).devirtualize([&](auto &&param3) {
fn(param0, param1, param2, param3);
return true;
});
});
});
});
}
if constexpr (DeviNum == 5) {
return std::get<0>(devis).devirtualize([&](auto &&param0) {
return std::get<1>(devis).devirtualize([&](auto &&param1) {
return std::get<2>(devis).devirtualize([&](auto &&param2) {
return std::get<3>(devis).devirtualize([&](auto &&param3) {
return std::get<4>(devis).devirtualize([&](auto &&param4) {
fn(param0, param1, param2, param3, param4);
return true;
});
});
});
});
});
}
if constexpr (DeviNum == 6) {
return std::get<0>(devis).devirtualize([&](auto &&param0) {
return std::get<1>(devis).devirtualize([&](auto &&param1) {
return std::get<2>(devis).devirtualize([&](auto &&param2) {
return std::get<3>(devis).devirtualize([&](auto &&param3) {
return std::get<4>(devis).devirtualize([&](auto &&param4) {
return std::get<5>(devis).devirtualize([&](auto &&param5) {
fn(param0, param1, param2, param3, param4, param5);
return true;
});
});
});
});
});
});
}
if constexpr (DeviNum == 7) {
return std::get<0>(devis).devirtualize([&](auto &&param0) {
return std::get<1>(devis).devirtualize([&](auto &&param1) {
return std::get<2>(devis).devirtualize([&](auto &&param2) {
return std::get<3>(devis).devirtualize([&](auto &&param3) {
return std::get<4>(devis).devirtualize([&](auto &&param4) {
return std::get<5>(devis).devirtualize([&](auto &&param5) {
return std::get<6>(devis).devirtualize([&](auto &&param6) {
fn(param0, param1, param2, param3, param4, param5, param6);
return true;
});
});
});
});
});
});
});
}
return false;
}
/**
* Same as `devirtualize_varray`, but devirtualizes two virtual arrays at the same time.
* This is better than nesting two calls to `devirtualize_varray`, because it instantiates fewer
* cases.
* A devirtualizer to be used with #call_with_devirtualized_parameters.
*
* This one is very simple, it does not perform any actual devirtualization. It can be used to pass
* parameters to the function that shouldn't be devirtualized.
*/
template<typename T1, typename T2, typename Func>
inline void devirtualize_varray2(const VArray<T1> &varray1,
const VArray<T2> &varray2,
const Func &func,
bool enable = true)
{
using namespace devirtualize_parameters;
if (enable) {
Devirtualizer<decltype(func), VArray<T1>, VArray<T2>> devirtualizer(func, &varray1, &varray2);
constexpr DeviMode devi_mode = DeviMode::Single | DeviMode::Span;
devirtualizer.try_execute_devirtualized(DeviModeSequence<devi_mode, devi_mode>());
if (devirtualizer.executed()) {
return;
}
template<typename T> struct BasicDevirtualizer {
const T value;
template<typename Fn> bool devirtualize(const Fn &fn) const
{
return fn(this->value);
}
func(varray1, varray2);
}
};
} // namespace blender

View File

@ -8,8 +8,8 @@
#include "BLI_assert.h"
#include "BLI_math_base.h"
#include "BLI_math_matrix.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector.h"
#include "BLI_math_vector_types.hh"
namespace blender {

View File

@ -3,9 +3,9 @@
#pragma once
#include "BLI_math_matrix.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector.h"
#include "BLI_math_vector.hh"
#include "BLI_math_vector_types.hh"
namespace blender {

View File

@ -798,6 +798,28 @@ inline bool GVArrayCommon::is_empty() const
/** \} */
/** To be used with #call_with_devirtualized_parameters. */
template<typename T, bool UseSingle, bool UseSpan> struct GVArrayDevirtualizer {
const GVArrayImpl &varray_impl;
template<typename Fn> bool devirtualize(const Fn &fn) const
{
const CommonVArrayInfo info = this->varray_impl.common_info();
const int64_t size = this->varray_impl.size();
if constexpr (UseSingle) {
if (info.type == CommonVArrayInfo::Type::Single) {
return fn(SingleAsSpan<T>(*static_cast<const T *>(info.data), size));
}
}
if constexpr (UseSpan) {
if (info.type == CommonVArrayInfo::Type::Span) {
return fn(Span<T>(static_cast<const T *>(info.data), size));
}
}
return false;
}
};
/* -------------------------------------------------------------------- */
/** \name Inline methods for #GVArray.
* \{ */

View File

@ -284,4 +284,22 @@ class IndexMask {
Vector<int64_t> *r_skip_amounts = nullptr) const;
};
/** To be used with #call_with_devirtualized_parameters. */
template<bool UseRange, bool UseSpan> struct IndexMaskDevirtualizer {
const IndexMask &mask;
template<typename Fn> bool devirtualize(const Fn &fn) const
{
if constexpr (UseRange) {
if (this->mask.is_range()) {
return fn(this->mask.as_range());
}
}
if constexpr (UseSpan) {
return fn(this->mask.indices());
}
return false;
}
};
} // namespace blender

View File

@ -59,13 +59,12 @@ template<typename T> inline T clamp(const T &a, const T &min, const T &max)
return std::clamp(a, min, max);
}
template<typename T, BLI_ENABLE_IF((is_math_float_type<T>))> inline T mod(const T &a, const T &b)
template<typename T> inline T mod(const T &a, const T &b)
{
return std::fmod(a, b);
}
template<typename T, BLI_ENABLE_IF((is_math_float_type<T>))>
inline T safe_mod(const T &a, const T &b)
template<typename T> inline T safe_mod(const T &a, const T &b)
{
return (b != 0) ? std::fmod(a, b) : 0;
}
@ -76,18 +75,17 @@ template<typename T> inline void min_max(const T &value, T &min, T &max)
max = math::max(value, max);
}
template<typename T, BLI_ENABLE_IF((is_math_float_type<T>))>
inline T safe_divide(const T &a, const T &b)
template<typename T> inline T safe_divide(const T &a, const T &b)
{
return (b != 0) ? a / b : T(0.0f);
}
template<typename T, BLI_ENABLE_IF((is_math_float_type<T>))> inline T floor(const T &a)
template<typename T> inline T floor(const T &a)
{
return std::floor(a);
}
template<typename T, BLI_ENABLE_IF((is_math_float_type<T>))> inline T ceil(const T &a)
template<typename T> inline T ceil(const T &a)
{
return std::ceil(a);
}
@ -97,7 +95,7 @@ template<typename T> inline T distance(const T &a, const T &b)
return std::abs(a - b);
}
template<typename T, BLI_ENABLE_IF((is_math_float_type<T>))> inline T fract(const T &a)
template<typename T> inline T fract(const T &a)
{
return a - std::floor(a);
}
@ -147,10 +145,7 @@ template<typename T> inline T hypot(const T &y, const T &x)
return std::hypot(y, x);
}
template<typename T,
typename FactorT,
BLI_ENABLE_IF((std::is_arithmetic_v<T>)),
BLI_ENABLE_IF((is_math_float_type<FactorT>))>
template<typename T, typename FactorT>
inline T interpolate(const T &a, const T &b, const FactorT &t)
{
auto result = a * (1 - t) + b * t;

View File

@ -7,11 +7,11 @@
* \brief Math vector functions needed specifically for mesh intersect and boolean.
*/
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#ifdef WITH_GMP
# include "BLI_math_mpq.hh"
# include "BLI_math_vec_mpq_types.hh"
# include "BLI_math_vector_mpq_types.hh"
#endif
namespace blender {

View File

@ -54,7 +54,8 @@ template<typename T, int Size> [[nodiscard]] T determinant(const MatBase<T, Size
/**
* Returns the adjoint of the matrix (also known as adjugate matrix).
*/
template<typename T, int Size> MatBase<T, Size, Size> adjoint(const MatBase<T, Size, Size> &mat);
template<typename T, int Size>
[[nodiscard]] MatBase<T, Size, Size> adjoint(const MatBase<T, Size, Size> &mat);
/**
* Equivalent to `mat * from_location(translation)` but with fewer operation.
@ -182,7 +183,7 @@ template<typename MatT> [[nodiscard]] MatT from_location(const typename MatT::ve
* If vector dimension is lower than matrix diagonal, the missing terms are filled with ones.
*/
template<typename MatT, int ScaleDim>
[[nodiscard]] MatT from_scale(const vec_base<typename MatT::base_type, ScaleDim> &scale);
[[nodiscard]] MatT from_scale(const VecBase<typename MatT::base_type, ScaleDim> &scale);
/**
* Create a rotation only matrix.
@ -209,7 +210,7 @@ template<typename MatT, typename RotationT>
template<typename MatT, typename RotationT, int ScaleDim>
[[nodiscard]] MatT from_loc_rot_scale(const typename MatT::vec3_type &location,
const RotationT &rotation,
const vec_base<typename MatT::base_type, ScaleDim> &scale);
const VecBase<typename MatT::base_type, ScaleDim> &scale);
/**
* Create a rotation matrix from 2 basis vectors.
@ -253,27 +254,27 @@ template<typename T, bool Normalized = false>
/**
* Extract the absolute 3d scale from a transform matrix.
* \tparam AllowNegativeScale if true, will compute determinant to know if matrix is negative.
* \tparam AllowNegativeScale: if true, will compute determinant to know if matrix is negative.
* This is a costly operation so it is disabled by default.
*/
template<bool AllowNegativeScale = false, typename T, int NumCol, int NumRow>
[[nodiscard]] inline vec_base<T, 3> to_scale(const MatBase<T, NumCol, NumRow> &mat);
[[nodiscard]] inline VecBase<T, 3> to_scale(const MatBase<T, NumCol, NumRow> &mat);
/**
* Decompose a matrix into location, rotation, and scale components.
* \tparam AllowNegativeScale if true, will compute determinant to know if matrix is negative.
* \tparam AllowNegativeScale: if true, will compute determinant to know if matrix is negative.
* Rotation and scale values will be flipped if it is negative.
* This is a costly operation so it is disabled by default.
*/
template<bool AllowNegativeScale = false, typename T, typename RotationT>
inline void to_rot_scale(const MatBase<T, 3, 3> &mat,
RotationT &r_rotation,
vec_base<T, 3> &r_scale);
VecBase<T, 3> &r_scale);
template<bool AllowNegativeScale = false, typename T, typename RotationT>
inline void to_loc_rot_scale(const MatBase<T, 4, 4> &mat,
vec_base<T, 3> &r_location,
VecBase<T, 3> &r_location,
RotationT &r_rotation,
vec_base<T, 3> &r_scale);
VecBase<T, 3> &r_scale);
/** \} */
@ -285,29 +286,29 @@ inline void to_loc_rot_scale(const MatBase<T, 4, 4> &mat,
* Transform a 3d point using a 3x3 matrix (rotation & scale).
*/
template<typename T>
[[nodiscard]] vec_base<T, 3> transform_point(const MatBase<T, 3, 3> &mat,
const vec_base<T, 3> &point);
[[nodiscard]] VecBase<T, 3> transform_point(const MatBase<T, 3, 3> &mat,
const VecBase<T, 3> &point);
/**
* Transform a 3d point using a 4x4 matrix (location & rotation & scale).
*/
template<typename T>
[[nodiscard]] vec_base<T, 3> transform_point(const MatBase<T, 4, 4> &mat,
const vec_base<T, 3> &point);
[[nodiscard]] VecBase<T, 3> transform_point(const MatBase<T, 4, 4> &mat,
const VecBase<T, 3> &point);
/**
* Transform a 3d direction vector using a 3x3 matrix (rotation & scale).
*/
template<typename T>
[[nodiscard]] vec_base<T, 3> transform_direction(const MatBase<T, 3, 3> &mat,
const vec_base<T, 3> &direction);
[[nodiscard]] VecBase<T, 3> transform_direction(const MatBase<T, 3, 3> &mat,
const VecBase<T, 3> &direction);
/**
* Transform a 3d direction vector using a 4x4 matrix (rotation & scale).
*/
template<typename T>
[[nodiscard]] vec_base<T, 3> transform_direction(const MatBase<T, 4, 4> &mat,
const vec_base<T, 3> &direction);
[[nodiscard]] VecBase<T, 3> transform_direction(const MatBase<T, 4, 4> &mat,
const VecBase<T, 3> &direction);
/**
* Project a point using a matrix (location & rotation & scale & perspective divide).
@ -378,7 +379,7 @@ template<typename T> [[nodiscard]] bool is_negative(const MatBase<T, 4, 4> &mat)
template<typename T, int NumCol, int NumRow>
[[nodiscard]] inline bool is_equal(const MatBase<T, NumCol, NumRow> &a,
const MatBase<T, NumCol, NumRow> &b,
const T epsilon)
const T epsilon = T(0))
{
for (int i = 0; i < NumCol; i++) {
for (int j = 0; j < NumRow; j++) {
@ -508,12 +509,12 @@ template<typename T, int NumCol, int NumRow, typename VectorT>
using MatT = MatBase<T, NumCol, NumRow>;
BLI_STATIC_ASSERT(VectorT::type_length <= MatT::col_len - 1,
"Translation should be at least 1 column less than the matrix.");
static constexpr int location_col = MatT::col_len - 1;
constexpr int location_col = MatT::col_len - 1;
/* Avoid multiplying the last row if it exists.
* Allows using non square matrices like float3x2 and saves computation. */
using IntermediateVecT =
vec_base<typename MatT::base_type,
(MatT::row_len > MatT::col_len - 1) ? (MatT::col_len - 1) : MatT::row_len>;
VecBase<typename MatT::base_type,
(MatT::row_len > MatT::col_len - 1) ? (MatT::col_len - 1) : MatT::row_len>;
MatT result = mat;
unroll<VectorT::type_length>([&](auto c) {
@ -590,11 +591,11 @@ template<typename T,
int SrcStartCol,
int SrcStartRow,
int SrcAlignment>
[[nodiscard]] MatBase<T, NumCol, NumRow, SrcAlignment> normalize(
[[nodiscard]] MatBase<T, NumCol, NumRow> normalize(
const MatView<T, NumCol, NumRow, SrcNumCol, SrcNumRow, SrcStartCol, SrcStartRow, SrcAlignment>
&a)
{
MatBase<T, NumCol, NumRow, SrcAlignment> result;
MatBase<T, NumCol, NumRow> result;
unroll<NumCol>([&](auto i) { result[i] = math::normalize(a[i]); });
return result;
}
@ -760,7 +761,7 @@ template<typename T> detail::Quaternion<T> normalized_to_quat_fast(const MatBase
}
BLI_assert(!(q.x < 0.0f));
BLI_assert(math::is_unit_scale(vec_base<T, 4>(q)));
BLI_assert(math::is_unit_scale(VecBase<T, 4>(q)));
return q;
}
@ -897,8 +898,8 @@ template<typename T, bool Normalized>
detail::normalized_to_eul2(normalize(mat), eul1, eul2);
}
/* Return best, which is just the one with lowest values it in. */
return (length_manhattan(vec_base<T, 3>(eul1)) > length_manhattan(vec_base<T, 3>(eul2))) ? eul2 :
eul1;
return (length_manhattan(VecBase<T, 3>(eul1)) > length_manhattan(VecBase<T, 3>(eul2))) ? eul2 :
eul1;
}
template<typename T, bool Normalized>
@ -928,9 +929,9 @@ template<typename T, bool Normalized>
}
template<bool AllowNegativeScale, typename T, int NumCol, int NumRow>
[[nodiscard]] inline vec_base<T, 3> to_scale(const MatBase<T, NumCol, NumRow> &mat)
[[nodiscard]] inline VecBase<T, 3> to_scale(const MatBase<T, NumCol, NumRow> &mat)
{
vec_base<T, 3> result = {length(mat.x_axis()), length(mat.y_axis()), length(mat.z_axis())};
VecBase<T, 3> result = {length(mat.x_axis()), length(mat.y_axis()), length(mat.z_axis())};
if constexpr (AllowNegativeScale) {
if (UNLIKELY(is_negative(mat))) {
result = -result;
@ -959,7 +960,7 @@ inline void to_rotation(const MatBase<T, 3, 3> &mat, detail::EulerXYZ<T> &r_rota
template<bool AllowNegativeScale, typename T, typename RotationT>
inline void to_rot_scale(const MatBase<T, 3, 3> &mat,
RotationT &r_rotation,
vec_base<T, 3> &r_scale)
VecBase<T, 3> &r_scale)
{
MatBase<T, 3, 3> normalized_mat = normalize_and_get_size(mat, r_scale);
if constexpr (AllowNegativeScale) {
@ -973,9 +974,9 @@ inline void to_rot_scale(const MatBase<T, 3, 3> &mat,
template<bool AllowNegativeScale, typename T, typename RotationT>
inline void to_loc_rot_scale(const MatBase<T, 4, 4> &mat,
vec_base<T, 3> &r_location,
VecBase<T, 3> &r_location,
RotationT &r_rotation,
vec_base<T, 3> &r_scale)
VecBase<T, 3> &r_scale)
{
r_location = mat.location();
to_rot_scale<AllowNegativeScale>(MatBase<T, 3, 3>(mat), r_rotation, r_scale);
@ -989,7 +990,7 @@ template<typename MatT> [[nodiscard]] MatT from_location(const typename MatT::ve
}
template<typename MatT, int ScaleDim>
[[nodiscard]] MatT from_scale(const vec_base<typename MatT::base_type, ScaleDim> &scale)
[[nodiscard]] MatT from_scale(const VecBase<typename MatT::base_type, ScaleDim> &scale)
{
BLI_STATIC_ASSERT(ScaleDim <= MatT::min_dim,
"Scale dimension should fit the matrix diagonal length.");
@ -1014,7 +1015,7 @@ template<typename MatT, typename RotationT, typename VectorT>
template<typename MatT, typename RotationT, int ScaleDim>
[[nodiscard]] MatT from_loc_rot_scale(const typename MatT::vec3_type &location,
const RotationT &rotation,
const vec_base<typename MatT::base_type, ScaleDim> &scale)
const VecBase<typename MatT::base_type, ScaleDim> &scale)
{
using Mat3x3 = MatBase<typename MatT::base_type, 3, 3>;
MatT mat = MatT(from_rot_scale<Mat3x3>(rotation, scale));
@ -1059,36 +1060,36 @@ template<typename MatT, typename VectorT>
}
template<typename T>
vec_base<T, 3> transform_point(const MatBase<T, 3, 3> &mat, const vec_base<T, 3> &point)
VecBase<T, 3> transform_point(const MatBase<T, 3, 3> &mat, const VecBase<T, 3> &point)
{
return mat * point;
}
template<typename T>
vec_base<T, 3> transform_point(const MatBase<T, 4, 4> &mat, const vec_base<T, 3> &point)
VecBase<T, 3> transform_point(const MatBase<T, 4, 4> &mat, const VecBase<T, 3> &point)
{
return mat.template view<3, 3>() * point + mat.location();
}
template<typename T>
vec_base<T, 3> transform_direction(const MatBase<T, 3, 3> &mat, const vec_base<T, 3> &direction)
VecBase<T, 3> transform_direction(const MatBase<T, 3, 3> &mat, const VecBase<T, 3> &direction)
{
return mat * direction;
}
template<typename T>
vec_base<T, 3> transform_direction(const MatBase<T, 4, 4> &mat, const vec_base<T, 3> &direction)
VecBase<T, 3> transform_direction(const MatBase<T, 4, 4> &mat, const VecBase<T, 3> &direction)
{
return mat.template view<3, 3>() * direction;
}
template<typename T, int N, int NumRow>
vec_base<T, N> project_point(const MatBase<T, N + 1, NumRow> &mat, const vec_base<T, N> &point)
VecBase<T, N> project_point(const MatBase<T, N + 1, NumRow> &mat, const VecBase<T, N> &point)
{
vec_base<T, N + 1> tmp(point, T(1));
VecBase<T, N + 1> tmp(point, T(1));
tmp = mat * tmp;
/* Absolute value to not flip the frustum upside down behind the camera. */
return vec_base<T, N>(tmp) / math::abs(tmp[N]);
return VecBase<T, N>(tmp) / math::abs(tmp[N]);
}
extern template float3 transform_point(const float3x3 &mat, const float3 &point);

View File

@ -30,12 +30,14 @@
* defined outside of the class in the `blender::math` namespace.
*/
#define __BLI_MATH_MATRIX_TYPES_HH__
#include <array>
#include <cmath>
#include <iostream>
#include <type_traits>
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_utildefines.h"
#include "BLI_utility_mixins.hh"
@ -70,13 +72,13 @@ template<
int NumRow,
/* Alignment in bytes. Do not align matrices whose size is not a multiple of 4 component.
* This is in order to avoid padding when using arrays of matrices. */
int Alignment = (((NumCol * NumRow) % 4) ? 4 : 0) * sizeof(T)>
struct alignas(Alignment) MatBase : public vec_struct_base<vec_base<T, NumRow>, NumCol> {
int Alignment = (((NumCol * NumRow) % 4 == 0) ? 4 : 1) * sizeof(T)>
struct alignas(Alignment) MatBase : public vec_struct_base<VecBase<T, NumRow>, NumCol> {
using base_type = T;
using vec3_type = vec_base<T, 3>;
using col_type = vec_base<T, NumRow>;
using row_type = vec_base<T, NumCol>;
using vec3_type = VecBase<T, 3>;
using col_type = VecBase<T, NumRow>;
using row_type = VecBase<T, NumCol>;
static constexpr int min_dim = (NumRow < NumCol) ? NumRow : NumCol;
static constexpr int col_len = NumCol;
static constexpr int row_len = NumRow;
@ -523,8 +525,8 @@ template<typename T,
struct MatView : NonCopyable, NonMovable {
using MatT = MatBase<T, NumCol, NumRow>;
using SrcMatT = MatBase<T, SrcNumCol, SrcNumRow, SrcAlignment>;
using col_type = vec_base<T, NumRow>;
using row_type = vec_base<T, NumCol>;
using col_type = VecBase<T, NumRow>;
using row_type = VecBase<T, NumCol>;
const SrcMatT &mat;
@ -605,7 +607,7 @@ struct MatView : NonCopyable, NonMovable {
friend MatT operator-(const MatView &a, const MatT &b)
{
return a - b.template view();
return a - b.view();
}
template<int OtherSrcNumCol,
@ -630,7 +632,7 @@ struct MatView : NonCopyable, NonMovable {
friend MatT operator-(const MatT &a, const MatView &b)
{
return a.template view() - b;
return a.view() - b;
}
friend MatT operator-(const MatView &a, T b)
@ -677,7 +679,7 @@ struct MatView : NonCopyable, NonMovable {
MatT operator*(const MatT &b) const
{
return *this * b.template view();
return *this * b.view();
}
/** Multiply each component by a scalar. */
@ -755,12 +757,12 @@ template<typename T,
struct MutableMatView
: MatView<T, NumCol, NumRow, SrcNumCol, SrcNumRow, SrcStartCol, SrcStartRow, SrcAlignment> {
using MatT = MatBase<T, NumCol, NumRow, SrcAlignment>;
using MatT = MatBase<T, NumCol, NumRow>;
using MatViewT =
MatView<T, NumCol, NumRow, SrcNumCol, SrcNumRow, SrcStartCol, SrcStartRow, SrcAlignment>;
using SrcMatT = MatBase<T, SrcNumCol, SrcNumRow, SrcAlignment>;
using col_type = vec_base<T, NumRow>;
using row_type = vec_base<T, NumCol>;
using col_type = VecBase<T, NumRow>;
using row_type = VecBase<T, NumCol>;
public:
MutableMatView() = delete;
@ -815,7 +817,7 @@ struct MutableMatView
MutableMatView &operator=(const MatT &other)
{
*this = other.template view();
*this = other.view();
return *this;
}
@ -841,7 +843,7 @@ struct MutableMatView
MutableMatView &operator+=(const MatT &b)
{
return *this += b.template view();
return *this += b.view();
}
MutableMatView &operator+=(T b)
@ -870,7 +872,7 @@ struct MutableMatView
MutableMatView &operator-=(const MatT &b)
{
return *this -= b.template view();
return *this -= b.view();
}
MutableMatView &operator-=(T b)
@ -900,7 +902,7 @@ struct MutableMatView
MutableMatView &operator*=(const MatT &b)
{
return *this *= b.template view();
return *this *= b.view();
}
/** Multiply each component by a scalar. */
@ -923,8 +925,8 @@ using float4x4 = MatBase<float, 4, 4>;
/* These types are reserved to wrap C matrices without copy. Note the un-alignment. */
/* TODO: It would be preferable to align all C matrices inside DNA structs. */
using float4x4_view = MatView<float, 4, 4, 4, 4, 0, 0, /* Alignment */ 0>;
using float4x4_mutableview = MutableMatView<float, 4, 4, 4, 4, 0, 0, /* Alignment */ 0>;
using float4x4_view = MatView<float, 4, 4, 4, 4, 0, 0, alignof(float)>;
using float4x4_mutableview = MutableMatView<float, 4, 4, 4, 4, 0, 0, alignof(float)>;
using double2x2 = MatBase<double, 2, 2>;
using double2x3 = MatBase<double, 2, 3>;

View File

@ -20,13 +20,13 @@ namespace blender::math {
* \param cosom: dot product from normalized vectors/quats.
* \param r_w: calculated weights.
*/
template<typename T> inline vec_base<T, 2> interpolate_dot_slerp(const T t, const T cosom)
template<typename T> inline VecBase<T, 2> interpolate_dot_slerp(const T t, const T cosom)
{
const T eps = T(1e-4);
BLI_assert(IN_RANGE_INCL(cosom, T(-1.0001), T(1.0001)));
vec_base<T, 2> w;
VecBase<T, 2> w;
/* Within [-1..1] range, avoid aligned axis. */
if (LIKELY(math::abs(cosom) < (T(1) - eps))) {
const T omega = math::acos(cosom);
@ -48,7 +48,7 @@ inline detail::Quaternion<T> interpolate(const detail::Quaternion<T> &a,
const detail::Quaternion<T> &b,
T t)
{
using Vec4T = vec_base<T, 4>;
using Vec4T = VecBase<T, 4>;
BLI_assert(is_unit_scale(Vec4T(a)));
BLI_assert(is_unit_scale(Vec4T(b)));
@ -60,7 +60,7 @@ inline detail::Quaternion<T> interpolate(const detail::Quaternion<T> &a,
quat = -quat;
}
vec_base<T, 2> w = interpolate_dot_slerp(t, cosom);
VecBase<T, 2> w = interpolate_dot_slerp(t, cosom);
return detail::Quaternion<T>(w[0] * quat + w[1] * Vec4T(b));
}
@ -76,7 +76,7 @@ namespace blender::math::detail {
#ifdef DEBUG
# define BLI_ASSERT_UNIT_QUATERNION(_q) \
{ \
auto rot_vec = static_cast<vec_base<T, 4>>(_q); \
auto rot_vec = static_cast<VecBase<T, 4>>(_q); \
T quat_length = math::length_squared(rot_vec); \
if (!(quat_length == 0 || (math::abs(quat_length - 1) < 0.0001))) { \
std::cout << "Warning! " << __func__ << " called with non-normalized quaternion: size " \
@ -87,7 +87,7 @@ namespace blender::math::detail {
# define BLI_ASSERT_UNIT_QUATERNION(_q)
#endif
template<typename T> AxisAngle<T>::AxisAngle(const vec_base<T, 3> &axis, T angle)
template<typename T> AxisAngle<T>::AxisAngle(const VecBase<T, 3> &axis, T angle)
{
T length;
axis_ = math::normalize_and_get_length(axis, length);
@ -101,7 +101,7 @@ template<typename T> AxisAngle<T>::AxisAngle(const vec_base<T, 3> &axis, T angle
}
}
template<typename T> AxisAngle<T>::AxisAngle(const vec_base<T, 3> &from, const vec_base<T, 3> &to)
template<typename T> AxisAngle<T>::AxisAngle(const VecBase<T, 3> &from, const VecBase<T, 3> &to)
{
BLI_assert(is_unit_scale(from));
BLI_assert(is_unit_scale(to));
@ -124,7 +124,7 @@ template<typename T> AxisAngle<T>::AxisAngle(const vec_base<T, 3> &from, const v
}
}
template<typename T>
AxisAngleNormalized<T>::AxisAngleNormalized(const vec_base<T, 3> &axis, T angle) : AxisAngle<T>()
AxisAngleNormalized<T>::AxisAngleNormalized(const VecBase<T, 3> &axis, T angle) : AxisAngle<T>()
{
BLI_assert(is_unit_scale(axis));
this->axis_ = axis;
@ -183,7 +183,7 @@ template<typename T> Quaternion<T>::operator AxisAngle<T>() const
si = 1.0f;
}
vec_base<T, 3> axis = vec_base<T, 3>(quat.y, quat.z, quat.w) / si;
VecBase<T, 3> axis = VecBase<T, 3>(quat.y, quat.z, quat.w) / si;
if (math::is_zero(axis)) {
axis[1] = 1.0f;
}

View File

@ -6,7 +6,7 @@
* \ingroup bli
*/
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
namespace blender::math {

View File

@ -7,7 +7,7 @@
*/
#include "BLI_math_base.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
namespace blender::math {
@ -16,8 +16,8 @@ namespace detail {
/**
* Rotation Types
*
* It gives more semantic informations allowing overloaded functions based on the rotation
* type. It also prevent implicit cast from rotation to vector types.
* It gives more semantic information allowing overloaded functions based on the rotation type.
* It also prevent implicit cast from rotation to vector types.
*/
/* Forward declaration. */
@ -36,7 +36,7 @@ template<typename T> struct EulerXYZ {
this->z = z;
}
EulerXYZ(const vec_base<T, 3> &vec) : EulerXYZ(UNPACK3(vec)){};
EulerXYZ(const VecBase<T, 3> &vec) : EulerXYZ(UNPACK3(vec)){};
/** Static functions. */
@ -47,7 +47,7 @@ template<typename T> struct EulerXYZ {
/** Conversions. */
explicit operator vec_base<T, 3>() const
explicit operator VecBase<T, 3>() const
{
return {this->x, this->y, this->z};
}
@ -60,7 +60,7 @@ template<typename T> struct EulerXYZ {
friend std::ostream &operator<<(std::ostream &stream, const EulerXYZ &rot)
{
return stream << "EulerXYZ" << static_cast<vec_base<T, 3>>(rot);
return stream << "EulerXYZ" << static_cast<VecBase<T, 3>>(rot);
}
};
@ -77,7 +77,7 @@ template<typename T = float> struct Quaternion {
this->w = w;
}
Quaternion(const vec_base<T, 4> &vec) : Quaternion(UNPACK4(vec)){};
Quaternion(const VecBase<T, 4> &vec) : Quaternion(UNPACK4(vec)){};
/** Static functions. */
@ -88,7 +88,7 @@ template<typename T = float> struct Quaternion {
/** Conversions. */
explicit operator vec_base<T, 4>() const
explicit operator VecBase<T, 4>() const
{
return {this->x, this->y, this->z, this->w};
}
@ -107,12 +107,12 @@ template<typename T = float> struct Quaternion {
friend std::ostream &operator<<(std::ostream &stream, const Quaternion &rot)
{
return stream << "Quaternion" << static_cast<vec_base<T, 4>>(rot);
return stream << "Quaternion" << static_cast<VecBase<T, 4>>(rot);
}
};
template<typename T> struct AxisAngle {
using vec3_type = vec_base<T, 3>;
using vec3_type = VecBase<T, 3>;
protected:
vec3_type axis_ = {0, 1, 0};
@ -207,7 +207,7 @@ template<typename T> struct AxisAngle {
* Implicitly cast back to AxisAngle.
*/
template<typename T> struct AxisAngleNormalized : public AxisAngle<T> {
AxisAngleNormalized(const vec_base<T, 3> &axis, T angle);
AxisAngleNormalized(const VecBase<T, 3> &axis, T angle);
operator AxisAngle<T>() const
{

View File

@ -11,13 +11,16 @@
#include <type_traits>
#include "BLI_math_base.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
#include "BLI_utildefines.h"
namespace blender::math {
template<typename T, int Size> inline bool is_zero(const vec_base<T, Size> &a)
/**
* Returns true if all components are exactly equal to 0.
*/
template<typename T, int Size> [[nodiscard]] inline bool is_zero(const VecBase<T, Size> &a)
{
for (int i = 0; i < Size; i++) {
if (a[i] != T(0)) {
@ -27,7 +30,10 @@ template<typename T, int Size> inline bool is_zero(const vec_base<T, Size> &a)
return true;
}
template<typename T, int Size> inline bool is_any_zero(const vec_base<T, Size> &a)
/**
* Returns true if at least one component is exactly equal to 0.
*/
template<typename T, int Size> [[nodiscard]] inline bool is_any_zero(const VecBase<T, Size> &a)
{
for (int i = 0; i < Size; i++) {
if (a[i] == T(0)) {
@ -37,10 +43,14 @@ template<typename T, int Size> inline bool is_any_zero(const vec_base<T, Size> &
return false;
}
/**
* Returns true if the given vectors are equal within the given epsilon.
* The epsilon is scaled for each component by magnitude of the matching component of `a`.
*/
template<typename T, int Size>
inline bool almost_equal_relative(const vec_base<T, Size> &a,
const vec_base<T, Size> &b,
const T &epsilon_factor)
[[nodiscard]] inline bool almost_equal_relative(const VecBase<T, Size> &a,
const VecBase<T, Size> &b,
const T &epsilon_factor)
{
for (int i = 0; i < Size; i++) {
const float epsilon = epsilon_factor * math::abs(a[i]);
@ -51,9 +61,9 @@ inline bool almost_equal_relative(const vec_base<T, Size> &a,
return true;
}
template<typename T, int Size> inline vec_base<T, Size> abs(const vec_base<T, Size> &a)
template<typename T, int Size> [[nodiscard]] inline VecBase<T, Size> abs(const VecBase<T, Size> &a)
{
vec_base<T, Size> result;
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = a[i] >= 0 ? a[i] : -a[i];
}
@ -61,9 +71,9 @@ template<typename T, int Size> inline vec_base<T, Size> abs(const vec_base<T, Si
}
template<typename T, int Size>
inline vec_base<T, Size> min(const vec_base<T, Size> &a, const vec_base<T, Size> &b)
[[nodiscard]] inline VecBase<T, Size> min(const VecBase<T, Size> &a, const VecBase<T, Size> &b)
{
vec_base<T, Size> result;
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = a[i] < b[i] ? a[i] : b[i];
}
@ -71,9 +81,9 @@ inline vec_base<T, Size> min(const vec_base<T, Size> &a, const vec_base<T, Size>
}
template<typename T, int Size>
inline vec_base<T, Size> max(const vec_base<T, Size> &a, const vec_base<T, Size> &b)
[[nodiscard]] inline VecBase<T, Size> max(const VecBase<T, Size> &a, const VecBase<T, Size> &b)
{
vec_base<T, Size> result;
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = a[i] > b[i] ? a[i] : b[i];
}
@ -81,11 +91,11 @@ inline vec_base<T, Size> max(const vec_base<T, Size> &a, const vec_base<T, Size>
}
template<typename T, int Size>
inline vec_base<T, Size> clamp(const vec_base<T, Size> &a,
const vec_base<T, Size> &min,
const vec_base<T, Size> &max)
[[nodiscard]] inline VecBase<T, Size> clamp(const VecBase<T, Size> &a,
const VecBase<T, Size> &min,
const VecBase<T, Size> &max)
{
vec_base<T, Size> result = a;
VecBase<T, Size> result = a;
for (int i = 0; i < Size; i++) {
result[i] = std::clamp(result[i], min[i], max[i]);
}
@ -93,19 +103,19 @@ inline vec_base<T, Size> clamp(const vec_base<T, Size> &a,
}
template<typename T, int Size>
inline vec_base<T, Size> clamp(const vec_base<T, Size> &a, const T &min, const T &max)
[[nodiscard]] inline VecBase<T, Size> clamp(const VecBase<T, Size> &a, const T &min, const T &max)
{
vec_base<T, Size> result = a;
VecBase<T, Size> result = a;
for (int i = 0; i < Size; i++) {
result[i] = std::clamp(result[i], min, max);
}
return result;
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline vec_base<T, Size> mod(const vec_base<T, Size> &a, const vec_base<T, Size> &b)
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> mod(const VecBase<T, Size> &a, const VecBase<T, Size> &b)
{
vec_base<T, Size> result;
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
BLI_assert(b[i] != 0);
result[i] = std::fmod(a[i], b[i]);
@ -113,34 +123,41 @@ inline vec_base<T, Size> mod(const vec_base<T, Size> &a, const vec_base<T, Size>
return result;
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline vec_base<T, Size> mod(const vec_base<T, Size> &a, const T &b)
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> mod(const VecBase<T, Size> &a, const T &b)
{
BLI_assert(b != 0);
vec_base<T, Size> result;
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = std::fmod(a[i], b);
}
return result;
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline vec_base<T, Size> safe_mod(const vec_base<T, Size> &a, const vec_base<T, Size> &b)
/**
* Safe version of mod(a, b) that returns 0 if b is equal to 0.
*/
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> safe_mod(const VecBase<T, Size> &a,
const VecBase<T, Size> &b)
{
vec_base<T, Size> result;
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = (b[i] != 0) ? std::fmod(a[i], b[i]) : 0;
}
return result;
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline vec_base<T, Size> safe_mod(const vec_base<T, Size> &a, const T &b)
/**
* Safe version of mod(a, b) that returns 0 if b is equal to 0.
*/
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> safe_mod(const VecBase<T, Size> &a, const T &b)
{
if (b == 0) {
return vec_base<T, Size>(0);
return VecBase<T, Size>(0);
}
vec_base<T, Size> result;
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = std::fmod(a[i], b);
}
@ -152,10 +169,11 @@ inline vec_base<T, Size> safe_mod(const vec_base<T, Size> &a, const T &b)
* In other words, it is equivalent to `divide_ceil(a, b) * b`.
* It is undefined if \a a is negative or \b b is not strictly positive.
*/
template<typename T, int Size, BLI_ENABLE_IF((is_math_integral_type<T>))>
inline vec_base<T, Size> ceil_to_multiple(const vec_base<T, Size> &a, const vec_base<T, Size> &b)
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> ceil_to_multiple(const VecBase<T, Size> &a,
const VecBase<T, Size> &b)
{
vec_base<T, Size> result;
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
BLI_assert(a[i] >= 0);
BLI_assert(b[i] > 0);
@ -168,10 +186,11 @@ inline vec_base<T, Size> ceil_to_multiple(const vec_base<T, Size> &a, const vec_
* Integer division that returns the ceiling, instead of flooring like normal C division.
* It is undefined if \a a is negative or \b b is not strictly positive.
*/
template<typename T, int Size, BLI_ENABLE_IF((is_math_integral_type<T>))>
inline vec_base<T, Size> divide_ceil(const vec_base<T, Size> &a, const vec_base<T, Size> &b)
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> divide_ceil(const VecBase<T, Size> &a,
const VecBase<T, Size> &b)
{
vec_base<T, Size> result;
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
BLI_assert(a[i] >= 0);
BLI_assert(b[i] > 0);
@ -181,62 +200,73 @@ inline vec_base<T, Size> divide_ceil(const vec_base<T, Size> &a, const vec_base<
}
template<typename T, int Size>
inline void min_max(const vec_base<T, Size> &vector,
vec_base<T, Size> &min,
vec_base<T, Size> &max)
void min_max(const VecBase<T, Size> &vector, VecBase<T, Size> &min, VecBase<T, Size> &max)
{
min = math::min(vector, min);
max = math::max(vector, max);
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline vec_base<T, Size> safe_divide(const vec_base<T, Size> &a, const vec_base<T, Size> &b)
/**
* Returns 0 if denominator is exactly equal to 0.
*/
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> safe_divide(const VecBase<T, Size> &a,
const VecBase<T, Size> &b)
{
vec_base<T, Size> result;
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = (b[i] == 0) ? 0 : a[i] / b[i];
}
return result;
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline vec_base<T, Size> safe_divide(const vec_base<T, Size> &a, const T &b)
/**
* Returns 0 if denominator is exactly equal to 0.
*/
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> safe_divide(const VecBase<T, Size> &a, const T &b)
{
return (b != 0) ? a / b : vec_base<T, Size>(0.0f);
return (b != 0) ? a / b : VecBase<T, Size>(0.0f);
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline vec_base<T, Size> floor(const vec_base<T, Size> &a)
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> floor(const VecBase<T, Size> &a)
{
vec_base<T, Size> result;
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = std::floor(a[i]);
}
return result;
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline vec_base<T, Size> ceil(const vec_base<T, Size> &a)
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> ceil(const VecBase<T, Size> &a)
{
vec_base<T, Size> result;
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = std::ceil(a[i]);
}
return result;
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline vec_base<T, Size> fract(const vec_base<T, Size> &a)
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> fract(const VecBase<T, Size> &a)
{
vec_base<T, Size> result;
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = a[i] - std::floor(a[i]);
}
return result;
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline T dot(const vec_base<T, Size> &a, const vec_base<T, Size> &b)
/**
* Dot product between two vectors.
* Equivalent to component wise multiplication followed by summation of the result.
* Equivalent to the cosine of the angle between the two vectors if the vectors are normalized.
* \note prefer using `length_manhattan(a)` than `dot(a, vec(1))` to get the sum of all components.
*/
template<typename T, int Size>
[[nodiscard]] inline T dot(const VecBase<T, Size> &a, const VecBase<T, Size> &b)
{
T result = a[0] * b[0];
for (int i = 1; i < Size; i++) {
@ -245,7 +275,10 @@ inline T dot(const vec_base<T, Size> &a, const vec_base<T, Size> &b)
return result;
}
template<typename T, int Size> inline T length_manhattan(const vec_base<T, Size> &a)
/**
* Returns summation of all components.
*/
template<typename T, int Size> [[nodiscard]] inline T length_manhattan(const VecBase<T, Size> &a)
{
T result = std::abs(a[0]);
for (int i = 1; i < Size; i++) {
@ -254,19 +287,18 @@ template<typename T, int Size> inline T length_manhattan(const vec_base<T, Size>
return result;
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline T length_squared(const vec_base<T, Size> &a)
template<typename T, int Size> [[nodiscard]] inline T length_squared(const VecBase<T, Size> &a)
{
return dot(a, a);
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline T length(const vec_base<T, Size> &a)
template<typename T, int Size> [[nodiscard]] inline T length(const VecBase<T, Size> &a)
{
return std::sqrt(length_squared(a));
}
template<typename T, int Size> inline bool is_unit_scale(const vec_base<T, Size> &v)
/** Return true if each individual column is unit scaled. Mainly for assert usage. */
template<typename T, int Size> [[nodiscard]] inline bool is_unit_scale(const VecBase<T, Size> &v)
{
/* Checks are flipped so NAN doesn't assert because we're making sure the value was
* normalized and in the case we don't want NAN to be raising asserts since there
@ -276,56 +308,62 @@ template<typename T, int Size> inline bool is_unit_scale(const vec_base<T, Size>
!(std::abs(test_unit) >= AssertUnitEpsilon<T>::value));
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline T distance_manhattan(const vec_base<T, Size> &a, const vec_base<T, Size> &b)
template<typename T, int Size>
[[nodiscard]] inline T distance_manhattan(const VecBase<T, Size> &a, const VecBase<T, Size> &b)
{
return length_manhattan(a - b);
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline T distance_squared(const vec_base<T, Size> &a, const vec_base<T, Size> &b)
template<typename T, int Size>
[[nodiscard]] inline T distance_squared(const VecBase<T, Size> &a, const VecBase<T, Size> &b)
{
return length_squared(a - b);
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline T distance(const vec_base<T, Size> &a, const vec_base<T, Size> &b)
template<typename T, int Size>
[[nodiscard]] inline T distance(const VecBase<T, Size> &a, const VecBase<T, Size> &b)
{
return length(a - b);
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline vec_base<T, Size> reflect(const vec_base<T, Size> &incident,
const vec_base<T, Size> &normal)
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> reflect(const VecBase<T, Size> &incident,
const VecBase<T, Size> &normal)
{
BLI_assert(is_unit_scale(normal));
return incident - 2.0 * dot(normal, incident) * normal;
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline vec_base<T, Size> refract(const vec_base<T, Size> &incident,
const vec_base<T, Size> &normal,
const T &eta)
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> refract(const VecBase<T, Size> &incident,
const VecBase<T, Size> &normal,
const T &eta)
{
float dot_ni = dot(normal, incident);
float k = 1.0f - eta * eta * (1.0f - dot_ni * dot_ni);
if (k < 0.0f) {
return vec_base<T, Size>(0.0f);
return VecBase<T, Size>(0.0f);
}
return eta * incident - (eta * dot_ni + sqrt(k)) * normal;
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline vec_base<T, Size> project(const vec_base<T, Size> &p, const vec_base<T, Size> &v_proj)
/**
* Project \a p onto \a v_proj .
* Returns zero vector if \a v_proj is degenerate (zero length).
*/
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> project(const VecBase<T, Size> &p,
const VecBase<T, Size> &v_proj)
{
if (UNLIKELY(is_zero(v_proj))) {
return vec_base<T, Size>(0.0f);
return VecBase<T, Size>(0.0f);
}
return v_proj * (dot(p, v_proj) / dot(v_proj, v_proj));
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline vec_base<T, Size> normalize_and_get_length(const vec_base<T, Size> &v, T &out_length)
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> normalize_and_get_length(const VecBase<T, Size> &v,
T &out_length)
{
out_length = length_squared(v);
/* A larger value causes normalize errors in a scaled down models with camera extreme close. */
@ -336,41 +374,56 @@ inline vec_base<T, Size> normalize_and_get_length(const vec_base<T, Size> &v, T
}
/* Either the vector is small or one of it's values contained `nan`. */
out_length = 0.0;
return vec_base<T, Size>(0.0);
return VecBase<T, Size>(0.0);
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline vec_base<T, Size> normalize(const vec_base<T, Size> &v)
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> normalize(const VecBase<T, Size> &v)
{
T len;
return normalize_and_get_length(v, len);
}
template<typename T, BLI_ENABLE_IF((is_math_float_type<T>))>
inline vec_base<T, 3> cross(const vec_base<T, 3> &a, const vec_base<T, 3> &b)
/**
* \return cross perpendicular vector to \a a and \a b.
* \note Return zero vector if \a a and \a b are collinear.
* \note The length of the resulting vector is equal to twice the area of the triangle between \a a
* and \a b ; and it is equal to the sine of the angle between \a a and \a b if they are
* normalized.
* \note Blender 3D space uses right handedness: \a a = thumb, \a b = index, return = middle.
*/
template<typename T>
[[nodiscard]] inline VecBase<T, 3> cross(const VecBase<T, 3> &a, const VecBase<T, 3> &b)
{
return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x};
}
inline vec_base<float, 3> cross_high_precision(const vec_base<float, 3> &a,
const vec_base<float, 3> &b)
/**
* Same as `cross(a, b)` but use double float precision for the computation.
*/
[[nodiscard]] inline VecBase<float, 3> cross_high_precision(const VecBase<float, 3> &a,
const VecBase<float, 3> &b)
{
return {float(double(a.y) * double(b.z) - double(a.z) * double(b.y)),
float(double(a.z) * double(b.x) - double(a.x) * double(b.z)),
float(double(a.x) * double(b.y) - double(a.y) * double(b.x))};
}
template<typename T, BLI_ENABLE_IF((is_math_float_type<T>))>
inline vec_base<T, 3> cross_poly(Span<vec_base<T, 3>> poly)
/**
* \param poly: Array of points around a polygon. They don't have to be co-planar.
* \return Best fit plane normal for the given polygon loop or zero vector if point
* array is too short. Not normalized.
*/
template<typename T> [[nodiscard]] inline VecBase<T, 3> cross_poly(Span<VecBase<T, 3>> poly)
{
/* Newell's Method. */
int nv = int(poly.size());
if (nv < 3) {
return vec_base<T, 3>(0, 0, 0);
return VecBase<T, 3>(0, 0, 0);
}
const vec_base<T, 3> *v_prev = &poly[nv - 1];
const vec_base<T, 3> *v_curr = &poly[0];
vec_base<T, 3> n(0, 0, 0);
const VecBase<T, 3> *v_prev = &poly[nv - 1];
const VecBase<T, 3> *v_curr = &poly[0];
VecBase<T, 3> n(0, 0, 0);
for (int i = 0; i < nv;) {
n[0] = n[0] + ((*v_prev)[1] - (*v_curr)[1]) * ((*v_prev)[2] + (*v_curr)[2]);
n[1] = n[1] + ((*v_prev)[2] - (*v_curr)[2]) * ((*v_prev)[0] + (*v_curr)[0]);
@ -384,16 +437,25 @@ inline vec_base<T, 3> cross_poly(Span<vec_base<T, 3>> poly)
return n;
}
template<typename T, typename FactorT, int Size, BLI_ENABLE_IF((is_math_float_type<FactorT>))>
inline vec_base<T, Size> interpolate(const vec_base<T, Size> &a,
const vec_base<T, Size> &b,
const FactorT &t)
/**
* Per component linear interpolation.
* \param t: interpolation factor. Return \a a if equal 0. Return \a b if equal 1.
* Outside of [0..1] range, use linear extrapolation.
*/
template<typename T, typename FactorT, int Size>
[[nodiscard]] inline VecBase<T, Size> interpolate(const VecBase<T, Size> &a,
const VecBase<T, Size> &b,
const FactorT &t)
{
return a * (1 - t) + b * t;
}
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline vec_base<T, Size> midpoint(const vec_base<T, Size> &a, const vec_base<T, Size> &b)
/**
* \return Point halfway between \a a and \a b.
*/
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> midpoint(const VecBase<T, Size> &a,
const VecBase<T, Size> &b)
{
return (a + b) * 0.5;
}
@ -401,17 +463,20 @@ inline vec_base<T, Size> midpoint(const vec_base<T, Size> &a, const vec_base<T,
/**
* Return `vector` if `incident` and `reference` are pointing in the same direction.
*/
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
inline vec_base<T, Size> faceforward(const vec_base<T, Size> &vector,
const vec_base<T, Size> &incident,
const vec_base<T, Size> &reference)
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> faceforward(const VecBase<T, Size> &vector,
const VecBase<T, Size> &incident,
const VecBase<T, Size> &reference)
{
return (dot(reference, incident) < 0) ? vector : -vector;
}
template<typename T> inline int dominant_axis(const vec_base<T, 3> &a)
/**
* \return Index of the component with the greatest magnitude.
*/
template<typename T> [[nodiscard]] inline int dominant_axis(const VecBase<T, 3> &a)
{
vec_base<T, 3> b = abs(a);
VecBase<T, 3> b = abs(a);
return ((b.x > b.y) ? ((b.x > b.z) ? 0 : 2) : ((b.y > b.z) ? 1 : 2));
}
@ -420,7 +485,7 @@ template<typename T> inline int dominant_axis(const vec_base<T, 3> &a)
* \note Returned vector can be in any perpendicular direction.
* \note Returned vector might not the same length as \a v.
*/
template<typename T> inline vec_base<T, 3> orthogonal(const vec_base<T, 3> &v)
template<typename T> [[nodiscard]] inline VecBase<T, 3> orthogonal(const VecBase<T, 3> &v)
{
const int axis = dominant_axis(v);
switch (axis) {
@ -438,16 +503,21 @@ template<typename T> inline vec_base<T, 3> orthogonal(const vec_base<T, 3> &v)
* Calculates a perpendicular vector to \a v.
* \note Returned vector can be in any perpendicular direction.
*/
template<typename T> inline vec_base<T, 2> orthogonal(const vec_base<T, 2> &v)
template<typename T> [[nodiscard]] inline VecBase<T, 2> orthogonal(const VecBase<T, 2> &v)
{
return {-v.y, v.x};
}
/**
* Returns true if vectors are equal within the given epsilon.
*/
template<typename T, int Size>
inline bool compare(const vec_base<T, Size> &a, const vec_base<T, Size> &b, const T limit)
[[nodiscard]] inline bool is_equal(const VecBase<T, Size> &a,
const VecBase<T, Size> &b,
const T epsilon = T(0))
{
for (int i = 0; i < Size; i++) {
if (std::abs(a[i] - b[i]) > limit) {
if (std::abs(a[i] - b[i]) > epsilon) {
return false;
}
}
@ -466,10 +536,10 @@ template<typename T> struct isect_result {
typename T::base_type lambda;
};
template<typename T, int Size, BLI_ENABLE_IF((is_math_float_type<T>))>
isect_result<vec_base<T, Size>> isect_seg_seg(const vec_base<T, Size> &v1,
const vec_base<T, Size> &v2,
const vec_base<T, Size> &v3,
const vec_base<T, Size> &v4);
template<typename T, int Size>
[[nodiscard]] isect_result<VecBase<T, Size>> isect_seg_seg(const VecBase<T, Size> &v1,
const VecBase<T, Size> &v2,
const VecBase<T, Size> &v3,
const VecBase<T, Size> &v4);
} // namespace blender::math

View File

@ -14,8 +14,8 @@
namespace blender {
using mpq2 = vec_base<mpq_class, 2>;
using mpq3 = vec_base<mpq_class, 3>;
using mpq2 = VecBase<mpq_class, 2>;
using mpq3 = VecBase<mpq_class, 3>;
namespace math {

View File

@ -77,16 +77,16 @@ template<typename T> uint64_t vector_hash(const T &vec)
} // namespace math
template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size> {
template<typename T, int Size> struct VecBase : public vec_struct_base<T, Size> {
static constexpr int type_length = Size;
using base_type = T;
using uint_type = vec_base<as_uint_type<T>, Size>;
using uint_type = VecBase<as_uint_type<T>, Size>;
vec_base() = default;
VecBase() = default;
explicit vec_base(T value)
explicit VecBase(T value)
{
for (int i = 0; i < Size; i++) {
(*this)[i] = value;
@ -94,27 +94,27 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size>
}
template<typename U, BLI_ENABLE_IF((std::is_convertible_v<U, T>))>
explicit vec_base(U value) : vec_base(T(value))
explicit VecBase(U value) : VecBase(T(value))
{
}
/* Workaround issue with template BLI_ENABLE_IF((Size == 2)) not working. */
#define BLI_ENABLE_IF_VEC(_size, _test) int S = _size, BLI_ENABLE_IF((S _test))
template<BLI_ENABLE_IF_VEC(Size, == 2)> vec_base(T _x, T _y)
template<BLI_ENABLE_IF_VEC(Size, == 2)> VecBase(T _x, T _y)
{
(*this)[0] = _x;
(*this)[1] = _y;
}
template<BLI_ENABLE_IF_VEC(Size, == 3)> vec_base(T _x, T _y, T _z)
template<BLI_ENABLE_IF_VEC(Size, == 3)> VecBase(T _x, T _y, T _z)
{
(*this)[0] = _x;
(*this)[1] = _y;
(*this)[2] = _z;
}
template<BLI_ENABLE_IF_VEC(Size, == 4)> vec_base(T _x, T _y, T _z, T _w)
template<BLI_ENABLE_IF_VEC(Size, == 4)> VecBase(T _x, T _y, T _z, T _w)
{
(*this)[0] = _x;
(*this)[1] = _y;
@ -125,49 +125,49 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size>
/** Mixed scalar-vector constructors. */
template<typename U, BLI_ENABLE_IF_VEC(Size, == 3)>
constexpr vec_base(const vec_base<U, 2> &xy, T z) : vec_base(T(xy.x), T(xy.y), z)
constexpr VecBase(const VecBase<U, 2> &xy, T z) : VecBase(T(xy.x), T(xy.y), z)
{
}
template<typename U, BLI_ENABLE_IF_VEC(Size, == 3)>
constexpr vec_base(T x, const vec_base<U, 2> &yz) : vec_base(x, T(yz.x), T(yz.y))
constexpr VecBase(T x, const VecBase<U, 2> &yz) : VecBase(x, T(yz.x), T(yz.y))
{
}
template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)>
vec_base(vec_base<U, 3> xyz, T w) : vec_base(T(xyz.x), T(xyz.y), T(xyz.z), T(w))
VecBase(VecBase<U, 3> xyz, T w) : VecBase(T(xyz.x), T(xyz.y), T(xyz.z), T(w))
{
}
template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)>
vec_base(T x, vec_base<U, 3> yzw) : vec_base(T(x), T(yzw.x), T(yzw.y), T(yzw.z))
VecBase(T x, VecBase<U, 3> yzw) : VecBase(T(x), T(yzw.x), T(yzw.y), T(yzw.z))
{
}
template<typename U, typename V, BLI_ENABLE_IF_VEC(Size, == 4)>
vec_base(vec_base<U, 2> xy, vec_base<V, 2> zw) : vec_base(T(xy.x), T(xy.y), T(zw.x), T(zw.y))
VecBase(VecBase<U, 2> xy, VecBase<V, 2> zw) : VecBase(T(xy.x), T(xy.y), T(zw.x), T(zw.y))
{
}
template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)>
vec_base(vec_base<U, 2> xy, T z, T w) : vec_base(T(xy.x), T(xy.y), T(z), T(w))
VecBase(VecBase<U, 2> xy, T z, T w) : VecBase(T(xy.x), T(xy.y), T(z), T(w))
{
}
template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)>
vec_base(T x, vec_base<U, 2> yz, T w) : vec_base(T(x), T(yz.x), T(yz.y), T(w))
VecBase(T x, VecBase<U, 2> yz, T w) : VecBase(T(x), T(yz.x), T(yz.y), T(w))
{
}
template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)>
vec_base(T x, T y, vec_base<U, 2> zw) : vec_base(T(x), T(y), T(zw.x), T(zw.y))
VecBase(T x, T y, VecBase<U, 2> zw) : VecBase(T(x), T(y), T(zw.x), T(zw.y))
{
}
/** Masking. */
template<typename U, int OtherSize, BLI_ENABLE_IF(OtherSize > Size)>
explicit vec_base(const vec_base<U, OtherSize> &other)
explicit VecBase(const VecBase<U, OtherSize> &other)
{
for (int i = 0; i < Size; i++) {
(*this)[i] = T(other[i]);
@ -178,24 +178,23 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size>
/** Conversion from pointers (from C-style vectors). */
vec_base(const T *ptr)
VecBase(const T *ptr)
{
unroll<Size>([&](auto i) { (*this)[i] = ptr[i]; });
}
template<typename U, BLI_ENABLE_IF((std::is_convertible_v<U, T>))>
explicit vec_base(const U *ptr)
template<typename U, BLI_ENABLE_IF((std::is_convertible_v<U, T>))> explicit VecBase(const U *ptr)
{
unroll<Size>([&](auto i) { (*this)[i] = ptr[i]; });
}
vec_base(const T (*ptr)[Size]) : vec_base(static_cast<const T *>(ptr[0]))
VecBase(const T (*ptr)[Size]) : VecBase(static_cast<const T *>(ptr[0]))
{
}
/** Conversion from other vector types. */
template<typename U> explicit vec_base(const vec_base<U, Size> &vec)
template<typename U> explicit VecBase(const VecBase<U, Size> &vec)
{
unroll<Size>([&](auto i) { (*this)[i] = T(vec[i]); });
}
@ -234,144 +233,144 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size>
/** Arithmetic operators. */
friend vec_base operator+(const vec_base &a, const vec_base &b)
friend VecBase operator+(const VecBase &a, const VecBase &b)
{
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] + b[i]; });
return result;
}
friend vec_base operator+(const vec_base &a, const T &b)
friend VecBase operator+(const VecBase &a, const T &b)
{
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] + b; });
return result;
}
friend vec_base operator+(const T &a, const vec_base &b)
friend VecBase operator+(const T &a, const VecBase &b)
{
return b + a;
}
vec_base &operator+=(const vec_base &b)
VecBase &operator+=(const VecBase &b)
{
unroll<Size>([&](auto i) { (*this)[i] += b[i]; });
return *this;
}
vec_base &operator+=(const T &b)
VecBase &operator+=(const T &b)
{
unroll<Size>([&](auto i) { (*this)[i] += b; });
return *this;
}
friend vec_base operator-(const vec_base &a)
friend VecBase operator-(const VecBase &a)
{
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = -a[i]; });
return result;
}
friend vec_base operator-(const vec_base &a, const vec_base &b)
friend VecBase operator-(const VecBase &a, const VecBase &b)
{
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] - b[i]; });
return result;
}
friend vec_base operator-(const vec_base &a, const T &b)
friend VecBase operator-(const VecBase &a, const T &b)
{
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] - b; });
return result;
}
friend vec_base operator-(const T &a, const vec_base &b)
friend VecBase operator-(const T &a, const VecBase &b)
{
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a - b[i]; });
return result;
}
vec_base &operator-=(const vec_base &b)
VecBase &operator-=(const VecBase &b)
{
unroll<Size>([&](auto i) { (*this)[i] -= b[i]; });
return *this;
}
vec_base &operator-=(const T &b)
VecBase &operator-=(const T &b)
{
unroll<Size>([&](auto i) { (*this)[i] -= b; });
return *this;
}
friend vec_base operator*(const vec_base &a, const vec_base &b)
friend VecBase operator*(const VecBase &a, const VecBase &b)
{
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] * b[i]; });
return result;
}
template<typename FactorT> friend vec_base operator*(const vec_base &a, FactorT b)
template<typename FactorT> friend VecBase operator*(const VecBase &a, FactorT b)
{
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] * b; });
return result;
}
friend vec_base operator*(T a, const vec_base &b)
friend VecBase operator*(T a, const VecBase &b)
{
return b * a;
}
vec_base &operator*=(T b)
VecBase &operator*=(T b)
{
unroll<Size>([&](auto i) { (*this)[i] *= b; });
return *this;
}
vec_base &operator*=(const vec_base &b)
VecBase &operator*=(const VecBase &b)
{
unroll<Size>([&](auto i) { (*this)[i] *= b[i]; });
return *this;
}
friend vec_base operator/(const vec_base &a, const vec_base &b)
friend VecBase operator/(const VecBase &a, const VecBase &b)
{
for (int i = 0; i < Size; i++) {
BLI_assert(b[i] != T(0));
}
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] / b[i]; });
return result;
}
friend vec_base operator/(const vec_base &a, T b)
friend VecBase operator/(const VecBase &a, T b)
{
BLI_assert(b != T(0));
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] / b; });
return result;
}
friend vec_base operator/(T a, const vec_base &b)
friend VecBase operator/(T a, const VecBase &b)
{
for (int i = 0; i < Size; i++) {
BLI_assert(b[i] != T(0));
}
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a / b[i]; });
return result;
}
vec_base &operator/=(T b)
VecBase &operator/=(T b)
{
BLI_assert(b != T(0));
unroll<Size>([&](auto i) { (*this)[i] /= b; });
return *this;
}
vec_base &operator/=(const vec_base &b)
VecBase &operator/=(const VecBase &b)
{
BLI_assert(b != T(0));
unroll<Size>([&](auto i) { (*this)[i] /= b[i]; });
@ -380,155 +379,155 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size>
/** Binary operators. */
BLI_INT_OP(T) friend vec_base operator&(const vec_base &a, const vec_base &b)
BLI_INT_OP(T) friend VecBase operator&(const VecBase &a, const VecBase &b)
{
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] & b[i]; });
return result;
}
BLI_INT_OP(T) friend vec_base operator&(const vec_base &a, T b)
BLI_INT_OP(T) friend VecBase operator&(const VecBase &a, T b)
{
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] & b; });
return result;
}
BLI_INT_OP(T) friend vec_base operator&(T a, const vec_base &b)
BLI_INT_OP(T) friend VecBase operator&(T a, const VecBase &b)
{
return b & a;
}
BLI_INT_OP(T) vec_base &operator&=(T b)
BLI_INT_OP(T) VecBase &operator&=(T b)
{
unroll<Size>([&](auto i) { (*this)[i] &= b; });
return *this;
}
BLI_INT_OP(T) vec_base &operator&=(const vec_base &b)
BLI_INT_OP(T) VecBase &operator&=(const VecBase &b)
{
unroll<Size>([&](auto i) { (*this)[i] &= b[i]; });
return *this;
}
BLI_INT_OP(T) friend vec_base operator|(const vec_base &a, const vec_base &b)
BLI_INT_OP(T) friend VecBase operator|(const VecBase &a, const VecBase &b)
{
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] | b[i]; });
return result;
}
BLI_INT_OP(T) friend vec_base operator|(const vec_base &a, T b)
BLI_INT_OP(T) friend VecBase operator|(const VecBase &a, T b)
{
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] | b; });
return result;
}
BLI_INT_OP(T) friend vec_base operator|(T a, const vec_base &b)
BLI_INT_OP(T) friend VecBase operator|(T a, const VecBase &b)
{
return b | a;
}
BLI_INT_OP(T) vec_base &operator|=(T b)
BLI_INT_OP(T) VecBase &operator|=(T b)
{
unroll<Size>([&](auto i) { (*this)[i] |= b; });
return *this;
}
BLI_INT_OP(T) vec_base &operator|=(const vec_base &b)
BLI_INT_OP(T) VecBase &operator|=(const VecBase &b)
{
unroll<Size>([&](auto i) { (*this)[i] |= b[i]; });
return *this;
}
BLI_INT_OP(T) friend vec_base operator^(const vec_base &a, const vec_base &b)
BLI_INT_OP(T) friend VecBase operator^(const VecBase &a, const VecBase &b)
{
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] ^ b[i]; });
return result;
}
BLI_INT_OP(T) friend vec_base operator^(const vec_base &a, T b)
BLI_INT_OP(T) friend VecBase operator^(const VecBase &a, T b)
{
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] ^ b; });
return result;
}
BLI_INT_OP(T) friend vec_base operator^(T a, const vec_base &b)
BLI_INT_OP(T) friend VecBase operator^(T a, const VecBase &b)
{
return b ^ a;
}
BLI_INT_OP(T) vec_base &operator^=(T b)
BLI_INT_OP(T) VecBase &operator^=(T b)
{
unroll<Size>([&](auto i) { (*this)[i] ^= b; });
return *this;
}
BLI_INT_OP(T) vec_base &operator^=(const vec_base &b)
BLI_INT_OP(T) VecBase &operator^=(const VecBase &b)
{
unroll<Size>([&](auto i) { (*this)[i] ^= b[i]; });
return *this;
}
BLI_INT_OP(T) friend vec_base operator~(const vec_base &a)
BLI_INT_OP(T) friend VecBase operator~(const VecBase &a)
{
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = ~a[i]; });
return result;
}
/** Bit-shift operators. */
BLI_INT_OP(T) friend vec_base operator<<(const vec_base &a, const vec_base &b)
BLI_INT_OP(T) friend VecBase operator<<(const VecBase &a, const VecBase &b)
{
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] << b[i]; });
return result;
}
BLI_INT_OP(T) friend vec_base operator<<(const vec_base &a, T b)
BLI_INT_OP(T) friend VecBase operator<<(const VecBase &a, T b)
{
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] << b; });
return result;
}
BLI_INT_OP(T) vec_base &operator<<=(T b)
BLI_INT_OP(T) VecBase &operator<<=(T b)
{
unroll<Size>([&](auto i) { (*this)[i] <<= b; });
return *this;
}
BLI_INT_OP(T) vec_base &operator<<=(const vec_base &b)
BLI_INT_OP(T) VecBase &operator<<=(const VecBase &b)
{
unroll<Size>([&](auto i) { (*this)[i] <<= b[i]; });
return *this;
}
BLI_INT_OP(T) friend vec_base operator>>(const vec_base &a, const vec_base &b)
BLI_INT_OP(T) friend VecBase operator>>(const VecBase &a, const VecBase &b)
{
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] >> b[i]; });
return result;
}
BLI_INT_OP(T) friend vec_base operator>>(const vec_base &a, T b)
BLI_INT_OP(T) friend VecBase operator>>(const VecBase &a, T b)
{
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] >> b; });
return result;
}
BLI_INT_OP(T) vec_base &operator>>=(T b)
BLI_INT_OP(T) VecBase &operator>>=(T b)
{
unroll<Size>([&](auto i) { (*this)[i] >>= b; });
return *this;
}
BLI_INT_OP(T) vec_base &operator>>=(const vec_base &b)
BLI_INT_OP(T) VecBase &operator>>=(const VecBase &b)
{
unroll<Size>([&](auto i) { (*this)[i] >>= b[i]; });
return *this;
@ -536,28 +535,28 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size>
/** Modulo operators. */
BLI_INT_OP(T) friend vec_base operator%(const vec_base &a, const vec_base &b)
BLI_INT_OP(T) friend VecBase operator%(const VecBase &a, const VecBase &b)
{
for (int i = 0; i < Size; i++) {
BLI_assert(b[i] != T(0));
}
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] % b[i]; });
return result;
}
BLI_INT_OP(T) friend vec_base operator%(const vec_base &a, T b)
BLI_INT_OP(T) friend VecBase operator%(const VecBase &a, T b)
{
BLI_assert(b != 0);
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a[i] % b; });
return result;
}
BLI_INT_OP(T) friend vec_base operator%(T a, const vec_base &b)
BLI_INT_OP(T) friend VecBase operator%(T a, const VecBase &b)
{
BLI_assert(b != T(0));
vec_base result;
VecBase result;
unroll<Size>([&](auto i) { result[i] = a % b[i]; });
return result;
}
@ -566,7 +565,7 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size>
/** Compare. */
friend bool operator==(const vec_base &a, const vec_base &b)
friend bool operator==(const VecBase &a, const VecBase &b)
{
for (int i = 0; i < Size; i++) {
if (a[i] != b[i]) {
@ -576,7 +575,7 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size>
return true;
}
friend bool operator!=(const vec_base &a, const vec_base &b)
friend bool operator!=(const VecBase &a, const VecBase &b)
{
return !(a == b);
}
@ -588,7 +587,7 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size>
return math::vector_hash(*this);
}
friend std::ostream &operator<<(std::ostream &stream, const vec_base &v)
friend std::ostream &operator<<(std::ostream &stream, const VecBase &v)
{
stream << "(";
for (int i = 0; i < Size; i++) {
@ -611,32 +610,32 @@ template<typename T> struct AssertUnitEpsilon {
} // namespace math
using char3 = blender::vec_base<int8_t, 3>;
using char3 = blender::VecBase<int8_t, 3>;
using uchar3 = blender::vec_base<uint8_t, 3>;
using uchar4 = blender::vec_base<uint8_t, 4>;
using uchar3 = blender::VecBase<uint8_t, 3>;
using uchar4 = blender::VecBase<uint8_t, 4>;
using int2 = vec_base<int32_t, 2>;
using int3 = vec_base<int32_t, 3>;
using int4 = vec_base<int32_t, 4>;
using int2 = VecBase<int32_t, 2>;
using int3 = VecBase<int32_t, 3>;
using int4 = VecBase<int32_t, 4>;
using uint2 = vec_base<uint32_t, 2>;
using uint3 = vec_base<uint32_t, 3>;
using uint4 = vec_base<uint32_t, 4>;
using uint2 = VecBase<uint32_t, 2>;
using uint3 = VecBase<uint32_t, 3>;
using uint4 = VecBase<uint32_t, 4>;
using short2 = blender::vec_base<int16_t, 2>;
using short3 = blender::vec_base<int16_t, 3>;
using short2 = blender::VecBase<int16_t, 2>;
using short3 = blender::VecBase<int16_t, 3>;
using ushort2 = vec_base<uint16_t, 2>;
using ushort3 = blender::vec_base<uint16_t, 3>;
using ushort4 = blender::vec_base<uint16_t, 4>;
using ushort2 = VecBase<uint16_t, 2>;
using ushort3 = blender::VecBase<uint16_t, 3>;
using ushort4 = blender::VecBase<uint16_t, 4>;
using float2 = vec_base<float, 2>;
using float3 = vec_base<float, 3>;
using float4 = vec_base<float, 4>;
using float2 = VecBase<float, 2>;
using float3 = VecBase<float, 3>;
using float4 = VecBase<float, 4>;
using double2 = vec_base<double, 2>;
using double3 = vec_base<double, 3>;
using double4 = vec_base<double, 4>;
using double2 = VecBase<double, 2>;
using double3 = VecBase<double, 3>;
using double4 = VecBase<double, 4>;
} // namespace blender

View File

@ -17,8 +17,8 @@
# include "BLI_index_range.hh"
# include "BLI_map.hh"
# include "BLI_math_mpq.hh"
# include "BLI_math_vec_mpq_types.hh"
# include "BLI_math_vec_types.hh"
# include "BLI_math_vector_mpq_types.hh"
# include "BLI_math_vector_types.hh"
# include "BLI_span.hh"
# include "BLI_utility_mixins.hh"
# include "BLI_vector.hh"

View File

@ -2,7 +2,7 @@
#pragma once
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
namespace blender::noise {

View File

@ -7,7 +7,7 @@
#pragma once
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
#include "BLI_utildefines.h"

View File

@ -27,6 +27,7 @@
#include "BLI_any.hh"
#include "BLI_array.hh"
#include "BLI_devirtualize_parameters.hh"
#include "BLI_index_mask.hh"
#include "BLI_span.hh"
@ -1312,4 +1313,68 @@ template<typename T> class SingleAsSpan {
}
};
/** To be used with #call_with_devirtualized_parameters. */
template<typename T, bool UseSingle, bool UseSpan> struct VArrayDevirtualizer {
const VArray<T> &varray;
template<typename Fn> bool devirtualize(const Fn &fn) const
{
const CommonVArrayInfo info = this->varray.common_info();
const int64_t size = this->varray.size();
if constexpr (UseSingle) {
if (info.type == CommonVArrayInfo::Type::Single) {
return fn(SingleAsSpan<T>(*static_cast<const T *>(info.data), size));
}
}
if constexpr (UseSpan) {
if (info.type == CommonVArrayInfo::Type::Span) {
return fn(Span<T>(static_cast<const T *>(info.data), size));
}
}
return false;
}
};
/**
* Generate multiple versions of the given function optimized for different virtual arrays.
* One has to be careful with nesting multiple devirtualizations, because that results in an
* exponential number of function instantiations (increasing compile time and binary size).
*
* Generally, this function should only be used when the virtual method call overhead to get an
* element from a virtual array is significant.
*/
template<typename T, typename Func>
inline void devirtualize_varray(const VArray<T> &varray, const Func &func, bool enable = true)
{
if (enable) {
if (call_with_devirtualized_parameters(
std::make_tuple(VArrayDevirtualizer<T, true, true>{varray}), func)) {
return;
}
}
func(varray);
}
/**
* Same as `devirtualize_varray`, but devirtualizes two virtual arrays at the same time.
* This is better than nesting two calls to `devirtualize_varray`, because it instantiates fewer
* cases.
*/
template<typename T1, typename T2, typename Func>
inline void devirtualize_varray2(const VArray<T1> &varray1,
const VArray<T2> &varray2,
const Func &func,
bool enable = true)
{
if (enable) {
if (call_with_devirtualized_parameters(
std::make_tuple(VArrayDevirtualizer<T1, true, true>{varray1},
VArrayDevirtualizer<T2, true, true>{varray2}),
func)) {
return;
}
}
func(varray1, varray2);
}
} // namespace blender

View File

@ -278,8 +278,8 @@ set(SRC
BLI_math_solvers.h
BLI_math_statistics.h
BLI_math_time.h
BLI_math_vec_mpq_types.hh
BLI_math_vec_types.hh
BLI_math_vector_mpq_types.hh
BLI_math_vector_types.hh
BLI_math_vector.h
BLI_math_vector.hh
BLI_memarena.h
@ -492,7 +492,7 @@ if(WITH_GTESTS)
tests/BLI_math_rotation_test.cc
tests/BLI_math_solvers_test.cc
tests/BLI_math_time_test.cc
tests/BLI_math_vec_types_test.cc
tests/BLI_math_vector_types_test.cc
tests/BLI_math_vector_test.cc
tests/BLI_memiter_test.cc
tests/BLI_memory_utils_test.cc

View File

@ -4,7 +4,7 @@
#include "BLI_cpp_type_make.hh"
#include "BLI_cpp_types_make.hh"
#include "BLI_float4x4.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
namespace blender {

View File

@ -14,7 +14,7 @@
#include "BLI_linklist.h"
#include "BLI_math_boolean.hh"
#include "BLI_math_mpq.hh"
#include "BLI_math_vec_mpq_types.hh"
#include "BLI_math_vector_mpq_types.hh"
#include "BLI_set.hh"
#include "BLI_task.hh"
#include "BLI_vector.hh"

View File

@ -140,7 +140,7 @@ void BLI_listbase_swaplinks(ListBase *listbase, void *vlinka, void *vlinkb)
}
if (linkb->next == linka) {
SWAP(Link *, linka, linkb);
std::swap(linka, linkb);
}
if (linka->next == linkb) {
@ -150,8 +150,8 @@ void BLI_listbase_swaplinks(ListBase *listbase, void *vlinka, void *vlinkb)
linkb->next = linka;
}
else { /* Non-contiguous items, we can safely swap. */
SWAP(Link *, linka->prev, linkb->prev);
SWAP(Link *, linka->next, linkb->next);
std::swap(linka->prev, linkb->prev);
std::swap(linka->next, linkb->next);
}
/* Update neighbors of linka and linkb. */

View File

@ -7,7 +7,7 @@
#include "BLI_hash.hh"
#include "BLI_math_boolean.hh"
#include "BLI_math_mpq.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
#include "BLI_utildefines.h"

View File

@ -214,7 +214,7 @@ MatBase<T, Size, Size> pseudo_invert(const MatBase<T, Size, Size> &mat, T epsilo
* of `A` as `Ainv = V.Winv.transpose(U)`.
*/
MatBase<T, Size, Size> U, W, V;
vec_base<T, Size> S_val;
VecBase<T, Size> S_val;
{
using namespace Eigen;
@ -274,7 +274,7 @@ static void polar_decompose(const MatBase<T, 3, 3> &mat3,
* P = VSV*
*/
MatBase<T, 3, 3> W, V;
vec_base<T, 3> S_val;
VecBase<T, 3> S_val;
{
using namespace Eigen;

View File

@ -5,8 +5,8 @@
*/
#include "BLI_hash.hh"
#include "BLI_math_vec_mpq_types.hh"
#include "BLI_math_vector.hh"
#include "BLI_math_vector_mpq_types.hh"
#include "BLI_span.hh"
#include "BLI_utildefines.h"

View File

@ -21,8 +21,8 @@
# include "BLI_math_boolean.hh"
# include "BLI_math_geom.h"
# include "BLI_math_mpq.hh"
# include "BLI_math_vec_mpq_types.hh"
# include "BLI_math_vector.hh"
# include "BLI_math_vector_mpq_types.hh"
# include "BLI_mesh_intersect.hh"
# include "BLI_set.hh"
# include "BLI_span.hh"

View File

@ -21,9 +21,9 @@
# include "BLI_map.hh"
# include "BLI_math_boolean.hh"
# include "BLI_math_mpq.hh"
# include "BLI_math_vec_mpq_types.hh"
# include "BLI_math_vec_types.hh"
# include "BLI_math_vector.h"
# include "BLI_math_vector_mpq_types.hh"
# include "BLI_math_vector_types.hh"
# include "BLI_polyfill_2d.h"
# include "BLI_set.hh"
# include "BLI_sort.hh"

View File

@ -23,7 +23,7 @@ extern "C" {
#include "BLI_array.hh"
#include "BLI_math_boolean.hh"
#include "BLI_math_mpq.hh"
#include "BLI_math_vec_mpq_types.hh"
#include "BLI_math_vector_mpq_types.hh"
#include "BLI_vector.hh"
#include "BLI_delaunay_2d.h"

View File

@ -4,7 +4,7 @@
#include "BLI_float3x3.hh"
#include "BLI_math_base.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
namespace blender::tests {

View File

@ -221,7 +221,7 @@ static void test_sin_cos_from_fraction_symmetry(const int range)
sin_cos_fl[0] = fabsf(sin_cos_fl[0]);
sin_cos_fl[1] = fabsf(sin_cos_fl[1]);
if (sin_cos_fl[0] > sin_cos_fl[1]) {
SWAP(float, sin_cos_fl[0], sin_cos_fl[1]);
std::swap(sin_cos_fl[0], sin_cos_fl[1]);
}
break;
}

View File

@ -2,7 +2,7 @@
#include "testing/testing.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
namespace blender::tests {

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: Apache-2.0 */
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_memory_utils.hh"
#include "BLI_strict_flags.h"
#include "testing/testing.h"

View File

@ -11,7 +11,7 @@
#include "BLI_array.hh"
#include "BLI_map.hh"
#include "BLI_math_mpq.hh"
#include "BLI_math_vec_mpq_types.hh"
#include "BLI_math_vector_mpq_types.hh"
#include "BLI_mesh_boolean.hh"
#include "BLI_vector.hh"

View File

@ -10,7 +10,7 @@
#include "BLI_array.hh"
#include "BLI_math_mpq.hh"
#include "BLI_math_vec_mpq_types.hh"
#include "BLI_math_vector_mpq_types.hh"
#include "BLI_mesh_intersect.hh"
#include "BLI_task.h"
#include "BLI_vector.hh"

View File

@ -724,13 +724,15 @@ static BHeadN *get_bhead(FileData *fd)
new_bhead->has_data = false;
new_bhead->is_memchunk_identical = false;
new_bhead->bhead = bhead;
off64_t seek_new = fd->file->seek(fd->file, bhead.len, SEEK_CUR);
if (seek_new == -1) {
const off64_t seek_new = fd->file->seek(fd->file, bhead.len, SEEK_CUR);
if (UNLIKELY(seek_new == -1)) {
fd->is_eof = true;
MEM_freeN(new_bhead);
new_bhead = nullptr;
}
BLI_assert(fd->file->offset == seek_new);
else {
BLI_assert(fd->file->offset == seek_new);
}
}
else {
fd->is_eof = true;

View File

@ -15,7 +15,7 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_string.h"
#include "BLI_system.h"
#include "BLI_utildefines.h"

Some files were not shown because too many files have changed in this diff Show More