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

This commit is contained in:
Hans Goudey 2022-12-08 12:39:18 -06:00
commit a9b193f663
89 changed files with 1562 additions and 846 deletions

View File

@ -201,11 +201,11 @@ set(OSL_HASH 53211da86c34ba6e0344998c1a6d219c)
set(OSL_HASH_TYPE MD5)
set(OSL_FILE OpenShadingLanguage-${OSL_VERSION}.tar.gz)
set(PYTHON_VERSION 3.10.8)
set(PYTHON_VERSION 3.10.9)
set(PYTHON_SHORT_VERSION 3.10)
set(PYTHON_SHORT_VERSION_NO_DOTS 310)
set(PYTHON_URI https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz)
set(PYTHON_HASH e92356b012ed4d0e09675131d39b1bde)
set(PYTHON_HASH dc8c0f274b28ee9e95923d20cfc364c9)
set(PYTHON_HASH_TYPE MD5)
set(PYTHON_FILE Python-${PYTHON_VERSION}.tar.xz)
set(PYTHON_CPE "cpe:2.3:a:python:python:${PYTHON_VERSION}:-:*:*:*:*:*:*")

View File

@ -260,7 +260,12 @@ if(WITH_BOOST)
endif()
find_package(Boost COMPONENTS ${_boost_FIND_COMPONENTS})
# Boost Python is separate to avoid linking Python into tests that don't need it.
set(BOOST_LIBRARIES ${Boost_LIBRARIES})
if(WITH_USD AND USD_PYTHON_SUPPORT)
set(BOOST_PYTHON_LIBRARIES ${Boost_PYTHON${PYTHON_VERSION_NO_DOTS}_LIBRARY})
list(REMOVE_ITEM BOOST_LIBRARIES ${BOOST_PYTHON_LIBRARIES})
endif()
set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS})
set(BOOST_DEFINITIONS)
@ -496,7 +501,7 @@ if(PLATFORM_BUNDLED_LIBRARIES)
# Environment variables to run precompiled executables that needed libraries.
list(JOIN PLATFORM_BUNDLED_LIBRARY_DIRS ":" _library_paths)
set(PLATFORM_ENV_BUILD "DYLD_LIBRARY_PATH=\"${_library_paths};${DYLD_LIBRARY_PATH}\"")
set(PLATFORM_ENV_INSTALL "DYLD_LIBRARY_PATH=${CMAKE_INSTALL_PREFIX_WITH_CONFIG}Blender.app/Contents/Resources/lib/;$DYLD_LIBRARY_PATH")
set(PLATFORM_ENV_INSTALL "DYLD_LIBRARY_PATH=${CMAKE_INSTALL_PREFIX_WITH_CONFIG}/Blender.app/Contents/Resources/lib/;$DYLD_LIBRARY_PATH")
unset(_library_paths)
endif()

View File

@ -407,8 +407,13 @@ if(WITH_BOOST)
mark_as_advanced(Boost_INCLUDE_DIR) # why doesn't boost do this?
endif()
set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS})
# Boost Python is separate to avoid linking Python into tests that don't need it.
set(BOOST_LIBRARIES ${Boost_LIBRARIES})
if(WITH_USD AND USD_PYTHON_SUPPORT)
set(BOOST_PYTHON_LIBRARIES ${Boost_PYTHON${PYTHON_VERSION_NO_DOTS}_LIBRARY})
list(REMOVE_ITEM BOOST_LIBRARIES ${BOOST_PYTHON_LIBRARIES})
endif()
set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS})
set(BOOST_LIBPATH ${Boost_LIBRARY_DIRS})
set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB")

View File

@ -575,7 +575,7 @@ if(WITH_BOOST)
)
if (EXISTS ${BOOST_34_TRIGGER_FILE})
if(WITH_USD)
set(BOOST_LIBRARIES ${BOOST_LIBRARIES}
set(BOOST_PYTHON_LIBRARIES
debug ${BOOST_LIBPATH}/${BOOST_PREFIX}boost_python310-${BOOST_DEBUG_POSTFIX}.lib
optimized ${BOOST_LIBPATH}/${BOOST_PREFIX}boost_python310-${BOOST_POSTFIX}.lib
)

View File

@ -235,27 +235,6 @@ def main():
if args_out is not None:
args_out_index[:] = [i for (i, a) in enumerate(args_out) if type(a) == tuple]
fw(".. function:: %s(bm, %s)\n\n" % (b[0], ", ".join([args_in[i][0] for i in args_in_index])))
# -- wash the comment
comment_washed = []
comment = [] if comment is None else comment
for i, l in enumerate(comment):
assert ((l.strip() == "") or
(l in {"/*", " *"}) or
(l.startswith(("/* ", " * "))))
l = l[3:]
if i == 0 and not l.strip():
continue
if l.strip():
l = " " + l
comment_washed.append(l)
fw("\n".join(comment_washed))
fw("\n")
# -- done
# get the args
def get_args_wash(args, args_index, is_ret):
args_wash = []
@ -296,26 +275,36 @@ def main():
if comment_next:
comment += ("\n" if comment_prev else "") + comment_next.strip()
default_value = None
if tp == BMO_OP_SLOT_FLT:
tp_str = "float"
default_value = '0'
elif tp == BMO_OP_SLOT_INT:
if tp_sub == BMO_OP_SLOT_SUBTYPE_INT_ENUM:
tp_str = "enum in " + enums + ", default " + enums.split(",", 1)[0].strip("[")
default_value = enums.split(",", 1)[0].strip("[")
tp_str = "enum in " + enums + ", default " + default_value
elif tp_sub == BMO_OP_SLOT_SUBTYPE_INT_FLAG:
tp_str = "set of flags from " + enums + ", default {}"
default_value = 'set()'
tp_str = "set of flags from " + enums + ", default " + default_value
else:
tp_str = "int"
default_value = '0'
elif tp == BMO_OP_SLOT_BOOL:
tp_str = "bool"
default_value = 'False'
elif tp == BMO_OP_SLOT_MAT:
tp_str = ":class:`mathutils.Matrix`"
default_value = 'mathutils.Matrix.Identity(4)'
elif tp == BMO_OP_SLOT_VEC:
tp_str = ":class:`mathutils.Vector`"
default_value = 'mathutils.Vector()'
if not is_ret:
tp_str += " or any sequence of 3 floats"
elif tp == BMO_OP_SLOT_PTR:
tp_str = "dict"
assert tp_sub is not None
if 'if None' in comment:
default_value = 'None'
if tp_sub == BMO_OP_SLOT_SUBTYPE_PTR_BMESH:
tp_str = ":class:`bmesh.types.BMesh`"
elif tp_sub == BMO_OP_SLOT_SUBTYPE_PTR_SCENE:
@ -348,13 +337,16 @@ def main():
tp_str = "/".join(ls)
else:
tp_str = ("list of (%s)" % ", ".join(ls))
default_value = '[]'
del ls
elif tp == BMO_OP_SLOT_MAPPING:
if tp_sub & BMO_OP_SLOT_SUBTYPE_MAP_EMPTY:
tp_str = "set of vert/edge/face type"
default_value = 'set()'
else:
tp_str = "dict mapping vert/edge/face types to "
default_value = '{}'
if tp_sub == BMO_OP_SLOT_SUBTYPE_MAP_BOOL:
tp_str += "bool"
elif tp_sub == BMO_OP_SLOT_SUBTYPE_MAP_INT:
@ -372,18 +364,40 @@ def main():
print("Can't find", vars_dict_reverse[tp])
assert 0
args_wash.append((name, tp_str, comment))
args_wash.append((name, default_value, tp_str, comment))
return args_wash
# end get_args_wash
args_in_wash = get_args_wash(args_in, args_in_index, False)
fw(".. function:: %s(bm, %s)\n\n" % (b[0], ", ".join([print_arg_in(arg) for arg in args_in_wash])))
# -- wash the comment
comment_washed = []
comment = [] if comment is None else comment
for i, l in enumerate(comment):
assert ((l.strip() == "") or
(l in {"/*", " *"}) or
(l.startswith(("/* ", " * "))))
l = l[3:]
if i == 0 and not l.strip():
continue
if l.strip():
l = " " + l
comment_washed.append(l)
fw("\n".join(comment_washed))
fw("\n")
# -- done
# all ops get this arg
fw(" :arg bm: The bmesh to operate on.\n")
fw(" :type bm: :class:`bmesh.types.BMesh`\n")
args_in_wash = get_args_wash(args_in, args_in_index, False)
args_out_wash = get_args_wash(args_out, args_out_index, True)
for (name, tp, comment) in args_in_wash:
for (name, _, tp, comment) in args_in_wash:
if comment == "":
comment = "Undocumented."
@ -393,7 +407,7 @@ def main():
if args_out_wash:
fw(" :return:\n\n")
for (name, tp, comment) in args_out_wash:
for (name, _, tp, comment) in args_out_wash:
assert name.endswith(".out")
name = name[:-4]
fw(" - ``%s``: %s\n\n" % (name, comment))
@ -409,5 +423,12 @@ def main():
print(OUT_RST)
def print_arg_in(arg):
(name, default_value, _, _) = arg
if default_value is None:
return name
return name + '=' + default_value
if __name__ == "__main__":
main()

View File

@ -3,6 +3,11 @@
#include "app/oiio_output_driver.h"
#include "scene/colorspace.h"
#include <OpenImageIO/imagebuf.h>
#include <OpenImageIO/imagebufalgo.h>
CCL_NAMESPACE_BEGIN
OIIOOutputDriver::OIIOOutputDriver(const string_view filepath,
@ -47,11 +52,23 @@ void OIIOOutputDriver::write_render_tile(const Tile &tile)
}
/* Manipulate offset and stride to convert from bottom-up to top-down convention. */
image_output->write_image(TypeDesc::FLOAT,
pixels.data() + (height - 1) * width * 4,
AutoStride,
-width * 4 * sizeof(float),
AutoStride);
ImageBuf image_buffer(spec,
pixels.data() + (height - 1) * width * 4,
AutoStride,
-width * 4 * sizeof(float),
AutoStride);
/* Apply gamma correction for (some) non-linear file formats.
* TODO: use OpenColorIO view transform if available. */
if (ColorSpaceManager::detect_known_colorspace(
u_colorspace_auto, "", image_output->format_name(), true) == u_colorspace_srgb) {
const float g = 1.0f / 2.2f;
ImageBufAlgo::pow(image_buffer, image_buffer, {g, g, g, 1.0f});
}
/* Write to disk and close */
image_buffer.set_write_format(TypeDesc::FLOAT);
image_buffer.write(image_output.get());
image_output->close();
}

View File

@ -809,6 +809,11 @@ void BlenderDisplayDriver::draw(const Params &params)
* is bound externally. */
immBindShader(active_shader);
if (tiles_->current_tile.need_update_texture_pixels) {
update_tile_texture_pixels(tiles_->current_tile);
tiles_->current_tile.need_update_texture_pixels = false;
}
draw_tile(zoom_, texcoord_attribute, position_attribute, tiles_->current_tile.tile);
for (const DrawTile &tile : tiles_->finished_tiles.tiles) {

View File

@ -75,19 +75,19 @@ void BlenderSync::sync_light(BL::Object &b_parent,
switch (b_area_light.shape()) {
case BL::AreaLight::shape_SQUARE:
light->set_sizev(light->get_sizeu());
light->set_round(false);
light->set_ellipse(false);
break;
case BL::AreaLight::shape_RECTANGLE:
light->set_sizev(b_area_light.size_y());
light->set_round(false);
light->set_ellipse(false);
break;
case BL::AreaLight::shape_DISK:
light->set_sizev(light->get_sizeu());
light->set_round(true);
light->set_ellipse(true);
break;
case BL::AreaLight::shape_ELLIPSE:
light->set_sizev(b_area_light.size_y());
light->set_round(true);
light->set_ellipse(true);
break;
}
light->set_light_type(LIGHT_AREA);

View File

@ -64,10 +64,6 @@ void HdCyclesDisplayDriver::gl_context_create()
#endif
if (!gl_pbo_id_) {
if (glewInit() != GLEW_OK) {
return;
}
glGenBuffers(1, &gl_pbo_id_);
}
}

View File

@ -382,12 +382,12 @@ void HdCyclesLight::Initialize(HdRenderParam *renderParam)
}
else if (_lightType == HdPrimTypeTokens->diskLight) {
_light->set_light_type(LIGHT_AREA);
_light->set_round(true);
_light->set_ellipse(true);
_light->set_size(1.0f);
}
else if (_lightType == HdPrimTypeTokens->rectLight) {
_light->set_light_type(LIGHT_AREA);
_light->set_round(false);
_light->set_ellipse(false);
_light->set_size(1.0f);
}
else if (_lightType == HdPrimTypeTokens->sphereLight) {

View File

@ -235,7 +235,11 @@ void HdCyclesMaterial::Sync(HdSceneDelegate *sceneDelegate,
}
else {
networkConverted = std::make_unique<HdMaterialNetwork2>();
# if PXR_VERSION >= 2205
*networkConverted = HdConvertToHdMaterialNetwork2(networkOld);
# else
HdMaterialNetwork2ConvertFromHdMaterialNetworkMap(networkOld, networkConverted.get());
# endif
network = networkConverted.get();
}
}

View File

@ -55,12 +55,13 @@ bool HdCyclesOutputDriver::update_render_tile(const Tile &tile)
const bool isId = aovBinding.aovName == HdAovTokens->primId ||
aovBinding.aovName == HdAovTokens->elementId ||
aovBinding.aovName == HdAovTokens->instanceId;
renderBuffer->Map();
renderBuffer->WritePixels(pixels.data(),
GfVec2i(tile.offset.x, tile.offset.y),
GfVec2i(tile.size.x, tile.size.y),
channels,
isId);
renderBuffer->Unmap();
}
else {
// Do not warn on missing elementId, which is a standard AOV but is not implememted

View File

@ -91,60 +91,138 @@ ccl_device_inline float area_light_rect_sample(float3 P,
ccl_device float area_light_spread_attenuation(const float3 D,
const float3 lightNg,
const float cot_half_spread,
const float tan_half_spread,
const float normalize_spread)
{
/* Model a soft-box grid, computing the ratio of light not hidden by the
* slats of the grid at a given angle. (see D10594). */
const float cos_a = -dot(D, lightNg);
if (tan_half_spread == 0.0f) {
/* cos(0.05°) ≈ 0.9999997 */
/* The factor M_PI_F comes from integrating the radiance over the hemisphere */
return (cos_a > 0.9999997f) ? M_PI_F : 0.0f;
}
const float sin_a = safe_sqrtf(1.0f - sqr(cos_a));
const float tan_a = sin_a / cos_a;
return max((1.0f - (cot_half_spread * tan_a)) * normalize_spread, 0.0f);
return max((tan_half_spread - tan_a) * normalize_spread, 0.0f);
}
/* Compute subset of area light that actually has an influence on the shading point, to
* reduce noise with low spread. */
ccl_device bool area_light_spread_clamp_area_light(const float3 P,
const float3 lightNg,
ccl_private float3 *lightP,
const float3 axis_u,
ccl_private float *len_u,
const float3 axis_v,
ccl_private float *len_v,
const float cot_half_spread)
/* Compute the minimal rectangle, circle or ellipse that covers the valid sample region, to reduce
* noise with low spread. */
ccl_device bool area_light_spread_clamp_light(const float3 P,
const float3 lightNg,
ccl_private float3 *lightP,
ccl_private float3 *axis_u,
ccl_private float *len_u,
ccl_private float3 *axis_v,
ccl_private float *len_v,
const float tan_half_spread,
ccl_private bool *sample_rectangle)
{
/* Closest point in area light plane and distance to that plane. */
const float3 closest_P = P - dot(lightNg, P - *lightP) * lightNg;
const float t = len(closest_P - P);
/* Radius of circle on area light that actually affects the shading point. */
const float radius = t / cot_half_spread;
const float r_spread = t * tan_half_spread;
/* Local uv coordinates of closest point. */
const float closest_u = dot(axis_u, closest_P - *lightP);
const float closest_v = dot(axis_v, closest_P - *lightP);
const float spread_u = dot(*axis_u, closest_P - *lightP);
const float spread_v = dot(*axis_v, closest_P - *lightP);
/* Compute rectangle encompassing the circle that affects the shading point,
* clamped to the bounds of the area light. */
const float min_u = max(closest_u - radius, -*len_u * 0.5f);
const float max_u = min(closest_u + radius, *len_u * 0.5f);
const float min_v = max(closest_v - radius, -*len_v * 0.5f);
const float max_v = min(closest_v + radius, *len_v * 0.5f);
const bool is_round = !(*sample_rectangle) && (*len_u == *len_v);
/* Skip if rectangle is empty. */
if (min_u >= max_u || min_v >= max_v) {
return false;
/* Whether we should sample the spread circle. */
bool sample_spread = (r_spread == 0.0f);
if (is_round && !sample_spread) {
/* Distance between the centers of the disk light and the valid region circle. */
const float dist = len(make_float2(spread_u, spread_v));
/* Radius of the disk light. */
const float r = *len_u * 0.5f;
if (dist >= r + r_spread) {
/* Two circles are outside each other or touch externally. */
return false;
}
sample_spread = (dist <= fabsf(r - r_spread)) && (r_spread < r);
if (dist > fabsf(r - r_spread)) {
/* Two circles intersect. Find the smallest rectangle that covers the intersection */
const float len_u_ = r + r_spread - dist;
const float len_v_ = (fabsf(sqr(r) - sqr(r_spread)) >= sqr(dist)) ?
2.0f * fminf(r, r_spread) :
sqrtf(sqr(2.0f * r_spread) -
sqr(dist + (sqr(r_spread) - sqr(r)) / dist));
const float rect_area = len_u_ * len_v_;
const float circle_area = M_PI_F * sqr(r);
const float spread_area = M_PI_F * sqr(r_spread);
/* Sample the shape with minimal area. */
if (rect_area < fminf(circle_area, spread_area)) {
*sample_rectangle = true;
*axis_u = normalize(*lightP - closest_P);
*axis_v = rotate_around_axis(*axis_u, lightNg, M_PI_2_F);
*len_u = len_u_;
*len_v = len_v_;
*lightP = 0.5f * (*lightP + closest_P + *axis_u * (r_spread - r));
return true;
}
sample_spread = (spread_area < circle_area);
}
}
else if (!is_round && !sample_spread) {
/* Compute rectangle encompassing the circle that affects the shading point,
* clamped to the bounds of the area light. */
const float min_u = max(spread_u - r_spread, -*len_u * 0.5f);
const float max_u = min(spread_u + r_spread, *len_u * 0.5f);
const float min_v = max(spread_v - r_spread, -*len_v * 0.5f);
const float max_v = min(spread_v + r_spread, *len_v * 0.5f);
/* Skip if rectangle is empty. */
if (min_u >= max_u || min_v >= max_v) {
return false;
}
const float rect_len_u = max_u - min_u;
const float rect_len_v = max_v - min_v;
const float rect_area = rect_len_u * rect_len_v;
const float ellipse_area = (*sample_rectangle) ? FLT_MAX : M_PI_4_F * (*len_u) * (*len_v);
const float spread_area = M_PI_F * sqr(r_spread);
/* Sample the shape with minimal area. */
/* NOTE: we don't switch to spread circle sampling for rectangle light because rectangle light
* supports solid angle sampling, which has less variance than sampling the area. If ellipse
* area light also supports solid angle sampling, `*sample_rectangle ||` could be deleted. */
if (*sample_rectangle || rect_area < fminf(ellipse_area, spread_area)) {
*sample_rectangle = true;
/* Compute new area light center position and axes from rectangle in local
* uv coordinates. */
const float new_center_u = 0.5f * (min_u + max_u);
const float new_center_v = 0.5f * (min_v + max_v);
*len_u = rect_len_u;
*len_v = rect_len_v;
*lightP = *lightP + *axis_u * new_center_u + *axis_v * new_center_v;
return true;
}
*sample_rectangle = false;
sample_spread = (spread_area < ellipse_area);
}
/* Compute new area light center position and axes from rectangle in local
* uv coordinates. */
const float new_center_u = 0.5f * (min_u + max_u);
const float new_center_v = 0.5f * (min_v + max_v);
*len_u = max_u - min_u;
*len_v = max_v - min_v;
*lightP = *lightP + new_center_u * axis_u + new_center_v * axis_v;
if (sample_spread) {
*sample_rectangle = false;
*lightP = *lightP + *axis_u * spread_u + *axis_v * spread_v;
*len_u = r_spread * 2.0f;
*len_v = r_spread * 2.0f;
return true;
}
/* Don't clamp. */
return true;
}
@ -159,13 +237,7 @@ ccl_device_inline bool area_light_sample(const ccl_global KernelLight *klight,
{
ls->P = klight->co;
const float3 axis_u = klight->area.axis_u;
const float3 axis_v = klight->area.axis_v;
const float len_u = klight->area.len_u;
const float len_v = klight->area.len_v;
float3 Ng = klight->area.dir;
float invarea = fabsf(klight->area.invarea);
bool is_round = (klight->area.invarea < 0.0f);
if (!in_volume_segment) {
if (dot(ls->P - P, Ng) > 0.0f) {
@ -173,40 +245,72 @@ ccl_device_inline bool area_light_sample(const ccl_global KernelLight *klight,
}
}
const float3 axis_u = klight->area.axis_u;
const float3 axis_v = klight->area.axis_v;
const float len_u = klight->area.len_u;
const float len_v = klight->area.len_v;
float invarea = fabsf(klight->area.invarea);
bool is_ellipse = (klight->area.invarea < 0.0f);
bool sample_rectangle = !is_ellipse;
float3 inplane;
if (is_round || in_volume_segment) {
if (in_volume_segment) {
/* FIXME: handle rectangular light. */
inplane = ellipse_sample(axis_u * len_u * 0.5f, axis_v * len_v * 0.5f, randu, randv);
ls->P += inplane;
ls->pdf = invarea;
}
else {
inplane = ls->P;
float3 old_P = ls->P;
float3 sample_axis_u = axis_u;
float3 sample_axis_v = axis_v;
float sample_len_u = len_u;
float sample_len_v = len_v;
if (!in_volume_segment && klight->area.cot_half_spread > 0.0f) {
if (!area_light_spread_clamp_area_light(P,
Ng,
&ls->P,
axis_u,
&sample_len_u,
axis_v,
&sample_len_v,
klight->area.cot_half_spread)) {
if (klight->area.normalize_spread > 0) {
if (!area_light_spread_clamp_light(P,
Ng,
&ls->P,
&sample_axis_u,
&sample_len_u,
&sample_axis_v,
&sample_len_v,
klight->area.tan_half_spread,
&sample_rectangle)) {
return false;
}
}
ls->pdf = area_light_rect_sample(
P, &ls->P, axis_u, sample_len_u, axis_v, sample_len_v, randu, randv, true);
inplane = ls->P - inplane;
if (sample_rectangle) {
ls->pdf = area_light_rect_sample(
P, &ls->P, sample_axis_u, sample_len_u, sample_axis_v, sample_len_v, randu, randv, true);
}
else {
if (klight->area.tan_half_spread == 0.0f) {
ls->pdf = 1.0f;
}
else {
ls->P += ellipse_sample(sample_axis_u * sample_len_u * 0.5f,
sample_axis_v * sample_len_v * 0.5f,
randu,
randv);
ls->pdf = 4.0f * M_1_PI_F / (sample_len_u * sample_len_v);
}
}
inplane = ls->P - old_P;
}
const float light_u = dot(inplane, axis_u) / len_u;
const float light_v = dot(inplane, axis_v) / len_v;
/* Sampled point lies outside of the area light. */
if (is_ellipse && (sqr(light_u) + sqr(light_v) > 0.25f)) {
return false;
}
if (!is_ellipse && (fabsf(light_u) > 0.5f || fabsf(light_v) > 0.5f)) {
return false;
}
/* NOTE: Return barycentric coordinates in the same notation as Embree and OptiX. */
ls->u = light_v + 0.5f;
ls->v = -light_u - light_v;
@ -216,13 +320,13 @@ ccl_device_inline bool area_light_sample(const ccl_global KernelLight *klight,
ls->eval_fac = 0.25f * invarea;
if (klight->area.cot_half_spread > 0.0f) {
if (klight->area.normalize_spread > 0) {
/* Area Light spread angle attenuation */
ls->eval_fac *= area_light_spread_attenuation(
ls->D, ls->Ng, klight->area.cot_half_spread, klight->area.normalize_spread);
ls->D, ls->Ng, klight->area.tan_half_spread, klight->area.normalize_spread);
}
if (is_round) {
if (!sample_rectangle && klight->area.tan_half_spread > 0) {
ls->pdf *= lamp_light_pdf(Ng, -ls->D, ls->t);
}
@ -237,10 +341,10 @@ ccl_device_forceinline void area_light_update_position(const ccl_global KernelLi
ls->D = normalize_len(ls->P - P, &ls->t);
ls->pdf = invarea;
if (klight->area.cot_half_spread > 0.f) {
if (klight->area.tan_half_spread > 0) {
ls->eval_fac = 0.25f * invarea;
ls->eval_fac *= area_light_spread_attenuation(
ls->D, ls->Ng, klight->area.cot_half_spread, klight->area.normalize_spread);
ls->D, ls->Ng, klight->area.tan_half_spread, klight->area.normalize_spread);
}
}
@ -252,7 +356,7 @@ ccl_device_inline bool area_light_intersect(const ccl_global KernelLight *klight
{
/* Area light. */
const float invarea = fabsf(klight->area.invarea);
const bool is_round = (klight->area.invarea < 0.0f);
const bool is_ellipse = (klight->area.invarea < 0.0f);
if (invarea == 0.0f) {
return false;
}
@ -281,7 +385,7 @@ ccl_device_inline bool area_light_intersect(const ccl_global KernelLight *klight
t,
u,
v,
is_round);
is_ellipse);
}
ccl_device_inline bool area_light_sample_from_intersection(
@ -303,44 +407,47 @@ ccl_device_inline bool area_light_sample_from_intersection(
ls->D = ray_D;
ls->Ng = Ng;
const bool is_round = (klight->area.invarea < 0.0f);
if (is_round) {
ls->pdf = invarea * lamp_light_pdf(Ng, -ray_D, ls->t);
}
else {
const float3 axis_u = klight->area.axis_u;
const float3 axis_v = klight->area.axis_v;
float sample_len_u = klight->area.len_u;
float sample_len_v = klight->area.len_v;
float3 sample_axis_u = klight->area.axis_u;
float3 sample_axis_v = klight->area.axis_v;
float sample_len_u = klight->area.len_u;
float sample_len_v = klight->area.len_v;
bool is_ellipse = (klight->area.invarea < 0.0f);
bool sample_rectangle = !is_ellipse;
if (klight->area.cot_half_spread > 0.0f) {
if (!area_light_spread_clamp_area_light(ray_P,
Ng,
&light_P,
axis_u,
&sample_len_u,
axis_v,
&sample_len_v,
klight->area.cot_half_spread)) {
return false;
}
}
ls->pdf = area_light_rect_sample(
ray_P, &light_P, axis_u, sample_len_u, axis_v, sample_len_v, 0, 0, false);
}
ls->eval_fac = 0.25f * invarea;
if (klight->area.cot_half_spread > 0.0f) {
/* Area Light spread angle attenuation */
ls->eval_fac *= area_light_spread_attenuation(
ls->D, ls->Ng, klight->area.cot_half_spread, klight->area.normalize_spread);
if (ls->eval_fac == 0.0f) {
if (klight->area.normalize_spread > 0) {
if (!area_light_spread_clamp_light(ray_P,
Ng,
&light_P,
&sample_axis_u,
&sample_len_u,
&sample_axis_v,
&sample_len_v,
klight->area.tan_half_spread,
&sample_rectangle)) {
return false;
}
}
return true;
if (sample_rectangle) {
ls->pdf = area_light_rect_sample(
ray_P, &light_P, sample_axis_u, sample_len_u, sample_axis_v, sample_len_v, 0, 0, false);
}
else {
ls->pdf = klight->area.tan_half_spread == 0.0f ?
1.0f :
4.0f * M_1_PI_F / (sample_len_u * sample_len_v) *
lamp_light_pdf(Ng, -ray_D, ls->t);
}
ls->eval_fac = 0.25f * invarea;
if (klight->area.normalize_spread > 0) {
/* Area Light spread angle attenuation */
ls->eval_fac *= area_light_spread_attenuation(
ls->D, ls->Ng, klight->area.tan_half_spread, klight->area.normalize_spread);
}
return ls->eval_fac > 0;
}
template<bool in_volume_segment>

View File

@ -11,7 +11,7 @@ CCL_NAMESPACE_BEGIN
/* Simple CDF based sampling over all lights in the scene, without taking into
* account shading position or normal. */
ccl_device int light_distribution_sample(KernelGlobals kg, ccl_private float &randu)
ccl_device int light_distribution_sample(KernelGlobals kg, ccl_private float *randu)
{
/* This is basically std::upper_bound as used by PBRT, to find a point light or
* triangle to emit from, proportional to area. a good improvement would be to
@ -19,7 +19,7 @@ ccl_device int light_distribution_sample(KernelGlobals kg, ccl_private float &ra
* arbitrary shaders. */
int first = 0;
int len = kernel_data.integrator.num_distribution + 1;
float r = randu;
float r = *randu;
do {
int half_len = len >> 1;
@ -42,34 +42,58 @@ ccl_device int light_distribution_sample(KernelGlobals kg, ccl_private float &ra
* each area light be stratified as well. */
float distr_min = kernel_data_fetch(light_distribution, index).totarea;
float distr_max = kernel_data_fetch(light_distribution, index + 1).totarea;
randu = (r - distr_min) / (distr_max - distr_min);
*randu = (r - distr_min) / (distr_max - distr_min);
return index;
}
template<bool in_volume_segment>
ccl_device_noinline bool light_distribution_sample(KernelGlobals kg,
ccl_private float &randu,
float randu,
const float randv,
const float time,
const float3 P,
const int bounce,
const uint32_t path_flag,
ccl_private int &emitter_object,
ccl_private int &emitter_prim,
ccl_private int &emitter_shader_flag,
ccl_private float &emitter_pdf_selection)
ccl_private LightSample *ls)
{
/* Sample light index from distribution. */
const int index = light_distribution_sample(kg, randu);
const int index = light_distribution_sample(kg, &randu);
ccl_global const KernelLightDistribution *kdistribution = &kernel_data_fetch(light_distribution,
index);
const int prim = kdistribution->prim;
emitter_object = kdistribution->mesh_light.object_id;
emitter_prim = kdistribution->prim;
emitter_shader_flag = kdistribution->mesh_light.shader_flag;
emitter_pdf_selection = kernel_data.integrator.distribution_pdf_lights;
if (prim >= 0) {
/* Mesh light. */
const int object = kdistribution->mesh_light.object_id;
return true;
/* Exclude synthetic meshes from shadow catcher pass. */
if ((path_flag & PATH_RAY_SHADOW_CATCHER_PASS) &&
!(kernel_data_fetch(object_flag, object) & SD_OBJECT_SHADOW_CATCHER)) {
return false;
}
const int shader_flag = kdistribution->mesh_light.shader_flag;
if (!triangle_light_sample<in_volume_segment>(kg, prim, object, randu, randv, time, ls, P)) {
return false;
}
ls->shader |= shader_flag;
}
else {
const int lamp = -prim - 1;
if (UNLIKELY(light_select_reached_max_bounces(kg, lamp, bounce))) {
return false;
}
if (!light_sample<in_volume_segment>(kg, lamp, randu, randv, P, path_flag, ls)) {
return false;
}
ls->pdf_selection = kernel_data.integrator.distribution_pdf_lights;
}
ls->pdf *= ls->pdf_selection;
return (ls->pdf > 0.0f);
}
ccl_device_inline float light_distribution_pdf_lamp(KernelGlobals kg)

View File

@ -325,7 +325,7 @@ ccl_device_inline float light_sample_mis_weight_nee(KernelGlobals kg,
ccl_device_inline bool light_sample_from_volume_segment(KernelGlobals kg,
float randu,
float randv,
const float randv,
const float time,
const float3 P,
const float3 D,
@ -334,89 +334,22 @@ ccl_device_inline bool light_sample_from_volume_segment(KernelGlobals kg,
const uint32_t path_flag,
ccl_private LightSample *ls)
{
/* Select an emitter. */
int emitter_object = 0;
int emitter_prim = 0;
int emitter_shader_flag = 0;
float emitter_pdf_selection = 0.0f;
#ifdef __LIGHT_TREE__
if (kernel_data.integrator.use_light_tree) {
if (!light_tree_sample<true>(kg,
randu,
randv,
time,
P,
D,
t,
SD_BSDF_HAS_TRANSMISSION,
bounce,
path_flag,
emitter_object,
emitter_prim,
emitter_shader_flag,
emitter_pdf_selection)) {
return false;
}
return light_tree_sample<true>(
kg, randu, randv, time, P, D, t, SD_BSDF_HAS_TRANSMISSION, bounce, path_flag, ls);
}
else
#endif
{
if (!light_distribution_sample(kg,
randu,
randv,
time,
P,
bounce,
path_flag,
emitter_object,
emitter_prim,
emitter_shader_flag,
emitter_pdf_selection)) {
return false;
}
return light_distribution_sample<true>(kg, randu, randv, time, P, bounce, path_flag, ls);
}
/* Set first, triangle light sampling from flat distribution will override. */
ls->pdf_selection = emitter_pdf_selection;
/* Sample a point on the chosen emitter. */
if (emitter_prim >= 0) {
/* Mesh light. */
/* Exclude synthetic meshes from shadow catcher pass. */
if ((path_flag & PATH_RAY_SHADOW_CATCHER_PASS) &&
!(kernel_data_fetch(object_flag, emitter_object) & SD_OBJECT_SHADOW_CATCHER)) {
return false;
}
if (!triangle_light_sample<true>(
kg, emitter_prim, emitter_object, randu, randv, time, ls, P)) {
return false;
}
}
else {
/* Light object. */
const int lamp = ~emitter_prim;
if (UNLIKELY(light_select_reached_max_bounces(kg, lamp, bounce))) {
return false;
}
if (!light_sample<true>(kg, lamp, randu, randv, P, path_flag, ls)) {
return false;
}
}
ls->pdf *= ls->pdf_selection;
ls->shader |= emitter_shader_flag;
return (ls->pdf > 0);
}
ccl_device bool light_sample_from_position(KernelGlobals kg,
ccl_private const RNGState *rng_state,
float randu,
float randv,
const float randu,
const float randv,
const float time,
const float3 P,
const float3 N,
@ -425,84 +358,16 @@ ccl_device bool light_sample_from_position(KernelGlobals kg,
const uint32_t path_flag,
ccl_private LightSample *ls)
{
/* Select an emitter. */
int emitter_object = 0;
int emitter_prim = 0;
int emitter_shader_flag = 0;
float emitter_pdf_selection = 0.0f;
#ifdef __LIGHT_TREE__
if (kernel_data.integrator.use_light_tree) {
if (!light_tree_sample<false>(kg,
randu,
randv,
time,
P,
N,
0,
shader_flags,
bounce,
path_flag,
emitter_object,
emitter_prim,
emitter_shader_flag,
emitter_pdf_selection)) {
return false;
}
return light_tree_sample<false>(
kg, randu, randv, time, P, N, 0, shader_flags, bounce, path_flag, ls);
}
else
#endif
{
if (!light_distribution_sample(kg,
randu,
randv,
time,
P,
bounce,
path_flag,
emitter_object,
emitter_prim,
emitter_shader_flag,
emitter_pdf_selection)) {
return false;
}
return light_distribution_sample<false>(kg, randu, randv, time, P, bounce, path_flag, ls);
}
/* Set first, triangle light sampling from flat distribution will override. */
ls->pdf_selection = emitter_pdf_selection;
/* Sample a point on the chosen emitter.
* TODO: deduplicate code with light_sample_from_volume_segment? */
if (emitter_prim >= 0) {
/* Mesh light. */
/* Exclude synthetic meshes from shadow catcher pass. */
if ((path_flag & PATH_RAY_SHADOW_CATCHER_PASS) &&
!(kernel_data_fetch(object_flag, emitter_object) & SD_OBJECT_SHADOW_CATCHER)) {
return false;
}
if (!triangle_light_sample<false>(
kg, emitter_prim, emitter_object, randu, randv, time, ls, P)) {
return false;
}
}
else {
/* Light object. */
const int lamp = ~emitter_prim;
if (UNLIKELY(light_select_reached_max_bounces(kg, lamp, bounce))) {
return false;
}
if (!light_sample<false>(kg, lamp, randu, randv, P, path_flag, ls)) {
return false;
}
}
ls->pdf *= ls->pdf_selection;
ls->shader |= emitter_shader_flag;
return (ls->pdf > 0);
}
ccl_device_inline bool light_sample_new_position(KernelGlobals kg,

View File

@ -41,7 +41,7 @@ ccl_device float light_tree_cos_bounding_box_angle(const BoundingBox bbox,
(i & 2) ? bbox.max.y : bbox.min.y,
(i & 4) ? bbox.max.z : bbox.min.z);
/* Caculate the bounding box angle. */
/* Calculate the bounding box angle. */
float3 point_to_corner = normalize(corner - P);
cos_theta_u = fminf(cos_theta_u, dot(point_to_centroid, point_to_corner));
}
@ -58,9 +58,8 @@ ccl_device float3 compute_v(
const float3 centroid, const float3 P, const float3 D, const float3 bcone_axis, const float t)
{
const float3 unnormalized_v0 = P - centroid;
float len_v0;
const float3 unnormalized_v1 = unnormalized_v0 + D * fminf(t, 1e12f);
const float3 v0 = normalize_len(unnormalized_v0, &len_v0);
const float3 v0 = normalize(unnormalized_v0);
const float3 v1 = normalize(unnormalized_v1);
const float3 o0 = v0;
@ -69,10 +68,11 @@ ccl_device float3 compute_v(
const float dot_o0_a = dot(o0, bcone_axis);
const float dot_o1_a = dot(o1, bcone_axis);
const float cos_phi0 = dot_o0_a / sqrtf(sqr(dot_o0_a) + sqr(dot_o1_a));
const float inv_len = inversesqrtf(sqr(dot_o0_a) + sqr(dot_o1_a));
const float cos_phi0 = dot_o0_a * inv_len;
return (dot_o1_a < 0 || dot(v0, v1) > cos_phi0) ? (dot_o0_a > dot(v1, bcone_axis) ? v0 : v1) :
cos_phi0 * o0 + sin_from_cos(cos_phi0) * o1;
cos_phi0 * o0 + dot_o1_a * inv_len * o1;
}
/* This is the general function for calculating the importance of either a cluster or an emitter.
@ -461,7 +461,7 @@ ccl_device int light_tree_cluster_select_emitter(KernelGlobals kg,
for (int i = 0; i < knode->num_prims; i++) {
int current_index = -knode->child_index + i;
/* maximum importance = importance[0], mininum importance = importance[1] */
/* maximum importance = importance[0], minimum importance = importance[1] */
float importance[2];
light_tree_emitter_importance<in_volume_segment>(
kg, P, N_or_D, t, has_transmission, current_index, importance[0], importance[1]);
@ -552,8 +552,8 @@ ccl_device bool get_left_probability(KernelGlobals kg,
template<bool in_volume_segment>
ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
ccl_private float &randu,
ccl_private float &randv,
float randu,
float randv,
const float time,
const float3 P,
const float3 N_or_D,
@ -561,10 +561,7 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
const int shader_flags,
const int bounce,
const uint32_t path_flag,
ccl_private int &emitter_object,
ccl_private int &emitter_prim,
ccl_private int &emitter_shader_flag,
ccl_private float &emitter_pdf_selection)
ccl_private LightSample *ls)
{
if (!kernel_data.integrator.use_direct_light) {
return false;
@ -610,16 +607,42 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
return false;
}
/* Return info about chosen emitter. */
/* Sample a point on the chosen emitter */
ccl_global const KernelLightTreeEmitter *kemitter = &kernel_data_fetch(light_tree_emitters,
selected_light);
emitter_object = kemitter->mesh_light.object_id;
emitter_prim = kemitter->prim_id;
emitter_shader_flag = kemitter->mesh_light.shader_flag;
emitter_pdf_selection = pdf_leaf * pdf_emitter_from_leaf;
/* TODO: this is the same code as light_distribution_sample, except the index is determined
* differently. Would it be better to refactor this into a separate function? */
const int prim = kemitter->prim_id;
if (prim >= 0) {
/* Mesh light. */
const int object = kemitter->mesh_light.object_id;
return true;
/* Exclude synthetic meshes from shadow catcher pass. */
if ((path_flag & PATH_RAY_SHADOW_CATCHER_PASS) &&
!(kernel_data_fetch(object_flag, object) & SD_OBJECT_SHADOW_CATCHER)) {
return false;
}
const int mesh_shader_flag = kemitter->mesh_light.shader_flag;
if (!triangle_light_sample<in_volume_segment>(kg, prim, object, randu, randv, time, ls, P)) {
return false;
}
ls->shader |= mesh_shader_flag;
}
else {
if (UNLIKELY(light_select_reached_max_bounces(kg, ~prim, bounce))) {
return false;
}
if (!light_sample<in_volume_segment>(kg, ~prim, randu, randv, P, path_flag, ls)) {
return false;
}
}
ls->pdf_selection = pdf_leaf * pdf_emitter_from_leaf;
ls->pdf *= ls->pdf_selection;
return (ls->pdf > 0);
}
/* We need to be able to find the probability of selecting a given light for MIS. */

View File

@ -1307,7 +1307,7 @@ typedef struct KernelAreaLight {
float len_v;
packed_float3 dir;
float invarea;
float cot_half_spread;
float tan_half_spread;
float normalize_spread;
float pad[2];
} KernelAreaLight;

View File

@ -95,16 +95,19 @@ bool ColorSpaceManager::colorspace_is_data(ustring colorspace)
}
ustring ColorSpaceManager::detect_known_colorspace(ustring colorspace,
const char *file_colorspace,
const char *file_format,
bool is_float)
{
if (colorspace == u_colorspace_auto) {
/* Auto detect sRGB or raw if none specified. */
if (is_float) {
bool srgb = (colorspace == "sRGB" || colorspace == "GammaCorrected" ||
(colorspace.empty() &&
(strcmp(file_format, "png") == 0 || strcmp(file_format, "tiff") == 0 ||
strcmp(file_format, "dpx") == 0 || strcmp(file_format, "jpeg2000") == 0)));
bool srgb = (strcmp(file_colorspace, "sRGB") == 0 ||
strcmp(file_colorspace, "GammaCorrected") == 0 ||
(file_colorspace[0] == '\0' &&
(strcmp(file_format, "png") == 0 || strcmp(file_format, "jpeg") == 0 ||
strcmp(file_format, "tiff") == 0 || strcmp(file_format, "dpx") == 0 ||
strcmp(file_format, "jpeg2000") == 0)));
return srgb ? u_colorspace_srgb : u_colorspace_raw;
}
else {

View File

@ -21,6 +21,7 @@ class ColorSpaceManager {
* convert to and from. If the colorspace is u_colorspace_auto, we auto
* detect a colospace. */
static ustring detect_known_colorspace(ustring colorspace,
const char *file_colorspace,
const char *file_format,
bool is_float);

View File

@ -261,7 +261,7 @@ void ImageMetaData::detect_colorspace()
{
/* Convert used specified color spaces to one we know how to handle. */
colorspace = ColorSpaceManager::detect_known_colorspace(
colorspace, colorspace_file_format, is_float());
colorspace, colorspace_file_hint.c_str(), colorspace_file_format, is_float());
if (colorspace == u_colorspace_raw) {
/* Nothing to do. */

View File

@ -69,6 +69,7 @@ class ImageMetaData {
/* Optional color space, defaults to raw. */
ustring colorspace;
string colorspace_file_hint;
const char *colorspace_file_format;
/* Optional transform for 3D images. */

View File

@ -85,6 +85,7 @@ bool OIIOImageLoader::load_metadata(const ImageDeviceFeatures & /*features*/,
}
metadata.colorspace_file_format = in->format_name();
metadata.colorspace_file_hint = spec.get_string_attribute("oiio:ColorSpace");
in->close();

View File

@ -106,7 +106,7 @@ NODE_DEFINE(Light)
SOCKET_FLOAT(sizeu, "Size U", 1.0f);
SOCKET_VECTOR(axisv, "Axis V", zero_float3());
SOCKET_FLOAT(sizev, "Size V", 1.0f);
SOCKET_BOOLEAN(round, "Round", false);
SOCKET_BOOLEAN(ellipse, "Ellipse", false);
SOCKET_FLOAT(spread, "Spread", M_PI_F);
SOCKET_INT(map_resolution, "Map Resolution", 0);
@ -911,7 +911,7 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
float3 axis_u = normalize_len(extentu, &len_u);
float3 axis_v = normalize_len(extentv, &len_v);
float area = len_u * len_v;
if (light->round) {
if (light->ellipse) {
area *= -M_PI_4_F;
}
float invarea = (area != 0.0f) ? 1.0f / area : 1.0f;
@ -1032,20 +1032,21 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
float3 axis_u = normalize_len(extentu, &len_u);
float3 axis_v = normalize_len(extentv, &len_v);
float area = len_u * len_v;
if (light->round) {
if (light->ellipse) {
area *= -M_PI_4_F;
}
float invarea = (area != 0.0f) ? 1.0f / area : 1.0f;
float3 dir = light->dir;
/* Clamping to a minimum angle to avoid excessive noise. */
const float min_spread = 1.0f * M_PI_F / 180.0f;
const float half_spread = 0.5f * max(light->spread, min_spread);
/* cot_half_spread is h in D10594#269626 */
const float cot_half_spread = tanf(M_PI_2_F - half_spread);
/* Clamp angles in (0, 0.1) to 0.1 to prevent zero intensity due to floating-point precision
* issues, but still handles spread = 0 */
const float min_spread = 0.1f * M_PI_F / 180.0f;
const float half_spread = light->spread == 0 ? 0.0f : 0.5f * max(light->spread, min_spread);
const float tan_half_spread = light->spread == M_PI_F ? FLT_MAX : tanf(half_spread);
/* Normalization computed using:
* integrate cos(x) * (1 - tan(x) / tan(a)) * sin(x) from x = 0 to a, a being half_spread */
const float normalize_spread = 1.0f / (1.0f - half_spread * cot_half_spread);
* integrate cos(x) * (1 - tan(x) / tan(a)) * sin(x) from x = 0 to a, a being half_spread.
* Divided by tan_half_spread to simplify the attenuation computation in `area.h`. */
const float normalize_spread = 1.0f / (tan_half_spread - half_spread);
dir = safe_normalize(dir);
@ -1059,7 +1060,7 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
klights[light_index].area.len_v = len_v;
klights[light_index].area.invarea = invarea;
klights[light_index].area.dir = dir;
klights[light_index].area.cot_half_spread = cot_half_spread;
klights[light_index].area.tan_half_spread = tan_half_spread;
klights[light_index].area.normalize_spread = normalize_spread;
}
else if (light->light_type == LIGHT_SPOT) {

View File

@ -45,7 +45,7 @@ class Light : public Node {
NODE_SOCKET_API(float, sizeu)
NODE_SOCKET_API(float3, axisv)
NODE_SOCKET_API(float, sizev)
NODE_SOCKET_API(bool, round)
NODE_SOCKET_API(bool, ellipse)
NODE_SOCKET_API(float, spread)
NODE_SOCKET_API(Transform, tfm)

View File

@ -33,7 +33,7 @@ struct OrientationBounds {
enum empty_t { empty = 0 };
/* If the orientation bound is set to empty, the values are set to minumums
/* If the orientation bound is set to empty, the values are set to minimums
* so that merging it with another non-empty orientation bound guarantees that
* the return value is equal to non-empty orientation bound. */
__forceinline OrientationBounds(empty_t)

View File

@ -860,7 +860,7 @@ ccl_device_inline uint find_first_set(uint x)
return (x != 0) ? ctz(x) + 1 : 0;
#else
# ifdef _MSC_VER
return (x != 0) ? (32 - count_leading_zeros(x & (-x))) : 0;
return (x != 0) ? (32 - count_leading_zeros(x & (~x + 1))) : 0;
# else
return __builtin_ffs(x);
# endif

View File

@ -1244,7 +1244,7 @@ static void ghost_wl_display_report_error(struct wl_display *display)
{
int ecode = wl_display_get_error(display);
GHOST_ASSERT(ecode, "Error not set!");
if ((ecode == EPIPE || ecode == ECONNRESET)) {
if (ELEM(ecode, EPIPE, ECONNRESET)) {
fprintf(stderr, "The Wayland connection broke. Did the Wayland compositor die?\n");
}
else {

View File

@ -396,11 +396,11 @@ path_reference_mode = EnumProperty(
name="Path Mode",
description="Method used to reference paths",
items=(
('AUTO', "Auto", "Use Relative paths with subdirectories only"),
('AUTO', "Auto", "Use relative paths with subdirectories only"),
('ABSOLUTE', "Absolute", "Always write absolute paths"),
('RELATIVE', "Relative", "Always write relative paths "
"(where possible)"),
('MATCH', "Match", "Match Absolute/Relative "
('MATCH', "Match", "Match absolute/relative "
"setting with input path"),
('STRIP', "Strip Path", "Filename only"),
('COPY', "Copy", "Copy the file to the destination path "

View File

@ -12,6 +12,7 @@ class NODE_MT_geometry_node_GEO_ATTRIBUTE(Menu):
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "GeometryNodeAttributeStatistic")
node_add_menu.add_node_type(layout, "GeometryNodeBlurAttribute")
node_add_menu.add_node_type(layout, "GeometryNodeCaptureAttribute")
node_add_menu.add_node_type(layout, "GeometryNodeAttributeDomainSize")
node_add_menu.add_node_type(layout, "GeometryNodeRemoveAttribute")

View File

@ -1541,6 +1541,7 @@ struct TexResult;
#define GEO_NODE_SAMPLE_UV_SURFACE 1187
#define GEO_NODE_SET_CURVE_NORMAL 1188
#define GEO_NODE_IMAGE_INFO 1189
#define GEO_NODE_BLUR_ATTRIBUTE 1190
/** \} */

View File

@ -1189,7 +1189,7 @@ static void cloth_update_spring_lengths(ClothModifierData *clmd, Mesh *mesh)
LinkNode *search = cloth->springs;
uint struct_springs = 0;
uint i = 0;
uint mvert_num = (uint)mesh->totvert;
uint mvert_num = uint(mesh->totvert);
float shrink_factor;
clmd->sim_parms->avg_spring_len = 0.0f;
@ -1465,7 +1465,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
ClothSpring *spring = nullptr, *tspring = nullptr, *tspring2 = nullptr;
uint struct_springs = 0, shear_springs = 0, bend_springs = 0, struct_springs_real = 0;
uint mvert_num = (uint)mesh->totvert;
uint numedges = (uint)mesh->totedge;
uint numedges = uint(mesh->totedge);
uint numpolys = (uint)mesh->totpoly;
float shrink_factor;
const MEdge *medge = BKE_mesh_edges(mesh);
@ -1652,7 +1652,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
for (int i = 0; i < mvert_num; i++) {
if (cloth->verts[i].spring_count > 0) {
cloth->verts[i].avg_spring_len = cloth->verts[i].avg_spring_len * 0.49f /
((float)cloth->verts[i].spring_count);
(float(cloth->verts[i].spring_count));
}
}

View File

@ -585,8 +585,8 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(ListBase *r_map
if (use_delete) {
if (tot_dst) {
data_dst_to_delete = static_cast<bool *>(
MEM_mallocN(sizeof(*data_dst_to_delete) * (size_t)tot_dst, __func__));
memset(data_dst_to_delete, true, sizeof(*data_dst_to_delete) * (size_t)tot_dst);
MEM_mallocN(sizeof(*data_dst_to_delete) * size_t(tot_dst), __func__));
memset(data_dst_to_delete, true, sizeof(*data_dst_to_delete) * size_t(tot_dst));
}
}
@ -824,7 +824,7 @@ static bool data_transfer_layersmapping_cdlayers(ListBase *r_map,
else if (fromlayers == DT_LAYERS_ALL_SRC) {
int num_src = CustomData_number_of_layers(cd_src, cddata_type);
bool *use_layers_src = num_src ? static_cast<bool *>(MEM_mallocN(
sizeof(*use_layers_src) * (size_t)num_src, __func__)) :
sizeof(*use_layers_src) * size_t(num_src), __func__)) :
nullptr;
bool ret;
@ -1392,7 +1392,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
if (mdef && vg_idx != -1 && !weights[VDATA]) {
weights[VDATA] = static_cast<float *>(
MEM_mallocN(sizeof(*(weights[VDATA])) * (size_t)num_verts_dst, __func__));
MEM_mallocN(sizeof(*(weights[VDATA])) * size_t(num_verts_dst), __func__));
BKE_defvert_extract_vgroup_to_vertweights(
mdef, vg_idx, num_verts_dst, invert_vgroup, weights[VDATA]);
}
@ -1473,7 +1473,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
if (mdef && vg_idx != -1 && !weights[EDATA]) {
weights[EDATA] = static_cast<float *>(
MEM_mallocN(sizeof(*weights[EDATA]) * (size_t)num_edges_dst, __func__));
MEM_mallocN(sizeof(*weights[EDATA]) * size_t(num_edges_dst), __func__));
BKE_defvert_extract_vgroup_to_edgeweights(
mdef, vg_idx, num_verts_dst, edges_dst, num_edges_dst, invert_vgroup, weights[EDATA]);
}
@ -1572,7 +1572,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
if (mdef && vg_idx != -1 && !weights[LDATA]) {
weights[LDATA] = static_cast<float *>(
MEM_mallocN(sizeof(*weights[LDATA]) * (size_t)num_loops_dst, __func__));
MEM_mallocN(sizeof(*weights[LDATA]) * size_t(num_loops_dst), __func__));
BKE_defvert_extract_vgroup_to_loopweights(mdef,
vg_idx,
num_verts_dst,
@ -1659,7 +1659,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
if (mdef && vg_idx != -1 && !weights[PDATA]) {
weights[PDATA] = static_cast<float *>(
MEM_mallocN(sizeof(*weights[PDATA]) * (size_t)num_polys_dst, __func__));
MEM_mallocN(sizeof(*weights[PDATA]) * size_t(num_polys_dst), __func__));
BKE_defvert_extract_vgroup_to_polyweights(mdef,
vg_idx,
num_verts_dst,

View File

@ -718,7 +718,7 @@ static void cp_key(const int start,
ktot = 0.0;
flagflo = 1;
if (kb->totelem) {
kd = kb->totelem / (float)tot;
kd = kb->totelem / float(tot);
}
else {
return;
@ -1036,7 +1036,7 @@ static void do_key(const int start,
k1tot = 0.0;
flagflo |= 1;
if (k[0]->totelem) {
k1d = k[0]->totelem / (float)tot;
k1d = k[0]->totelem / float(tot);
}
else {
flagdo -= 1;
@ -1046,7 +1046,7 @@ static void do_key(const int start,
k2tot = 0.0;
flagflo |= 2;
if (k[0]->totelem) {
k2d = k[1]->totelem / (float)tot;
k2d = k[1]->totelem / float(tot);
}
else {
flagdo -= 2;
@ -1056,7 +1056,7 @@ static void do_key(const int start,
k3tot = 0.0;
flagflo |= 4;
if (k[0]->totelem) {
k3d = k[2]->totelem / (float)tot;
k3d = k[2]->totelem / float(tot);
}
else {
flagdo -= 4;
@ -1066,7 +1066,7 @@ static void do_key(const int start,
k4tot = 0.0;
flagflo |= 8;
if (k[0]->totelem) {
k4d = k[3]->totelem / (float)tot;
k4d = k[3]->totelem / float(tot);
}
else {
flagdo -= 8;
@ -2210,7 +2210,7 @@ void BKE_keyblock_convert_from_mesh(const Mesh *me, const Key *key, KeyBlock *kb
MEM_SAFE_FREE(kb->data);
kb->data = MEM_malloc_arrayN((size_t)len, (size_t)key->elemsize, __func__);
kb->data = MEM_malloc_arrayN(size_t(len), size_t(key->elemsize), __func__);
kb->totelem = len;
BKE_keyblock_update_from_mesh(me, kb);

View File

@ -588,7 +588,7 @@ void BKE_id_material_append(Main *bmain, ID *id, Material *ma)
Material *BKE_id_material_pop(Main *bmain, ID *id, int index_i)
{
short index = (short)index_i;
short index = short(index_i);
Material *ret = nullptr;
Material ***matar;
if ((matar = BKE_id_material_array_p(id))) {
@ -878,7 +878,7 @@ void BKE_object_materials_test(Main *bmain, Object *ob, ID *id)
* use object's material slots amount as reference.
* This avoids losing materials in a local object when its linked obdata goes missing.
* See T92780. */
BKE_id_material_resize(bmain, id, (short)ob->totcol, false);
BKE_id_material_resize(bmain, id, short(ob->totcol), false);
}
else {
/* Normal case: the use the obdata amount of materials slots to update the object's one. */

View File

@ -398,7 +398,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
const int totloop = result->totloop;
const int totpoly = result->totpoly;
float(*loop_normals)[3] = static_cast<float(*)[3]>(
MEM_calloc_arrayN((size_t)totloop, sizeof(*loop_normals), __func__));
MEM_calloc_arrayN(size_t(totloop), sizeof(*loop_normals), __func__));
CustomData *ldata = &result->ldata;
short(*clnors)[2] = static_cast<short(*)[2]>(CustomData_get_layer(ldata, CD_CUSTOMLOOPNORMAL));
MLoopNorSpaceArray lnors_spacearr = {nullptr};

View File

@ -179,10 +179,8 @@ static void mesh_calc_eigen_matrix(const float (*positions)[3],
if (positions) {
float(*co)[3];
cos = static_cast<float(*)[3]>(MEM_mallocN(sizeof(*cos) * (size_t)numverts, __func__));
for (i = 0, co = cos; i < numverts; i++, co++) {
copy_v3_v3(*co, positions[i]);
}
cos = static_cast<float(*)[3]>(MEM_mallocN(sizeof(*cos) * size_t(numverts), __func__));
memcpy(cos, positions, sizeof(float[3]) * size_t(numverts));
/* TODO(sergey): For until we officially drop all compilers which
* doesn't handle casting correct we use workaround to avoid explicit
* cast here.
@ -324,7 +322,7 @@ void BKE_mesh_remap_init(MeshPairRemap *map, const int items_num)
BKE_mesh_remap_free(map);
map->items = static_cast<MeshPairRemapItem *>(
BLI_memarena_alloc(mem, sizeof(*map->items) * (size_t)items_num));
BLI_memarena_alloc(mem, sizeof(*map->items) * size_t(items_num)));
map->items_num = items_num;
map->mem = mem;
@ -355,11 +353,11 @@ static void mesh_remap_item_define(MeshPairRemap *map,
if (sources_num) {
mapit->sources_num = sources_num;
mapit->indices_src = static_cast<int *>(
BLI_memarena_alloc(mem, sizeof(*mapit->indices_src) * (size_t)sources_num));
memcpy(mapit->indices_src, indices_src, sizeof(*mapit->indices_src) * (size_t)sources_num);
BLI_memarena_alloc(mem, sizeof(*mapit->indices_src) * size_t(sources_num)));
memcpy(mapit->indices_src, indices_src, sizeof(*mapit->indices_src) * size_t(sources_num));
mapit->weights_src = static_cast<float *>(
BLI_memarena_alloc(mem, sizeof(*mapit->weights_src) * (size_t)sources_num));
memcpy(mapit->weights_src, weights_src, sizeof(*mapit->weights_src) * (size_t)sources_num);
BLI_memarena_alloc(mem, sizeof(*mapit->weights_src) * size_t(sources_num)));
memcpy(mapit->weights_src, weights_src, sizeof(*mapit->weights_src) * size_t(sources_num));
}
else {
mapit->sources_num = 0;
@ -393,8 +391,8 @@ static int mesh_remap_interp_poly_data_get(const MPoly *mp,
const int sources_num = mp->totloop;
int i;
if ((size_t)sources_num > *buff_size) {
*buff_size = (size_t)sources_num;
if (size_t(sources_num) > *buff_size) {
*buff_size = size_t(sources_num);
*vcos = static_cast<float(*)[3]>(MEM_reallocN(*vcos, sizeof(**vcos) * *buff_size));
*indices = static_cast<int *>(MEM_reallocN(*indices, sizeof(**indices) * *buff_size));
if (do_weights) {
@ -682,7 +680,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode,
}
else {
CLOG_WARN(&LOG, "Unsupported mesh-to-mesh vertex mapping mode (%d)!", mode);
memset(r_map->items, 0, sizeof(*r_map->items) * (size_t)numverts_dst);
memset(r_map->items, 0, sizeof(*r_map->items) * size_t(numverts_dst));
}
free_bvhtree_from_mesh(&treedata);
@ -737,7 +735,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
int index;
};
HitData *v_dst_to_src_map = static_cast<HitData *>(
MEM_mallocN(sizeof(*v_dst_to_src_map) * (size_t)numverts_dst, __func__));
MEM_mallocN(sizeof(*v_dst_to_src_map) * size_t(numverts_dst), __func__));
for (i = 0; i < numverts_dst; i++) {
v_dst_to_src_map[i].hit_dist = -1.0f;
@ -932,10 +930,10 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
/* Subtleness - this one we can allocate only max number of cast rays per edges! */
int *indices = static_cast<int *>(
MEM_mallocN(sizeof(*indices) * (size_t)min_ii(numedges_src, num_rays_max), __func__));
MEM_mallocN(sizeof(*indices) * size_t(min_ii(numedges_src, num_rays_max)), __func__));
/* Here it's simpler to just allocate for all edges :/ */
float *weights = static_cast<float *>(
MEM_mallocN(sizeof(*weights) * (size_t)numedges_src, __func__));
MEM_mallocN(sizeof(*weights) * size_t(numedges_src), __func__));
BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_EDGES, 2);
@ -1031,7 +1029,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
}
else {
CLOG_WARN(&LOG, "Unsupported mesh-to-mesh edge mapping mode (%d)!", mode);
memset(r_map->items, 0, sizeof(*r_map->items) * (size_t)numedges_dst);
memset(r_map->items, 0, sizeof(*r_map->items) * size_t(numedges_dst));
}
free_bvhtree_from_mesh(&treedata);
@ -1120,7 +1118,7 @@ static void mesh_island_to_astar_graph(MeshIslandStore *islands,
const int node_num = islands ? island_poly_map->count : numpolys;
uchar *poly_status = static_cast<uchar *>(
MEM_callocN(sizeof(*poly_status) * (size_t)node_num, __func__));
MEM_callocN(sizeof(*poly_status) * size_t(node_num), __func__));
float(*poly_centers)[3];
int pidx_isld;
@ -1129,12 +1127,12 @@ static void mesh_island_to_astar_graph(MeshIslandStore *islands,
BLI_astar_graph_init(r_as_graph, node_num, nullptr);
/* poly_centers is owned by graph memarena. */
poly_centers = static_cast<float(*)[3]>(
BLI_memarena_calloc(r_as_graph->mem, sizeof(*poly_centers) * (size_t)node_num));
BLI_memarena_calloc(r_as_graph->mem, sizeof(*poly_centers) * size_t(node_num)));
if (islands) {
/* poly_island_index_map is owned by graph memarena. */
poly_island_index_map = static_cast<int *>(
BLI_memarena_calloc(r_as_graph->mem, sizeof(*poly_island_index_map) * (size_t)numpolys));
BLI_memarena_calloc(r_as_graph->mem, sizeof(*poly_island_index_map) * size_t(numpolys)));
for (i = island_poly_map->count; i--;) {
poly_island_index_map[island_poly_map->indices[i]] = i;
}
@ -1430,9 +1428,9 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
num_loops_src);
if (use_from_vert) {
loop_to_poly_map_src = static_cast<int *>(
MEM_mallocN(sizeof(*loop_to_poly_map_src) * (size_t)num_loops_src, __func__));
MEM_mallocN(sizeof(*loop_to_poly_map_src) * size_t(num_loops_src), __func__));
poly_cents_src = static_cast<float(*)[3]>(
MEM_mallocN(sizeof(*poly_cents_src) * (size_t)num_polys_src, __func__));
MEM_mallocN(sizeof(*poly_cents_src) * size_t(num_polys_src), __func__));
for (pidx_src = 0, mp_src = polys_src; pidx_src < num_polys_src; pidx_src++, mp_src++) {
for (plidx_src = 0, lidx_src = mp_src->loopstart; plidx_src < mp_src->totloop;
plidx_src++, lidx_src++) {
@ -1465,10 +1463,10 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
num_trees = use_islands ? island_store.islands_num : 1;
treedata = static_cast<BVHTreeFromMesh *>(
MEM_callocN(sizeof(*treedata) * (size_t)num_trees, __func__));
MEM_callocN(sizeof(*treedata) * size_t(num_trees), __func__));
if (isld_steps_src) {
as_graphdata = static_cast<BLI_AStarGraph *>(
MEM_callocN(sizeof(*as_graphdata) * (size_t)num_trees, __func__));
MEM_callocN(sizeof(*as_graphdata) * size_t(num_trees), __func__));
}
if (use_islands) {
@ -1576,7 +1574,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
/* And check each dest poly! */
islands_res = static_cast<IslandResult **>(
MEM_mallocN(sizeof(*islands_res) * (size_t)num_trees, __func__));
MEM_mallocN(sizeof(*islands_res) * size_t(num_trees), __func__));
for (tindex = 0; tindex < num_trees; tindex++) {
islands_res[tindex] = static_cast<IslandResult *>(
MEM_mallocN(sizeof(**islands_res) * islands_res_buff_size, __func__));
@ -1598,7 +1596,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
}
if ((size_t)mp_dst->totloop > islands_res_buff_size) {
islands_res_buff_size = (size_t)mp_dst->totloop + MREMAP_DEFAULT_BUFSIZE;
islands_res_buff_size = size_t(mp_dst->totloop) + MREMAP_DEFAULT_BUFSIZE;
for (tindex = 0; tindex < num_trees; tindex++) {
islands_res[tindex] = static_cast<IslandResult *>(
MEM_reallocN(islands_res[tindex], sizeof(**islands_res) * islands_res_buff_size));
@ -2305,8 +2303,8 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
copy_vn_fl(weights, int(numpolys_src), 0.0f);
if (UNLIKELY((size_t)mp->totloop > tmp_poly_size)) {
tmp_poly_size = (size_t)mp->totloop;
if (UNLIKELY(size_t(mp->totloop) > tmp_poly_size)) {
tmp_poly_size = size_t(mp->totloop);
poly_vcos_2d = static_cast<float(*)[2]>(
MEM_reallocN(poly_vcos_2d, sizeof(*poly_vcos_2d) * tmp_poly_size));
tri_vidx_2d = static_cast<int(*)[3]>(
@ -2346,7 +2344,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
}
tot_rays *= tot_rays;
poly_area_2d_inv = area_poly_v2(poly_vcos_2d, (uint)mp->totloop);
poly_area_2d_inv = area_poly_v2(poly_vcos_2d, uint(mp->totloop));
/* In case we have a null-area degenerated poly... */
poly_area_2d_inv = 1.0f / max_ff(poly_area_2d_inv, 1e-9f);
@ -2365,7 +2363,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
tri_vidx_2d[1][2] = 3;
}
else {
BLI_polyfill_calc(poly_vcos_2d, (uint)mp->totloop, -1, (uint(*)[3])tri_vidx_2d);
BLI_polyfill_calc(poly_vcos_2d, uint(mp->totloop), -1, (uint(*)[3])tri_vidx_2d);
}
for (j = 0; j < tris_num; j++) {
@ -2434,7 +2432,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
}
else {
CLOG_WARN(&LOG, "Unsupported mesh-to-mesh poly mapping mode (%d)!", mode);
memset(r_map->items, 0, sizeof(*r_map->items) * (size_t)numpolys_dst);
memset(r_map->items, 0, sizeof(*r_map->items) * size_t(numpolys_dst));
}
free_bvhtree_from_mesh(&treedata);

View File

@ -2576,15 +2576,19 @@ static bool sculpt_attr_update(Object *ob, SculptAttribute *attr)
if (bad) {
MEM_SAFE_FREE(attr->data);
}
else {
attr->data_for_bmesh = false;
}
}
else {
CustomData *cdata = sculpt_get_cdata(ob, attr->domain);
if (cdata) {
int layer_index = CustomData_get_named_layer_index(cdata, attr->proptype, attr->name);
bad = layer_index == -1;
if (ss->bm) {
bad |= (ss->bm != nullptr) != attr->data_for_bmesh;
if (attr->data_for_bmesh) {
attr->bmesh_cd_offset = cdata->layers[layer_index].offset;
}
}

View File

@ -1185,7 +1185,7 @@ const UVVertex *UVPrimitive::get_other_uv_vertex(const UVVertex *v1, const UVVer
for (const UVEdge *edge : edges) {
for (const UVVertex *uv_vertex : edge->vertices) {
if (uv_vertex != v1 && uv_vertex != v2) {
if (!ELEM(uv_vertex, v1, v2)) {
return uv_vertex;
}
}

View File

@ -451,7 +451,7 @@ Tex *give_current_linestyle_texture(FreestyleLineStyle *linestyle)
Tex *tex = nullptr;
if (linestyle) {
mtex = linestyle->mtex[(int)(linestyle->texact)];
mtex = linestyle->mtex[int(linestyle->texact)];
if (mtex) {
tex = mtex->tex;
}
@ -555,7 +555,7 @@ Tex *give_current_particle_texture(ParticleSettings *part)
return nullptr;
}
mtex = part->mtex[(int)(part->texact)];
mtex = part->mtex[int(part->texact)];
if (mtex) {
tex = mtex->tex;
}

View File

@ -3696,8 +3696,8 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
LISTBASE_FOREACH (MovieClip *, clip, &bmain->movieclips) {
MovieTracking *tracking = &clip->tracking;
const float frame_center_x = ((float)clip->lastsize[0]) / 2;
const float frame_center_y = ((float)clip->lastsize[1]) / 2;
const float frame_center_x = (float(clip->lastsize[0])) / 2;
const float frame_center_y = float(clip->lastsize[1]) / 2;
tracking->camera.principal_point[0] = (tracking->camera.principal_legacy[0] -
frame_center_x) /

View File

@ -405,7 +405,7 @@ static void bm_mesh_edges_sharp_tag(BMesh *bm,
void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle)
{
if (split_angle >= (float)M_PI) {
if (split_angle >= float(M_PI)) {
/* Nothing to do! */
return;
}
@ -715,8 +715,8 @@ static int bm_mesh_loops_calc_normals_for_loop(BMesh *bm,
while ((clnor = static_cast<short *>(BLI_SMALLSTACK_POP(clnors)))) {
// print_v2("org clnor", clnor);
clnor[0] = (short)clnors_avg[0];
clnor[1] = (short)clnors_avg[1];
clnor[0] = short(clnors_avg[0]);
clnor[1] = short(clnors_avg[1]);
}
// print_v2("new clnors", clnors_avg);
}
@ -1382,7 +1382,7 @@ static bool bm_mesh_loops_split_lnor_fans(BMesh *bm,
MLoopNorSpaceArray *lnors_spacearr,
const float (*new_lnors)[3])
{
BLI_bitmap *done_loops = BLI_BITMAP_NEW((size_t)bm->totloop, __func__);
BLI_bitmap *done_loops = BLI_BITMAP_NEW(size_t(bm->totloop), __func__);
bool changed = false;
BLI_assert(lnors_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR);
@ -1480,7 +1480,7 @@ static void bm_mesh_loops_assign_normal_data(BMesh *bm,
const int cd_loop_clnors_offset,
const float (*new_lnors)[3])
{
BLI_bitmap *done_loops = BLI_BITMAP_NEW((size_t)bm->totloop, __func__);
BLI_bitmap *done_loops = BLI_BITMAP_NEW(size_t(bm->totloop), __func__);
BLI_SMALLSTACK_DECLARE(clnors_data, short *);
@ -1540,7 +1540,7 @@ static void bm_mesh_loops_assign_normal_data(BMesh *bm,
BLI_BITMAP_ENABLE(done_loops, lidx);
}
mul_v3_fl(avg_nor, 1.0f / (float)avg_nor_count);
mul_v3_fl(avg_nor, 1.0f / float(avg_nor_count));
BKE_lnor_space_custom_normal_to_data(
lnors_spacearr->lspacearr[i], avg_nor, clnor_data_tmp);

View File

@ -1373,7 +1373,7 @@ static BMOpDefine bmo_duplicate_def = {
"duplicate",
/* slots_in */
{{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */
{"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}}, /* destination bmesh, if NULL will use current on */
{"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}}, /* destination bmesh, if None will use current on */
{"use_select_history", BMO_OP_SLOT_BOOL},
{"use_edge_flip_from_face", BMO_OP_SLOT_BOOL},
{{'\0'}},
@ -1405,7 +1405,7 @@ static BMOpDefine bmo_split_def = {
"split",
/* slots_in */
{{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */
{"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}}, /* destination bmesh, if NULL will use current one */
{"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}}, /* destination bmesh, if None will use current one */
{"use_only_faces", BMO_OP_SLOT_BOOL}, /* when enabled. don't duplicate loose verts/edges */
{{'\0'}},
},
@ -1780,7 +1780,7 @@ static BMOpDefine bmo_bevel_def = {
bmo_enum_bevel_miter_type}, /* outer miter kind */
{"spread", BMO_OP_SLOT_FLT}, /* amount to offset beveled edge */
{"smoothresh", BMO_OP_SLOT_FLT}, /* for passing mesh's smoothresh, used in hardening */
{"custom_profile", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_STRUCT}}, /* CurveProfile */
{"custom_profile", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_STRUCT}}, /* CurveProfile, if None ignored */
{"vmesh_method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM},
bmo_enum_bevel_vmesh_method}, /* The method to use to create meshes at intersections. */
{{'\0'}},

View File

@ -235,7 +235,7 @@ static void gpencil_stroke_cache_populate(bGPDlayer * /*gpl*/,
if (show_stroke) {
int vfirst = gps->runtime.stroke_start * 3;
bool is_cyclic = ((gps->flag & GP_STROKE_CYCLIC) != 0) && (gps->totpoints > 2);
int vcount = (gps->totpoints + (int)is_cyclic) * 2 * 3;
int vcount = (gps->totpoints + int(is_cyclic)) * 2 * 3;
DRW_shgroup_call_range(iter->stroke_grp, iter->ob, geom, vfirst, vcount);
}
}

View File

@ -644,7 +644,7 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_fill)
}
/* Compute directly inside the IBO data buffer. */
/* OPTI: This is a bottleneck if the stroke is very long. */
BLI_polyfill_calc(tpoints2d, (uint)vert_len, 0, (uint(*)[3])ibo_builder.data);
BLI_polyfill_calc(tpoints2d, uint(vert_len), 0, (uint(*)[3])ibo_builder.data);
/* Add stroke start offset and shift. */
for (int i = 0; i < gps->tot_triangles * 3; i++) {
ibo_builder.data[i] = (ibo_builder.data[i] + 1) << GP_VERTEX_ID_SHIFT;

View File

@ -417,7 +417,7 @@ static void eyedropper_color_sample(bContext *C, Eyedropper *eye, const int m_xy
/* Apply to property. */
float accum_col[3];
if (eye->accum_tot > 1) {
mul_v3_v3fl(accum_col, eye->accum_col, 1.0f / (float)eye->accum_tot);
mul_v3_v3fl(accum_col, eye->accum_col, 1.0f / float(eye->accum_tot));
}
else {
copy_v3_v3(accum_col, eye->accum_col);

View File

@ -175,7 +175,7 @@ static void depthdropper_depth_sample_pt(bContext *C,
view3d_operator_needs_opengl(C);
if (ED_view3d_autodist(depsgraph, region, v3d, mval, co, true, nullptr)) {
const float mval_center_fl[2] = {(float)region->winx / 2, (float)region->winy / 2};
const float mval_center_fl[2] = {float(region->winx) / 2, float(region->winy) / 2};
float co_align[3];
/* quick way to get view-center aligned point */
@ -185,7 +185,7 @@ static void depthdropper_depth_sample_pt(bContext *C,
BKE_unit_value_as_string(ddr->name,
sizeof(ddr->name),
(double)*r_depth,
double(*r_depth),
4,
B_UNIT_LENGTH,
&scene->unit,
@ -215,7 +215,7 @@ static void depthdropper_depth_set_accum(bContext *C, DepthDropper *ddr)
{
float depth = ddr->accum_depth;
if (ddr->accum_tot) {
depth /= (float)ddr->accum_tot;
depth /= float(ddr->accum_tot);
}
depthdropper_depth_set(C, ddr, depth);
}

View File

@ -405,7 +405,7 @@ void ui_block_align_calc(uiBlock *block, const ARegion *region)
butal_array = static_cast<ButAlign *>(
MEM_mallocN(sizeof(*butal_array) * num_buttons, __func__));
}
memset(butal_array, 0, sizeof(*butal_array) * (size_t)num_buttons);
memset(butal_array, 0, sizeof(*butal_array) * size_t(num_buttons));
/* Second loop: we initialize our ButAlign data for each button. */
butal = butal_array;
@ -424,7 +424,7 @@ void ui_block_align_calc(uiBlock *block, const ARegion *region)
/* This will give us ButAlign items regrouped by align group, vertical and horizontal location.
* Note that, given how buttons are defined in UI code,
* butal_array shall already be "nearly sorted"... */
qsort(butal_array, (size_t)num_buttons, sizeof(*butal_array), ui_block_align_butal_cmp);
qsort(butal_array, size_t(num_buttons), sizeof(*butal_array), ui_block_align_butal_cmp);
/* Third loop: for each pair of buttons in the same align group,
* we compute their potential proximity. Note that each pair is checked only once, and that we

View File

@ -1224,7 +1224,7 @@ void ui_draw_but_COLORBAND(uiBut *but, const uiWidgetColors * /*wcol*/, const rc
immBegin(GPU_PRIM_TRI_STRIP, (sizex + 1) * 2);
for (int a = 0; a <= sizex; a++) {
const float pos = (float(a)) / sizex;
const float pos = float(a) / sizex;
BKE_colorband_evaluate(coba, pos, colf);
if (display) {
IMB_colormanagement_scene_linear_to_display_v3(colf, display);
@ -1244,7 +1244,7 @@ void ui_draw_but_COLORBAND(uiBut *but, const uiWidgetColors * /*wcol*/, const rc
immBegin(GPU_PRIM_TRI_STRIP, (sizex + 1) * 2);
for (int a = 0; a <= sizex; a++) {
const float pos = (float(a)) / sizex;
const float pos = float(a) / sizex;
BKE_colorband_evaluate(coba, pos, colf);
if (display) {
IMB_colormanagement_scene_linear_to_display_v3(colf, display);
@ -1871,7 +1871,7 @@ void ui_draw_but_CURVEPROFILE(ARegion *region,
/* Draw the handles for the selected control points. */
pts = profile->path;
const int path_len = tot_points = (uint)profile->path_len;
const int path_len = tot_points = uint(profile->path_len);
int selected_free_points = 0;
for (int i = 0; i < path_len; i++) {
if (point_draw_handles(&pts[i])) {
@ -1966,7 +1966,7 @@ void ui_draw_but_CURVEPROFILE(ARegion *region,
/* Draw the sampled points in addition to the control points if they have been created */
pts = profile->segments;
const int segments_len = (uint)profile->segments_len;
const int segments_len = uint(profile->segments_len);
if (segments_len > 0 && pts) {
GPU_point_size(max_ff(2.0f, min_ff(UI_DPI_FAC / but->block->aspect * 3.0f, 3.0f)));
immBegin(GPU_PRIM_POINTS, segments_len);

View File

@ -3283,7 +3283,7 @@ static bool ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, const in
if (pbuf) {
if (UI_but_is_utf8(but)) {
buf_len -= BLI_str_utf8_invalid_strip(pbuf, (size_t)buf_len);
buf_len -= BLI_str_utf8_invalid_strip(pbuf, size_t(buf_len));
}
ui_textedit_insert_buf(but, data, pbuf, buf_len);

View File

@ -413,7 +413,7 @@ static void vicon_collection_color_draw(
bTheme *btheme = UI_GetTheme();
const ThemeCollectionColor *collection_color = &btheme->collection_color[color_tag];
const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w;
const float aspect = float(ICON_DEFAULT_WIDTH) / float(w);
UI_icon_draw_ex(x,
y,
@ -449,7 +449,7 @@ static void vicon_strip_color_draw(
bTheme *btheme = UI_GetTheme();
const ThemeStripColor *strip_color = &btheme->strip_color[color_tag];
const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w;
const float aspect = float(ICON_DEFAULT_WIDTH) / float(w);
UI_icon_draw_ex(
x, y, ICON_SNAP_FACE, aspect, 1.0f, 0.0f, strip_color->color, true, UI_NO_ICON_OVERLAY_TEXT);
@ -478,7 +478,7 @@ DEF_ICON_STRIP_COLOR_DRAW(09, SEQUENCE_COLOR_09);
static void vicon_strip_color_draw_library_data_indirect(
int x, int y, int w, int UNUSED(h), float alpha)
{
const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w;
const float aspect = float(ICON_DEFAULT_WIDTH) / float(w);
UI_icon_draw_ex(x,
y,
@ -494,7 +494,7 @@ static void vicon_strip_color_draw_library_data_indirect(
static void vicon_strip_color_draw_library_data_override_noneditable(
int x, int y, int w, int UNUSED(h), float alpha)
{
const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w;
const float aspect = float(ICON_DEFAULT_WIDTH) / float(w);
UI_icon_draw_ex(x,
y,
@ -1543,16 +1543,16 @@ static void icon_draw_rect(float x,
/* preserve aspect ratio and center */
if (rw > rh) {
draw_w = w;
draw_h = (int)(((float)rh / (float)rw) * (float)w);
draw_h = (int)((float(rh) / float(rw)) * float(w));
draw_y += (h - draw_h) / 2;
}
else if (rw < rh) {
draw_w = (int)(((float)rw / (float)rh) * (float)h);
draw_w = (int)((float(rw) / float(rh)) * float(h));
draw_h = h;
draw_x += (w - draw_w) / 2;
}
scale_x = draw_w / (float)rw;
scale_y = draw_h / (float)rh;
scale_x = draw_w / float(rw);
scale_y = draw_h / float(rh);
/* If the image is squared, the `draw_*` initialization values are good. */
}
@ -1849,7 +1849,7 @@ static void icon_draw_size(float x,
const IconTextOverlay *text_overlay)
{
bTheme *btheme = UI_GetTheme();
const float fdraw_size = (float)draw_size;
const float fdraw_size = float(draw_size);
Icon *icon = BKE_icon_get(icon_id);
alpha *= btheme->tui.icon_alpha;
@ -1863,7 +1863,7 @@ static void icon_draw_size(float x,
/* scale width and height according to aspect */
int w = (int)(fdraw_size / aspect + 0.5f);
int h = (int)(fdraw_size / aspect + 0.5f);
int h = int(fdraw_size / aspect + 0.5f);
DrawInfo *di = icon_ensure_drawinfo(icon);
@ -1880,14 +1880,14 @@ static void icon_draw_size(float x,
else if (di->type == ICON_TYPE_VECTOR) {
/* vector icons use the uiBlock transformation, they are not drawn
* with untransformed coordinates like the other icons */
di->data.vector.func((int)x, (int)y, w, h, 1.0f);
di->data.vector.func(int(x), int(y), w, h, 1.0f);
}
else if (di->type == ICON_TYPE_GEOM) {
#ifdef USE_UI_TOOLBAR_HACK
/* TODO(@campbellbarton): scale icons up for toolbar,
* we need a way to detect larger buttons and do this automatic. */
{
float scale = (float)ICON_DEFAULT_HEIGHT_TOOLBAR / (float)ICON_DEFAULT_HEIGHT;
float scale = float(ICON_DEFAULT_HEIGHT_TOOLBAR) / float(ICON_DEFAULT_HEIGHT);
y = (y + (h / 2)) - ((h * scale) / 2);
w *= scale;
h *= scale;
@ -1926,8 +1926,8 @@ static void icon_draw_size(float x,
/* texture image use premul alpha for correct scaling */
icon_draw_texture(x,
y,
(float)w,
(float)h,
float(w),
float(h),
di->data.texture.x,
di->data.texture.y,
di->data.texture.w,
@ -1954,15 +1954,15 @@ static void icon_draw_size(float x,
uint border_texel = 0;
#ifndef WITH_HEADLESS
if (with_border) {
const float scale = (float)ICON_GRID_W / (float)ICON_DEFAULT_WIDTH;
const float scale = float(ICON_GRID_W) / float(ICON_DEFAULT_WIDTH);
border_texel = ICON_MONO_BORDER_OUTSET;
border_outset = ICON_MONO_BORDER_OUTSET / (scale * aspect);
}
#endif
icon_draw_texture(x - border_outset,
y - border_outset,
(float)w + 2 * border_outset,
(float)h + 2 * border_outset,
float(w) + 2 * border_outset,
float(h) + 2 * border_outset,
di->data.texture.x - border_texel,
di->data.texture.y - border_texel,
di->data.texture.w + 2 * border_texel,
@ -2009,7 +2009,7 @@ static void icon_draw_size(float x,
/* Just draw a colored rect - Like for vicon_colorset_draw() */
#ifndef WITH_HEADLESS
vicon_gplayer_color_draw(icon, (int)x, (int)y, w, h);
vicon_gplayer_color_draw(icon, int(x), int(y), w, h);
#endif
}
}

View File

@ -237,9 +237,9 @@ static int ui_item_fit(
return available - pos;
}
const float width = *extra_pixel + (item * available) / (float)all;
*extra_pixel = width - (int)width;
return (int)width;
const float width = *extra_pixel + (item * available) / float(all);
*extra_pixel = width - int(width);
return int(width);
}
/* contents is smaller or equal to available space */
@ -248,9 +248,9 @@ static int ui_item_fit(
return available - pos;
}
const float width = *extra_pixel + (item * available) / (float)all;
*extra_pixel = width - (int)width;
return (int)width;
const float width = *extra_pixel + (item * available) / float(all);
*extra_pixel = width - int(width);
return int(width);
}
return item;
}
@ -1508,7 +1508,7 @@ void uiItemsFullEnumO_items(uiLayout *layout,
bool last_iter = false;
const EnumPropertyItem *item = item_array;
for (int i = 1; item->identifier && !last_iter; i++, item++) {
/* handle oversized pies */
/* Handle over-sized pies. */
if (radial && (totitem > PIE_MAX_ITEMS) && (i >= PIE_MAX_ITEMS)) {
if (item->name) { /* only visible items */
const EnumPropertyItem *tmp;
@ -4316,7 +4316,7 @@ static void ui_litem_grid_flow_compute(ListBase *items,
ui_item_size(item, &item_w, &item_h);
global_avg_w += (float)(item_w * item_w);
global_totweight_w += (float)item_w;
global_totweight_w += float(item_w);
global_max_h = max_ii(global_max_h, item_h);
if (parameters->tot_rows != 0 && parameters->tot_columns != 0) {
@ -4325,8 +4325,8 @@ static void ui_litem_grid_flow_compute(ListBase *items,
const int index_row = parameters->row_major ? i / parameters->tot_columns :
i % parameters->tot_rows;
avg_w[index_col] += (float)(item_w * item_w);
totweight_w[index_col] += (float)item_w;
avg_w[index_col] += float(item_w * item_w);
totweight_w[index_col] += float(item_w);
max_h[index_row] = max_ii(max_h[index_row], item_h);
}
@ -4407,7 +4407,7 @@ static void ui_litem_grid_flow_compute(ListBase *items,
*results->global_max_h = global_max_h;
}
if (results->tot_w) {
*results->tot_w = (int)tot_w + parameters->space_x * (parameters->tot_columns - 1);
*results->tot_w = int(tot_w) + parameters->space_x * (parameters->tot_columns - 1);
}
if (results->tot_h) {
*results->tot_h = tot_h + parameters->space_y * (parameters->tot_rows - 1);
@ -4463,7 +4463,7 @@ static void ui_litem_estimate_grid_flow(uiLayout *litem)
gflow->tot_columns = min_ii(max_ii((int)(litem->w / avg_w), 1), gflow->tot_items);
}
}
gflow->tot_rows = (int)ceilf((float)gflow->tot_items / gflow->tot_columns);
gflow->tot_rows = (int)ceilf(float(gflow->tot_items) / gflow->tot_columns);
/* Try to tweak number of columns and rows to get better filling of last column or row,
* and apply 'modulo' value to number of columns or rows.
@ -4479,9 +4479,9 @@ static void ui_litem_estimate_grid_flow(uiLayout *litem)
gflow->tot_columns = gflow->tot_columns - (gflow->tot_columns % modulo);
}
/* Find smallest number of columns conserving computed optimal number of rows. */
for (gflow->tot_rows = (int)ceilf((float)gflow->tot_items / gflow->tot_columns);
for (gflow->tot_rows = (int)ceilf(float(gflow->tot_items) / gflow->tot_columns);
(gflow->tot_columns - step) > 0 &&
(int)ceilf((float)gflow->tot_items / (gflow->tot_columns - step)) <= gflow->tot_rows;
(int)ceilf(float(gflow->tot_items) / (gflow->tot_columns - step)) <= gflow->tot_rows;
gflow->tot_columns -= step) {
/* pass */
}
@ -4493,9 +4493,9 @@ static void ui_litem_estimate_grid_flow(uiLayout *litem)
gflow->tot_items);
}
/* Find smallest number of rows conserving computed optimal number of columns. */
for (gflow->tot_columns = (int)ceilf((float)gflow->tot_items / gflow->tot_rows);
for (gflow->tot_columns = (int)ceilf(float(gflow->tot_items) / gflow->tot_rows);
(gflow->tot_rows - step) > 0 &&
(int)ceilf((float)gflow->tot_items / (gflow->tot_rows - step)) <= gflow->tot_columns;
(int)ceilf(float(gflow->tot_items) / (gflow->tot_rows - step)) <= gflow->tot_columns;
gflow->tot_rows -= step) {
/* pass */
}
@ -4646,10 +4646,10 @@ static void ui_litem_layout_absolute(uiLayout *litem)
toth -= miny;
if (litem->w && totw > 0) {
scalex = (float)litem->w / (float)totw;
scalex = float(litem->w) / float(totw);
}
if (litem->h && toth > 0) {
scaley = (float)litem->h / (float)toth;
scaley = float(litem->h) / float(toth);
}
x = litem->x;
@ -4700,7 +4700,7 @@ static void ui_litem_layout_split(uiLayout *litem)
int x = litem->x;
const int y = litem->y;
const float percentage = (split->percentage == 0.0f) ? 1.0f / (float)tot : split->percentage;
const float percentage = (split->percentage == 0.0f) ? 1.0f / float(tot) : split->percentage;
const int w = (litem->w - (tot - 1) * litem->space);
int colw = w * percentage;
@ -4714,9 +4714,9 @@ static void ui_litem_layout_split(uiLayout *litem)
x += colw;
if (item->next) {
const float width = extra_pixel + (w - (int)(w * percentage)) / ((float)tot - 1);
extra_pixel = width - (int)width;
colw = (int)width;
const float width = extra_pixel + (w - (int)(w * percentage)) / (float(tot) - 1);
extra_pixel = width - int(width);
colw = int(width);
colw = MAX2(colw, 0);
x += litem->space;
@ -6010,7 +6010,7 @@ void UI_paneltype_draw(bContext *C, PanelType *pt, uiLayout *layout)
static void ui_layout_introspect_button(DynStr *ds, uiButtonItem *bitem)
{
uiBut *but = bitem->but;
BLI_dynstr_appendf(ds, "'type':%d, ", (int)but->type);
BLI_dynstr_appendf(ds, "'type':%d, ", int(but->type));
BLI_dynstr_appendf(ds, "'draw_string':'''%s''', ", but->drawstr);
/* Not exactly needed, rna has this. */
BLI_dynstr_appendf(ds, "'tip':'''%s''', ", but->tip ? but->tip : "");
@ -6136,7 +6136,7 @@ uiLayout *uiItemsAlertBox(uiBlock *block, const int size, const eAlertIcon icon)
* making the icon placement more symmetrical, between the block edge and the text. */
const float icon_padding = 5.0f * U.dpi_fac;
/* Calculate the factor of the fixed icon column depending on the block width. */
const float split_factor = ((float)icon_size + icon_padding) /
const float split_factor = (float(icon_size) + icon_padding) /
(float)(dialog_width - style->columnspace);
uiLayout *block_layout = UI_block_layout(

View File

@ -36,6 +36,8 @@
# include "BLI_math_base.h" /* M_PI */
#endif
static void fontstyle_set_ex(const uiFontStyle *fs, const float dpi_fac);
/* style + theme + layout-engine = UI */
/**
@ -347,21 +349,10 @@ int UI_fontstyle_string_width_with_block_aspect(const uiFontStyle *fs,
const char *str,
const float aspect)
{
uiFontStyle fs_buf;
if (aspect != 1.0f) {
fs_buf = *fs;
ui_fontscale(&fs_buf.points, aspect);
fs = &fs_buf;
}
int width = UI_fontstyle_string_width(fs, str);
if (aspect != 1.0f) {
/* While in most cases rounding up isn't important, it can make a difference
* with small fonts (3px or less), zooming out in the node-editor for e.g. */
width = int(ceilf(width * aspect));
}
return width;
/* FIXME(@campbellbarton): the final scale of the font is rounded which should be accounted for.
* Failing to do so causes bad alignment when zoomed out very far in the node-editor. */
fontstyle_set_ex(fs, U.dpi_fac / aspect);
return int(BLF_width(fs->uifont_id, str, BLF_DRAW_STR_DUMMY_MAX) * aspect);
}
int UI_fontstyle_height_max(const uiFontStyle *fs)
@ -492,9 +483,14 @@ void uiStyleInit(void)
BLF_load_font_stack();
}
void UI_fontstyle_set(const uiFontStyle *fs)
static void fontstyle_set_ex(const uiFontStyle *fs, const float dpi_fac)
{
uiFont *font = uifont_to_blfont(fs->uifont_id);
BLF_size(font->blf_id, fs->points * U.dpi_fac);
BLF_size(font->blf_id, fs->points * dpi_fac);
}
void UI_fontstyle_set(const uiFontStyle *fs)
{
fontstyle_set_ex(fs, U.dpi_fac);
}

View File

@ -5407,8 +5407,8 @@ static void CurveProfile_buttons_layout(uiLayout *layout, PointerRNA *ptr, RNAUp
"",
0,
0,
(short)path_width,
(short)path_height,
short(path_width),
short(path_height),
profile,
0.0f,
1.0f,
@ -6106,7 +6106,7 @@ static char *progress_tooltip_func(bContext * /*C*/, void *argN, const char * /*
BLI_timecode_string_from_time_simple(elapsed_str, sizeof(elapsed_str), elapsed);
if (progress) {
const double remaining = (elapsed / (double)progress) - elapsed;
const double remaining = (elapsed / double(progress)) - elapsed;
BLI_timecode_string_from_time_simple(remaining_str, sizeof(remaining_str), remaining);
}

View File

@ -881,22 +881,22 @@ static void shape_preset_init_trias_ex(uiWidgetTrias *tria,
/* center position and size */
float centx = (float)rect->xmin + 0.4f * minsize;
float centy = (float)rect->ymin + 0.5f * minsize;
float centy = float(rect->ymin) + 0.5f * minsize;
tria->size = sizex = sizey = -0.5f * triasize * minsize;
if (where == 'r') {
centx = (float)rect->xmax - 0.4f * minsize;
centx = float(rect->xmax) - 0.4f * minsize;
sizex = -sizex;
}
else if (where == 't') {
centx = (float)rect->xmin + 0.5f * minsize;
centy = (float)rect->ymax - 0.5f * minsize;
centx = float(rect->xmin) + 0.5f * minsize;
centy = float(rect->ymax) - 0.5f * minsize;
sizey = -sizey;
i2 = 0;
i1 = 1;
}
else if (where == 'b') {
centx = (float)rect->xmin + 0.5f * minsize;
centx = float(rect->xmin) + 0.5f * minsize;
sizex = -sizex;
i2 = 0;
i1 = 1;
@ -1515,7 +1515,7 @@ static void ui_text_clip_right_ex(const uiFontStyle *fstyle,
l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth, nullptr);
str[l_end] = '\0';
if (r_final_len) {
*r_final_len = (size_t)l_end;
*r_final_len = size_t(l_end);
}
}
}
@ -2134,7 +2134,7 @@ static void widget_draw_text(const uiFontStyle *fstyle,
(bounds.xmax - bounds.xmin - ul_width) / 2;
int pos_y = rect->ymin + font_yofs + bounds.ymin - U.pixelsize;
/* Use text output because direct drawing doesn't always work. See T89246. */
BLF_position(fstyle->uifont_id, (float)pos_x, pos_y, 0.0f);
BLF_position(fstyle->uifont_id, float(pos_x), pos_y, 0.0f);
BLF_color4ubv(fstyle->uifont_id, wcol->text);
BLF_draw(fstyle->uifont_id, "_", 2);
}
@ -2227,7 +2227,7 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle,
rcti *rect)
{
const bool show_menu_icon = ui_but_draw_menu_icon(but);
const float alpha = (float)wcol->text[3] / 255.0f;
const float alpha = float(wcol->text[3]) / 255.0f;
char password_str[UI_MAX_DRAW_STR];
bool no_text_padding = but->drawflag & UI_BUT_NO_TEXT_PADDING;
@ -2739,10 +2739,10 @@ static void widget_softshadow(const rcti *rect, int roundboxalign, const float r
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
for (int step = 1; step <= (int)radout; step++) {
for (int step = 1; step <= int(radout); step++) {
const float expfac = sqrtf(step / radout);
round_box_shadow_edges(wtb.outer_v, &rect1, radin, UI_CNR_ALL, (float)step);
round_box_shadow_edges(wtb.outer_v, &rect1, radin, UI_CNR_ALL, float(step));
immUniformColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac));
@ -2819,7 +2819,7 @@ void ui_hsvcircle_vals_from_pos(
const float dist_sq = len_squared_v2(m_delta);
*r_val_dist = (dist_sq < (radius * radius)) ? sqrtf(dist_sq) / radius : 1.0f;
*r_val_rad = atan2f(m_delta[0], m_delta[1]) / (2.0f * (float)M_PI) + 0.5f;
*r_val_rad = atan2f(m_delta[0], m_delta[1]) / (2.0f * float(M_PI)) + 0.5f;
}
void ui_hsvcircle_pos_from_vals(
@ -2830,7 +2830,7 @@ void ui_hsvcircle_pos_from_vals(
const float centy = BLI_rcti_cent_y_fl(rect);
const float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f;
const float ang = 2.0f * (float)M_PI * hsv[0] + (float)M_PI_2;
const float ang = 2.0f * float(M_PI) * hsv[0] + float(M_PI_2);
float radius_t;
if (cpicker->use_color_cubic && (U.color_picker_type == USER_CP_CIRCLE_HSV)) {
@ -2850,7 +2850,7 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, const uiWidgetColors *wcol, const
/* TODO(merwin): reimplement as shader for pixel-perfect colors */
const int tot = 64;
const float radstep = 2.0f * (float)M_PI / (float)tot;
const float radstep = 2.0f * float(M_PI) / float(tot);
const float centx = BLI_rcti_cent_x_fl(rect);
const float centy = BLI_rcti_cent_y_fl(rect);
const float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f;
@ -3685,7 +3685,7 @@ static void widget_nodesocket(uiBut *but,
rect->ymax = cent_y + radi;
wtb.draw_outline = true;
round_box_edges(&wtb, UI_CNR_ALL, rect, (float)radi);
round_box_edges(&wtb, UI_CNR_ALL, rect, float(radi));
widgetbase_draw(&wtb, wcol);
copy_v3_v3_uchar(wcol->inner, old_inner);
@ -4979,9 +4979,9 @@ static void ui_draw_clip_tri(uiBlock *block, rcti *rect, uiWidgetType *wt)
float draw_color[4];
const uchar *color = wt->wcol.text;
draw_color[0] = ((float)color[0]) / 255.0f;
draw_color[1] = ((float)color[1]) / 255.0f;
draw_color[2] = ((float)color[2]) / 255.0f;
draw_color[0] = (float(color[0])) / 255.0f;
draw_color[1] = (float(color[1])) / 255.0f;
draw_color[2] = (float(color[2])) / 255.0f;
draw_color[3] = 1.0f;
if (block->flag & UI_BLOCK_CLIPTOP) {
@ -5183,18 +5183,12 @@ void ui_draw_pie_center(uiBlock *block)
btheme->tui.wcol_pie_menu.inner,
btheme->tui.wcol_pie_menu.shadetop,
btheme->tui.wcol_pie_menu.shadedown);
draw_disk_shaded(0.0f,
(float)(M_PI * 2.0),
pie_radius_internal,
pie_radius_external,
subd,
col1,
col2,
true);
draw_disk_shaded(
0.0f, float(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, col1, col2, true);
}
else {
draw_disk_shaded(0.0f,
(float)(M_PI * 2.0),
float(M_PI * 2.0),
pie_radius_internal,
pie_radius_external,
subd,
@ -5492,7 +5486,7 @@ void ui_draw_preview_item_stateless(const uiFontStyle *fstyle,
char drawstr[UI_MAX_DRAW_STR];
const float okwidth = (float)BLI_rcti_size_x(&trect);
const size_t max_len = sizeof(drawstr);
const float minwidth = (float)(UI_DPI_ICON_SIZE);
const float minwidth = float(UI_DPI_ICON_SIZE);
BLI_strncpy(drawstr, name, sizeof(drawstr));
UI_text_clip_middle_ex(fstyle, drawstr, okwidth, minwidth, max_len, '\0');

View File

@ -49,10 +49,10 @@ static const EnumPropertyItem io_obj_export_evaluation_mode[] = {
{0, NULL, 0, NULL, NULL}};
static const EnumPropertyItem io_obj_path_mode[] = {
{PATH_REFERENCE_AUTO, "AUTO", 0, "Auto", "Use Relative paths with subdirectories only"},
{PATH_REFERENCE_AUTO, "AUTO", 0, "Auto", "Use relative paths with subdirectories only"},
{PATH_REFERENCE_ABSOLUTE, "ABSOLUTE", 0, "Absolute", "Always write absolute paths"},
{PATH_REFERENCE_RELATIVE, "RELATIVE", 0, "Relative", "Write relative paths where possible"},
{PATH_REFERENCE_MATCH, "MATCH", 0, "Match", "Match Absolute/Relative setting with input path"},
{PATH_REFERENCE_MATCH, "MATCH", 0, "Match", "Match absolute/relative setting with input path"},
{PATH_REFERENCE_STRIP, "STRIP", 0, "Strip", "Write filename only"},
{PATH_REFERENCE_COPY, "COPY", 0, "Copy", "Copy the file to the destination path"},
{0, NULL, 0, NULL, NULL}};

View File

@ -382,7 +382,7 @@ static bool screen_areas_can_align(bScreen *screen, ScrArea *sa1, ScrArea *sa2,
const short xmin = MIN2(sa1->v1->vec.x, sa2->v1->vec.x);
const short xmax = MAX2(sa1->v3->vec.x, sa2->v3->vec.x);
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
if (area == sa1 || area == sa2) {
if (ELEM(area, sa1, sa2)) {
continue;
}
if (area->v3->vec.x - area->v1->vec.x < tolerance &&
@ -396,7 +396,7 @@ static bool screen_areas_can_align(bScreen *screen, ScrArea *sa1, ScrArea *sa2,
const short ymin = MIN2(sa1->v1->vec.y, sa2->v1->vec.y);
const short ymax = MAX2(sa1->v3->vec.y, sa2->v3->vec.y);
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
if (area == sa1 || area == sa2) {
if (ELEM(area, sa1, sa2)) {
continue;
}
if (area->v3->vec.y - area->v1->vec.y < tolerance &&

View File

@ -175,8 +175,8 @@ static void load_tex_task_cb_ex(void *__restrict userdata,
int index = j * size + i;
float x = (float)i / size;
float y = (float)j / size;
float x = float(i) / size;
float y = float(j) / size;
float len;
if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) {
@ -375,8 +375,8 @@ static void load_tex_cursor_task_cb(void *__restrict userdata,
/* Largely duplicated from tex_strength. */
const int index = j * size + i;
const float x = (((float)i / size) - 0.5f) * 2.0f;
const float y = (((float)j / size) - 0.5f) * 2.0f;
const float x = ((float(i) / size) - 0.5f) * 2.0f;
const float y = ((float(j) / size) - 0.5f) * 2.0f;
const float len = sqrtf(x * x + y * y);
if (len <= 1.0f) {
@ -1105,7 +1105,7 @@ static void cursor_draw_point_with_symmetry(const uint gpuattr,
/* Radial Symmetry. */
for (char raxis = 0; raxis < 3; raxis++) {
for (int r = 1; r < sd->radial_symm[raxis]; r++) {
float angle = 2 * M_PI * r / sd->radial_symm[(int)raxis];
float angle = 2 * M_PI * r / sd->radial_symm[int(raxis)];
flip_v3_v3(location, true_location, ePaintSymmetryFlags(i));
unit_m4(symm_rot_mat);
rotate_m4(symm_rot_mat, raxis + 'X', angle);
@ -1286,8 +1286,8 @@ static bool paint_cursor_context_init(bContext *C,
pcontext->x = x;
pcontext->y = y;
pcontext->translation[0] = (float)x;
pcontext->translation[1] = (float)y;
pcontext->translation[0] = float(x);
pcontext->translation[1] = float(y);
float zoomx, zoomy;
get_imapaint_zoom(C, &zoomx, &zoomy);

View File

@ -540,8 +540,8 @@ static int project_paint_face_paint_tile(Image *ima, const float *uv)
}
/* Currently, faces are assumed to belong to one tile, so checking the first loop is enough. */
int tx = (int)uv[0];
int ty = (int)uv[1];
int tx = int(uv[0]);
int ty = int(uv[1]);
return 1001 + 10 * ty + tx;
}
@ -782,8 +782,8 @@ static bool project_paint_PickColor(
// if (xi < 0 || xi >= ibuf->x || yi < 0 || yi >= ibuf->y) return false;
/* wrap */
xi = mod_i((int)(uv[0] * ibuf->x), ibuf->x);
yi = mod_i((int)(uv[1] * ibuf->y), ibuf->y);
xi = mod_i(int(uv[0] * ibuf->x), ibuf->x);
yi = mod_i(int(uv[1] * ibuf->y), ibuf->y);
if (rgba) {
if (ibuf->rect_float) {
@ -1303,8 +1303,8 @@ static void uv_image_outset(const ProjPaintState *ps,
float ibuf_inv[2];
ibuf_inv[0] = 1.0f / (float)ibuf_x;
ibuf_inv[1] = 1.0f / (float)ibuf_y;
ibuf_inv[0] = 1.0f / float(ibuf_x);
ibuf_inv[1] = 1.0f / float(ibuf_y);
for (fidx[0] = 0; fidx[0] < 3; fidx[0]++) {
LoopSeamData *seam_data;
@ -1944,8 +1944,8 @@ static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps,
}
/* which bounding box cell are we in?, needed for undo */
projPixel->bb_cell_index = (int)(((float)x_px / (float)ibuf->x) * PROJ_BOUNDBOX_DIV) +
(int)(((float)y_px / (float)ibuf->y) * PROJ_BOUNDBOX_DIV) *
projPixel->bb_cell_index = (int)((float(x_px) / float(ibuf->x)) * PROJ_BOUNDBOX_DIV) +
(int)((float(y_px) / float(ibuf->y)) * PROJ_BOUNDBOX_DIV) *
PROJ_BOUNDBOX_DIV;
/* done with view3d_project_float inline */
@ -2768,8 +2768,8 @@ static void project_bucket_clip_face(const bool is_ortho,
cent[0] += isectVCosSS[i][0];
cent[1] += isectVCosSS[i][1];
}
cent[0] = cent[0] / (float)(*tot);
cent[1] = cent[1] / (float)(*tot);
cent[0] = cent[0] / float(*tot);
cent[1] = cent[1] / float(*tot);
/* Collect angles for every point around the center point */
@ -3021,7 +3021,7 @@ static void project_paint_face_init(const ProjPaintState *ps,
/* Bucket bounds in UV space so we can init pixels only for this face. */
float lt_uv_pxoffset[3][2];
float xhalfpx, yhalfpx;
const float ibuf_xf = (float)ibuf->x, ibuf_yf = (float)ibuf->y;
const float ibuf_xf = float(ibuf->x), ibuf_yf = float(ibuf->y);
/* for early loop exit */
int has_x_isect = 0, has_isect = 0;
@ -3104,13 +3104,13 @@ static void project_paint_face_init(const ProjPaintState *ps,
for (y = bounds_px.ymin; y < bounds_px.ymax; y++) {
// uv[1] = (((float)y) + 0.5f) / (float)ibuf->y;
/* use pixel offset UV coords instead */
uv[1] = (float)y / ibuf_yf;
uv[1] = float(y) / ibuf_yf;
has_x_isect = 0;
for (x = bounds_px.xmin; x < bounds_px.xmax; x++) {
// uv[0] = (((float)x) + 0.5f) / ibuf->x;
/* use pixel offset UV coords instead */
uv[0] = (float)x / ibuf_xf;
uv[0] = float(x) / ibuf_xf;
/* Note about IsectPoly2Df_twoside, checking the face or uv flipping doesn't work,
* could check the poly direction but better to do this */
@ -3314,15 +3314,15 @@ static void project_paint_face_init(const ProjPaintState *ps,
for (y = bounds_px.ymin; y < bounds_px.ymax; y++) {
// uv[1] = (((float)y) + 0.5f) / (float)ibuf->y;
/* use offset uvs instead */
uv[1] = (float)y / ibuf_yf;
uv[1] = float(y) / ibuf_yf;
has_x_isect = 0;
for (x = bounds_px.xmin; x < bounds_px.xmax; x++) {
const float puv[2] = {(float)x, (float)y};
const float puv[2] = {float(x), float(y)};
bool in_bounds;
// uv[0] = (((float)x) + 0.5f) / (float)ibuf->x;
/* use offset uvs instead */
uv[0] = (float)x / ibuf_xf;
uv[0] = float(x) / ibuf_xf;
/* test we're inside uvspace bucket and triangle bounds */
if (equals_v2v2(seam_uvs[0], seam_uvs[1])) {
@ -3371,7 +3371,7 @@ static void project_paint_face_init(const ProjPaintState *ps,
mul_m4_v4((float(*)[4])ps->projectMat, pixel_on_edge);
pixel_on_edge[0] = (float)(ps->winx * 0.5f) +
(ps->winx * 0.5f) * pixel_on_edge[0] / pixel_on_edge[3];
pixel_on_edge[1] = (float)(ps->winy * 0.5f) +
pixel_on_edge[1] = float(ps->winy * 0.5f) +
(ps->winy * 0.5f) * pixel_on_edge[1] / pixel_on_edge[3];
/* Use the depth for bucket point occlusion */
pixel_on_edge[2] = pixel_on_edge[2] / pixel_on_edge[3];
@ -3854,21 +3854,21 @@ static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int di
if (ps->source == PROJ_SRC_VIEW) {
#ifdef PROJ_DEBUG_WINCLIP
CLAMP(ps->screenMin[0], (float)(-diameter), (float)(ps->winx + diameter));
CLAMP(ps->screenMax[0], (float)(-diameter), (float)(ps->winx + diameter));
CLAMP(ps->screenMin[0], float(-diameter), float(ps->winx + diameter));
CLAMP(ps->screenMax[0], float(-diameter), float(ps->winx + diameter));
CLAMP(ps->screenMin[1], (float)(-diameter), (float)(ps->winy + diameter));
CLAMP(ps->screenMax[1], (float)(-diameter), (float)(ps->winy + diameter));
CLAMP(ps->screenMin[1], float(-diameter), float(ps->winy + diameter));
CLAMP(ps->screenMax[1], float(-diameter), float(ps->winy + diameter));
#else
UNUSED_VARS(diameter);
#endif
}
else if (ps->source != PROJ_SRC_VIEW_FILL) { /* re-projection, use bounds */
ps->screenMin[0] = 0;
ps->screenMax[0] = (float)(ps->winx);
ps->screenMax[0] = float(ps->winx);
ps->screenMin[1] = 0;
ps->screenMax[1] = (float)(ps->winy);
ps->screenMax[1] = float(ps->winy);
}
}
@ -3899,7 +3899,7 @@ static void proj_paint_state_cavity_init(ProjPaintState *ps)
if (counter[a] > 0) {
mul_v3_fl(edges[a], 1.0f / counter[a]);
/* Augment the difference. */
cavities[a] = saacos(10.0f * dot_v3v3(ps->vert_normals[a], edges[a])) * (float)M_1_PI;
cavities[a] = saacos(10.0f * dot_v3v3(ps->vert_normals[a], edges[a])) * float(M_1_PI);
}
else {
cavities[a] = 0.0;
@ -4535,8 +4535,8 @@ static void project_paint_begin(const bContext *C,
ps->screen_width = ps->screenMax[0] - ps->screenMin[0];
ps->screen_height = ps->screenMax[1] - ps->screenMin[1];
ps->buckets_x = (int)(ps->screen_width / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
ps->buckets_y = (int)(ps->screen_height / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
ps->buckets_x = (int)(ps->screen_width / ((float(diameter)) / PROJ_BUCKET_BRUSH_DIV));
ps->buckets_y = int(ps->screen_height / (float(diameter) / PROJ_BUCKET_BRUSH_DIV));
// printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, ps->buckets_y);
@ -4934,7 +4934,7 @@ static void do_projectpaint_soften_f(ProjPaintState *ps,
}
if (LIKELY(accum_tot != 0)) {
mul_v4_fl(rgba, 1.0f / (float)accum_tot);
mul_v4_fl(rgba, 1.0f / float(accum_tot));
if (ps->mode == BRUSH_STROKE_INVERT) {
/* subtract blurred image from normal image gives high pass filter */
@ -4997,7 +4997,7 @@ static void do_projectpaint_soften(ProjPaintState *ps,
if (LIKELY(accum_tot != 0)) {
uchar *rgba_ub = projPixel->newColor.ch;
mul_v4_fl(rgba, 1.0f / (float)accum_tot);
mul_v4_fl(rgba, 1.0f / float(accum_tot));
if (ps->mode == BRUSH_STROKE_INVERT) {
float rgba_pixel[4];
@ -5281,7 +5281,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v
}
}
BKE_colorband_evaluate(brush->gradient, f, color_f);
color_f[3] *= ((float)projPixel->mask) * (1.0f / 65535.0f) * brush_alpha;
color_f[3] *= (float(projPixel->mask)) * (1.0f / 65535.0f) * brush_alpha;
if (is_floatbuf) {
/* Convert to premutliplied. */
@ -5311,7 +5311,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v
else {
if (is_floatbuf) {
float newColor_f[4];
newColor_f[3] = ((float)projPixel->mask) * (1.0f / 65535.0f) * brush_alpha;
newColor_f[3] = (float(projPixel->mask)) * (1.0f / 65535.0f) * brush_alpha;
copy_v3_v3(newColor_f, ps->paint_color_linear);
IMB_blend_color_float(projPixel->pixel.f_pt,
@ -5320,7 +5320,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v
IMB_BlendMode(ps->blend));
}
else {
float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
float mask = float(projPixel->mask) * (1.0f / 65535.0f);
projPixel->newColor.ch[3] = mask * 255 * brush_alpha;
rgb_float_to_uchar(projPixel->newColor.ch, ps->paint_color);
@ -5348,7 +5348,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v
projPixel->projCoSS[0],
projPixel->projCoSS[1]);
if (projPixel->newColor.f[3]) {
float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
float mask = (float(projPixel->mask)) * (1.0f / 65535.0f);
mul_v4_v4fl(projPixel->newColor.f, projPixel->newColor.f, mask);
@ -5365,7 +5365,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v
projPixel->projCoSS[0],
projPixel->projCoSS[1]);
if (projPixel->newColor.ch[3]) {
float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
float mask = (float(projPixel->mask)) * (1.0f / 65535.0f);
projPixel->newColor.ch[3] *= mask;
blend_color_mix_byte(
@ -5395,7 +5395,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v
float mask;
/* Extra mask for normal, layer stencil, etc. */
float custom_mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
float custom_mask = (float(projPixel->mask)) * (1.0f / 65535.0f);
/* Mask texture. */
if (ps->is_maskbrush) {
@ -5451,7 +5451,7 @@ static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v
}
mask = min_ff(mask, 65535.0f);
mask_short = (ushort)mask;
mask_short = ushort(mask);
if (mask_short > *projPixel->mask_accum) {
*projPixel->mask_accum = mask_short;
@ -5794,7 +5794,7 @@ void paint_proj_stroke(const bContext *C,
View3D *v3d = CTX_wm_view3d(C);
ARegion *region = CTX_wm_region(C);
float *cursor = scene->cursor.location;
const int mval_i[2] = {(int)pos[0], (int)pos[1]};
const int mval_i[2] = {(int)pos[0], int(pos[1])};
view3d_operator_needs_opengl(C);
@ -5907,8 +5907,8 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
ps->normal_angle_inner = ps->normal_angle = settings->imapaint.normal_angle;
}
ps->normal_angle_inner *= (float)(M_PI_2 / 90);
ps->normal_angle *= (float)(M_PI_2 / 90);
ps->normal_angle_inner *= float(M_PI_2 / 90);
ps->normal_angle *= float(M_PI_2 / 90);
ps->normal_angle_range = ps->normal_angle - ps->normal_angle_inner;
if (ps->normal_angle_range <= 0.0f) {

View File

@ -824,7 +824,7 @@ static void sculpt_vertex_neighbors_get_bmesh(PBVHVertRef vertex, SculptVertexNe
const BMVert *v_other = adj_v[i];
if (v_other != v) {
sculpt_vertex_neighbor_add(
iter, BKE_pbvh_make_vref((intptr_t)v_other), BM_elem_index_get(v_other));
iter, BKE_pbvh_make_vref(intptr_t(v_other)), BM_elem_index_get(v_other));
}
}
}

View File

@ -1091,7 +1091,7 @@ static void snap_calc_uv_fn(TransInfo *t, float *UNUSED(vec))
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
t->scene, t->view_layer, nullptr, &objects_len);
float dist_sq = square_f((float)SNAP_MIN_DISTANCE);
float dist_sq = square_f(float(SNAP_MIN_DISTANCE));
if (ED_uvedit_nearest_uv_multi(&t->region->v2d,
t->scene,
objects,

View File

@ -204,11 +204,11 @@ static void generate_next_domains(uint8_t domains[][BDS],
bd[LL] - l_len,
bd[RL] - r_len,
bd[ADJ],
(uint8_t)(cur_pos));
uint8_t(cur_pos));
bound += std::min(bd[LL] - l_len, bd[RL] - r_len);
}
if (l_len && r_len) {
add_bidomain(domains, bd_pos, bd[L], bd[R], l_len, r_len, true, (uint8_t)(cur_pos));
add_bidomain(domains, bd_pos, bd[L], bd[R], l_len, r_len, true, uint8_t(cur_pos));
bound += std::min(l_len, r_len);
}
}
@ -351,7 +351,7 @@ static void maximum_common_subgraph_internal(
bd[W] = w; /* Store the W used for this iteration. */
cur[bd[P]][L] = v;
cur[bd[P]][R] = w;
update_incumbent(cur, incumbent, bd[P] + (uint8_t)1, inc_pos);
update_incumbent(cur, incumbent, bd[P] + uint8_t(1), inc_pos);
generate_next_domains(
domains, &bd_pos, bd[P] + 1, left, right, v, w, *inc_pos, adjmat0, adjmat1);
}

View File

@ -42,8 +42,8 @@ static void mul_v2_m2_add_v2v2(float r[2],
const float b[2])
{
/* Compute `r = mat * (a + b)` with high precision. */
const double x = static_cast<double>(a[0]) + static_cast<double>(b[0]);
const double y = static_cast<double>(a[1]) + static_cast<double>(b[1]);
const double x = static_cast<double>(a[0]) + double(b[0]);
const double y = static_cast<double>(a[1]) + double(b[1]);
r[0] = static_cast<float>(mat[0][0] * x + mat[1][0] * y);
r[1] = static_cast<float>(mat[0][1] * x + mat[1][1] * y);

View File

@ -16,7 +16,6 @@
#include "GEO_mesh_merge_by_distance.hh"
//#define USE_WELD_DEBUG
//#define USE_WELD_NORMALS
namespace blender::geometry {
@ -27,21 +26,8 @@ namespace blender::geometry {
/* indicates whether an edge or vertex in groups_map will be merged. */
#define ELEM_MERGED int(-2)
/* Used to indicate a range in an array specifying a group. */
struct WeldGroup {
int len;
int ofs;
};
/* Edge groups that will be merged. Final vertices are also indicated. */
struct WeldGroupEdge {
struct WeldGroup group;
int v1;
int v2;
};
struct WeldVert {
/* Indexes relative to the original Mesh. */
/* Indices relative to the original Mesh. */
int vert_dest;
int vert_orig;
};
@ -50,7 +36,7 @@ struct WeldEdge {
union {
int flag;
struct {
/* Indexes relative to the original Mesh. */
/* Indices relative to the original Mesh. */
int edge_dest;
int edge_orig;
int vert_a;
@ -63,7 +49,7 @@ struct WeldLoop {
union {
int flag;
struct {
/* Indexes relative to the original Mesh. */
/* Indices relative to the original Mesh. */
int vert;
int edge;
int loop_orig;
@ -76,7 +62,7 @@ struct WeldPoly {
union {
int flag;
struct {
/* Indexes relative to the original Mesh. */
/* Indices relative to the original Mesh. */
int poly_dst;
int poly_orig;
int loop_start;
@ -84,22 +70,25 @@ struct WeldPoly {
/* Final Polygon Size. */
int loop_len;
/* Group of loops that will be affected. */
struct WeldGroup loops;
struct {
int len;
int offs;
} loops;
};
};
};
struct WeldMesh {
/* Group of vertices to be merged. */
Array<WeldGroup> vert_groups;
Array<int> vert_groups_offs;
Array<int> vert_groups_buffer;
/* Group of edges to be merged. */
Array<WeldGroupEdge> edge_groups;
Array<int> edge_groups_offs;
Array<int> edge_groups_buffer;
/* From the original index of the vertex, this indicates which group it is or is going to be
* merged. */
/* From the original edge index, this indicates which group it is going to be merged. */
Array<int> edge_groups_map;
Array<int2> edge_groups_verts;
/* References all polygons and loops that will be affected. */
Vector<WeldLoop> wloop;
@ -295,10 +284,10 @@ static void weld_assert_poly_len(const WeldPoly *wp, const Span<WeldLoop> wloop)
}
int loop_len = wp->loop_len;
const WeldLoop *wl = &wloop[wp->loops.ofs];
const WeldLoop *wl = &wloop[wp->loops.offs];
BLI_assert(wp->loop_start <= wl->loop_orig);
int end_wloop = wp->loops.ofs + wp->loops.len;
int end_wloop = wp->loops.offs + wp->loops.len;
const WeldLoop *wl_end = &wloop[end_wloop - 1];
int min_len = 0;
@ -322,6 +311,11 @@ static void weld_assert_poly_len(const WeldPoly *wp, const Span<WeldLoop> wloop)
/** \name Vert API
* \{ */
/**
* Create a Weld Verts Context.
*
* \return array with the context weld vertices.
*/
static Vector<WeldVert> weld_vert_ctx_alloc_and_setup(Span<int> vert_dest_map,
const int vert_kill_len)
{
@ -339,56 +333,72 @@ static Vector<WeldVert> weld_vert_ctx_alloc_and_setup(Span<int> vert_dest_map,
return wvert;
}
/**
* Create groups of vertices to merge.
*
* \return r_vert_groups_map: Map that points out the group of vertices that a vertex belongs to.
* \return r_vert_groups_buffer: Buffer containing the indices of all vertices that merge.
* \return r_vert_groups_offs: Array that indicates where each vertex group starts in the buffer.
*/
static void weld_vert_groups_setup(Span<WeldVert> wvert,
Span<int> vert_dest_map,
const int vert_kill_len,
MutableSpan<int> r_vert_groups_map,
Array<int> &r_vert_groups_buffer,
Array<WeldGroup> &r_vert_groups)
Array<int> &r_vert_groups_offs)
{
/* Get weld vert groups. */
/**
* Since `r_vert_groups_map` comes from `vert_dest_map`, we don't need to reset vertices out of
* context again.
*
* \code{.c}
* for (const int i : vert_dest_map.index_range()) {
* r_vert_groups_map[i] = OUT_OF_CONTEXT;
* }
* \endcode
*/
BLI_assert(r_vert_groups_map.data() == vert_dest_map.data());
UNUSED_VARS_NDEBUG(vert_dest_map);
const int vert_groups_len = wvert.size() - vert_kill_len;
/* Add +1 to allow calculation of the length of the last group. */
r_vert_groups_offs.reinitialize(vert_groups_len + 1);
r_vert_groups_offs.fill(0);
int wgroups_len = 0;
for (const int i : vert_dest_map.index_range()) {
const int vert_dest = vert_dest_map[i];
if (vert_dest != OUT_OF_CONTEXT) {
if (vert_dest != i) {
r_vert_groups_map[i] = ELEM_MERGED;
}
else {
r_vert_groups_map[i] = wgroups_len;
wgroups_len++;
}
for (const WeldVert &wv : wvert) {
if (wv.vert_dest == wv.vert_orig) {
/* Indicate the index of the vertex group */
r_vert_groups_map[wv.vert_orig] = wgroups_len;
wgroups_len++;
}
else {
r_vert_groups_map[i] = OUT_OF_CONTEXT;
r_vert_groups_map[wv.vert_orig] = ELEM_MERGED;
}
}
r_vert_groups.reinitialize(wgroups_len);
r_vert_groups.fill({0, 0});
MutableSpan<WeldGroup> wgroups = r_vert_groups;
for (const WeldVert &wv : wvert) {
int group_index = r_vert_groups_map[wv.vert_dest];
wgroups[group_index].len++;
r_vert_groups_offs[group_index]++;
}
int ofs = 0;
for (WeldGroup &wg : wgroups) {
wg.ofs = ofs;
ofs += wg.len;
int offs = 0;
for (const int i : IndexRange(vert_groups_len)) {
offs += r_vert_groups_offs[i];
r_vert_groups_offs[i] = offs;
}
r_vert_groups_offs[vert_groups_len] = offs;
BLI_assert(ofs == wvert.size());
BLI_assert(offs == wvert.size());
r_vert_groups_buffer.reinitialize(ofs);
for (const WeldVert &wv : wvert) {
r_vert_groups_buffer.reinitialize(offs);
/* Use a reverse for loop to ensure that indexes are assigned in ascending order. */
for (int i = wvert.size(); i--;) {
const WeldVert &wv = wvert[i];
int group_index = r_vert_groups_map[wv.vert_dest];
r_vert_groups_buffer[wgroups[group_index].ofs++] = wv.vert_orig;
}
for (WeldGroup &wg : wgroups) {
wg.ofs -= wg.len;
r_vert_groups_buffer[--r_vert_groups_offs[group_index]] = wv.vert_orig;
}
}
@ -398,6 +408,12 @@ static void weld_vert_groups_setup(Span<WeldVert> wvert,
/** \name Edge API
* \{ */
/**
* Alloc Weld Edges.
*
* \return r_edge_dest_map: First step to create map of indices pointing edges that will be merged.
* \return r_edge_ctx_map: Map of indices pointing original edges to weld context edges.
*/
static Vector<WeldEdge> weld_edge_ctx_alloc(Span<MEdge> medge,
Span<int> vert_dest_map,
MutableSpan<int> r_edge_dest_map,
@ -433,15 +449,25 @@ static Vector<WeldEdge> weld_edge_ctx_alloc(Span<MEdge> medge,
return wedge;
}
static void weld_edge_ctx_setup(MutableSpan<WeldGroup> r_vlinks,
/**
* Configure Weld Edges.
*
* \param r_vlinks: An uninitialized buffer used to compute groups of WeldEdges attached to each
* weld target vertex. It doesn't need to be passed as a parameter but this is
* done to reduce allocations.
* \return r_edge_dest_map: Map of indices pointing edges that will be merged.
* \return r_wedge: Weld edges. `flag` and `edge_dest` members will be set here.
* \return r_edge_kill_len: Number of edges to be destroyed by merging or collapsing.
*/
static void weld_edge_ctx_setup(MutableSpan<int> r_vlinks,
MutableSpan<int> r_edge_dest_map,
MutableSpan<WeldEdge> r_wedge,
int *r_edge_kiil_len)
int *r_edge_kill_len)
{
/* Setup Edge Overlap. */
int edge_kill_len = 0;
MutableSpan<WeldGroup> v_links = r_vlinks;
r_vlinks.fill(0);
for (WeldEdge &we : r_wedge) {
int dst_vert_a = we.vert_a;
@ -455,20 +481,22 @@ static void weld_edge_ctx_setup(MutableSpan<WeldGroup> r_vlinks,
continue;
}
v_links[dst_vert_a].len++;
v_links[dst_vert_b].len++;
r_vlinks[dst_vert_a]++;
r_vlinks[dst_vert_b]++;
}
int link_len = 0;
for (WeldGroup &vl : r_vlinks) {
vl.ofs = link_len;
link_len += vl.len;
for (const int i : IndexRange(r_vlinks.size() - 1)) {
link_len += r_vlinks[i];
r_vlinks[i] = link_len;
}
r_vlinks.last() = link_len;
if (link_len > 0) {
Array<int> link_edge_buffer(link_len);
for (const int i : r_wedge.index_range()) {
/* Use a reverse for loop to ensure that indexes are assigned in ascending order. */
for (int i = r_wedge.size(); i--;) {
const WeldEdge &we = r_wedge[i];
if (we.flag == ELEM_COLLAPSED) {
continue;
@ -477,13 +505,8 @@ static void weld_edge_ctx_setup(MutableSpan<WeldGroup> r_vlinks,
int dst_vert_a = we.vert_a;
int dst_vert_b = we.vert_b;
link_edge_buffer[v_links[dst_vert_a].ofs++] = i;
link_edge_buffer[v_links[dst_vert_b].ofs++] = i;
}
for (WeldGroup &vl : r_vlinks) {
/* Fix offset */
vl.ofs -= vl.len;
link_edge_buffer[--r_vlinks[dst_vert_a]] = i;
link_edge_buffer[--r_vlinks[dst_vert_b]] = i;
}
for (const int i : r_wedge.index_range()) {
@ -497,18 +520,18 @@ static void weld_edge_ctx_setup(MutableSpan<WeldGroup> r_vlinks,
int dst_vert_a = we.vert_a;
int dst_vert_b = we.vert_b;
struct WeldGroup *link_a = &v_links[dst_vert_a];
struct WeldGroup *link_b = &v_links[dst_vert_b];
const int link_a = r_vlinks[dst_vert_a];
const int link_b = r_vlinks[dst_vert_b];
int edges_len_a = link_a->len;
int edges_len_b = link_b->len;
int edges_len_a = r_vlinks[dst_vert_a + 1] - link_a;
int edges_len_b = r_vlinks[dst_vert_b + 1] - link_b;
if (edges_len_a <= 1 || edges_len_b <= 1) {
continue;
}
int *edges_ctx_a = &link_edge_buffer[link_a->ofs];
int *edges_ctx_b = &link_edge_buffer[link_b->ofs];
int *edges_ctx_a = &link_edge_buffer[link_a];
int *edges_ctx_b = &link_edge_buffer[link_b];
int edge_orig = we.edge_orig;
for (; edges_len_a--; edges_ctx_a++) {
@ -542,22 +565,28 @@ static void weld_edge_ctx_setup(MutableSpan<WeldGroup> r_vlinks,
#endif
}
*r_edge_kiil_len = edge_kill_len;
*r_edge_kill_len = edge_kill_len;
}
/**
* Create groups of edges to merge.
*
* \return r_edge_groups_map: Map that points out the group of edges that an edge belongs to.
* \return r_edge_groups_buffer: Buffer containing the indices of all edges that merge.
* \return r_edge_groups_offs: Array that indicates where each edge group starts in the buffer.
*/
static void weld_edge_groups_setup(const int medge_len,
const int edge_kill_len,
MutableSpan<WeldEdge> wedge,
Span<int> wedge_map,
MutableSpan<int> r_edge_groups_map,
Array<int> &r_edge_groups_buffer,
Array<WeldGroupEdge> &r_edge_groups)
Array<int> &r_edge_groups_offs,
Array<int2> &r_edge_groups_verts)
{
/* Get weld edge groups. */
int wgroups_len = wedge.size() - edge_kill_len;
r_edge_groups.reinitialize(wgroups_len);
r_edge_groups.fill({{0}});
MutableSpan<WeldGroupEdge> wegroups = r_edge_groups;
r_edge_groups_verts.reinitialize(wgroups_len);
wgroups_len = 0;
for (const int i : IndexRange(medge_len)) {
@ -571,8 +600,7 @@ static void weld_edge_groups_setup(const int medge_len,
}
else {
we->edge_dest = we->edge_orig;
wegroups[wgroups_len].v1 = we->vert_a;
wegroups[wgroups_len].v2 = we->vert_b;
r_edge_groups_verts[wgroups_len] = {we->vert_a, we->vert_b};
r_edge_groups_map[i] = wgroups_len;
wgroups_len++;
}
@ -589,31 +617,35 @@ static void weld_edge_groups_setup(const int medge_len,
return;
}
/* Add +1 to allow calculation of the length of the last group. */
r_edge_groups_offs.reinitialize(wgroups_len + 1);
r_edge_groups_offs.fill(0);
for (const WeldEdge &we : wedge) {
if (we.flag == ELEM_COLLAPSED) {
continue;
}
int group_index = r_edge_groups_map[we.edge_dest];
wegroups[group_index].group.len++;
r_edge_groups_offs[group_index]++;
}
int ofs = 0;
for (WeldGroupEdge &wegrp : wegroups) {
wegrp.group.ofs = ofs;
ofs += wegrp.group.len;
int offs = 0;
for (const int i : IndexRange(wgroups_len)) {
offs += r_edge_groups_offs[i];
r_edge_groups_offs[i] = offs;
}
r_edge_groups_offs[wgroups_len] = offs;
r_edge_groups_buffer.reinitialize(ofs);
for (const WeldEdge &we : wedge) {
r_edge_groups_buffer.reinitialize(offs);
/* Use a reverse for loop to ensure that indexes are assigned in ascending order. */
for (int i = wedge.size(); i--;) {
const WeldEdge &we = wedge[i];
if (we.flag == ELEM_COLLAPSED) {
continue;
}
int group_index = r_edge_groups_map[we.edge_dest];
r_edge_groups_buffer[wegroups[group_index].group.ofs++] = we.edge_orig;
}
for (WeldGroupEdge &wegrp : wegroups) {
wegrp.group.ofs -= wegrp.group.len;
r_edge_groups_buffer[--r_edge_groups_offs[group_index]] = we.edge_orig;
}
}
@ -729,6 +761,11 @@ static bool weld_iter_loop_of_poly_next(WeldLoopOfPolyIter &iter)
return false;
}
/**
* Alloc Weld Polygons and Weld Loops.
*
* \return r_weld_mesh: Loop and poly members will be allocated here.
*/
static void weld_poly_loop_ctx_alloc(Span<MPoly> mpoly,
const Span<int> corner_verts,
const Span<int> corner_edges,
@ -789,7 +826,7 @@ static void weld_poly_loop_ctx_alloc(Span<MPoly> mpoly,
wp.poly_dst = OUT_OF_CONTEXT;
wp.poly_orig = i;
wp.loops.len = loops_len;
wp.loops.ofs = prev_wloop_len;
wp.loops.offs = prev_wloop_len;
wp.loop_start = loopstart;
wp.loop_end = loopstart + totloop - 1;
wp.loop_len = totloop;
@ -835,7 +872,7 @@ static void weld_poly_split_recursive(Span<int> vert_dest_map,
}
const int ctx_loops_len = r_wp->loops.len;
const int ctx_loops_ofs = r_wp->loops.ofs;
const int ctx_loops_ofs = r_wp->loops.offs;
MutableSpan<WeldLoop> wloop = r_weld_mesh->wloop;
int loop_kill = 0;
@ -914,7 +951,7 @@ static void weld_poly_split_recursive(Span<int> vert_dest_map,
new_wp->poly_dst = OUT_OF_CONTEXT;
new_wp->poly_orig = r_wp->poly_orig;
new_wp->loops.len = new_loops_len;
new_wp->loops.ofs = new_loops_ofs;
new_wp->loops.offs = new_loops_ofs;
new_wp->loop_start = wla->loop_orig;
new_wp->loop_end = wlb_prev->loop_orig;
new_wp->loop_len = dist_a;
@ -964,16 +1001,24 @@ static void weld_poly_split_recursive(Span<int> vert_dest_map,
#endif
}
/**
* Alloc Weld Polygons and Weld Loops.
*
* \param remain_edge_ctx_len: Context weld edges that won't be destroyed by merging or collapsing.
* \param r_vlinks: An uninitialized buffer used to compute groups of WeldPolys attached to each
* weld target vertex. It doesn't need to be passed as a parameter but this is
* done to reduce allocations.
* \return r_weld_mesh: Loop and poly members will be configured here.
*/
static void weld_poly_loop_ctx_setup(const Span<int> corner_verts,
const Span<int> corner_edges,
#ifdef USE_WELD_DEBUG
Span<MPoly> mpoly,
#endif
const int mvert_len,
Span<int> vert_dest_map,
const int remain_edge_ctx_len,
MutableSpan<WeldGroup> r_vlinks,
MutableSpan<int> r_vlinks,
WeldMesh *r_weld_mesh)
{
WeldPoly *wpoly = r_weld_mesh->wpoly.data();
@ -992,7 +1037,7 @@ static void weld_poly_loop_ctx_setup(const Span<int> corner_verts,
for (const int i : wpoly_original_range) {
WeldPoly &wp = wpoly[i];
const int ctx_loops_len = wp.loops.len;
const int ctx_loops_ofs = wp.loops.ofs;
const int ctx_loops_ofs = wp.loops.offs;
int poly_loop_len = wp.loop_len;
int ctx_verts_len = 0;
@ -1045,44 +1090,40 @@ static void weld_poly_loop_ctx_setup(const Span<int> corner_verts,
/* Setup Polygon Overlap. */
r_vlinks.fill({0, 0});
MutableSpan<WeldGroup> v_links = r_vlinks;
r_vlinks.fill(0);
for (const WeldPoly &wp : r_weld_mesh->wpoly) {
WeldLoopOfPolyIter iter;
if (weld_iter_loop_of_poly_begin(
iter, wp, wloop, corner_verts, corner_edges, loop_map, nullptr)) {
while (weld_iter_loop_of_poly_next(iter)) {
v_links[iter.v].len++;
r_vlinks[iter.v]++;
}
}
}
int link_len = 0;
for (const int i : IndexRange(mvert_len)) {
v_links[i].ofs = link_len;
link_len += v_links[i].len;
link_len += r_vlinks[i];
r_vlinks[i] = link_len;
}
r_vlinks[mvert_len] = link_len;
if (link_len) {
Array<int> link_poly_buffer(link_len);
for (const int i : IndexRange(r_weld_mesh->wpoly.size())) {
/* Use a reverse for loop to ensure that indexes are assigned in ascending order. */
for (int i = r_weld_mesh->wpoly.size(); i--;) {
const WeldPoly &wp = wpoly[i];
WeldLoopOfPolyIter iter;
if (weld_iter_loop_of_poly_begin(
iter, wp, wloop, corner_verts, corner_edges, loop_map, nullptr)) {
while (weld_iter_loop_of_poly_next(iter)) {
link_poly_buffer[v_links[iter.v].ofs++] = i;
link_poly_buffer[--r_vlinks[iter.v]] = i;
}
}
}
for (WeldGroup &vl : r_vlinks) {
/* Fix offset */
vl.ofs -= vl.len;
}
int polys_len_a, polys_len_b, *polys_ctx_a, *polys_ctx_b, p_ctx_a, p_ctx_b;
polys_len_b = p_ctx_b = 0; /* silence warnings */
@ -1098,14 +1139,14 @@ static void weld_poly_loop_ctx_setup(const Span<int> corner_verts,
weld_iter_loop_of_poly_begin(
iter, wp, wloop, corner_verts, corner_edges, loop_map, nullptr);
weld_iter_loop_of_poly_next(iter);
struct WeldGroup *link_a = &v_links[iter.v];
polys_len_a = link_a->len;
const int link_a = r_vlinks[iter.v];
polys_len_a = r_vlinks[iter.v + 1] - link_a;
if (polys_len_a == 1) {
BLI_assert(link_poly_buffer[link_a->ofs] == i);
BLI_assert(link_poly_buffer[link_a] == i);
continue;
}
int wp_loop_len = wp.loop_len;
polys_ctx_a = &link_poly_buffer[link_a->ofs];
polys_ctx_a = &link_poly_buffer[link_a];
for (; polys_len_a--; polys_ctx_a++) {
p_ctx_a = *polys_ctx_a;
if (p_ctx_a == i) {
@ -1119,15 +1160,15 @@ static void weld_poly_loop_ctx_setup(const Span<int> corner_verts,
WeldLoopOfPolyIter iter_b = iter;
while (weld_iter_loop_of_poly_next(iter_b)) {
struct WeldGroup *link_b = &v_links[iter_b.v];
polys_len_b = link_b->len;
const int link_b = r_vlinks[iter_b.v];
polys_len_b = r_vlinks[iter_b.v + 1] - link_b;
if (polys_len_b == 1) {
BLI_assert(link_poly_buffer[link_b->ofs] == i);
BLI_assert(link_poly_buffer[link_b] == i);
polys_len_b = 0;
break;
}
polys_ctx_b = &link_poly_buffer[link_b->ofs];
polys_ctx_b = &link_poly_buffer[link_b];
for (; polys_len_b; polys_len_b--, polys_ctx_b++) {
p_ctx_b = *polys_ctx_b;
if (p_ctx_b < p_ctx_a) {
@ -1185,6 +1226,7 @@ static void weld_poly_loop_ctx_setup(const Span<int> corner_verts,
static void weld_mesh_context_create(const Mesh &mesh,
MutableSpan<int> vert_dest_map,
const int vert_kill_len,
MutableSpan<int> r_vert_group_map,
WeldMesh *r_weld_mesh)
{
const int mvert_len = mesh.totvert;
@ -1200,7 +1242,8 @@ static void weld_mesh_context_create(const Mesh &mesh,
Array<int> edge_ctx_map(edges.size());
Vector<WeldEdge> wedge = weld_edge_ctx_alloc(edges, vert_dest_map, edge_dest_map, edge_ctx_map);
Array<WeldGroup> v_links(mvert_len, {0, 0});
/* Add +1 to allow calculation of the length of the last group. */
Array<int> v_links(mvert_len + 1);
weld_edge_ctx_setup(v_links, edge_dest_map, wedge, &r_weld_mesh->edge_kill_len);
weld_poly_loop_ctx_alloc(
@ -1220,9 +1263,10 @@ static void weld_mesh_context_create(const Mesh &mesh,
weld_vert_groups_setup(wvert,
vert_dest_map,
vert_dest_map,
vert_kill_len,
r_vert_group_map,
r_weld_mesh->vert_groups_buffer,
r_weld_mesh->vert_groups);
r_weld_mesh->vert_groups_offs);
weld_edge_groups_setup(edges.size(),
r_weld_mesh->edge_kill_len,
@ -1230,7 +1274,8 @@ static void weld_mesh_context_create(const Mesh &mesh,
edge_ctx_map,
edge_dest_map,
r_weld_mesh->edge_groups_buffer,
r_weld_mesh->edge_groups);
r_weld_mesh->edge_groups_offs,
r_weld_mesh->edge_groups_verts);
r_weld_mesh->edge_groups_map = std::move(edge_dest_map);
}
@ -1344,8 +1389,12 @@ static Mesh *create_merged_mesh(const Mesh &mesh,
const int totvert = mesh.totvert;
const int totedge = mesh.totedge;
/* Reuse the same buffer as #vert_dest_map.
* Note: the caller must be made aware of it changes. */
MutableSpan<int> vert_group_map = vert_dest_map;
WeldMesh weld_mesh;
weld_mesh_context_create(mesh, vert_dest_map, removed_vertex_count, &weld_mesh);
weld_mesh_context_create(mesh, vert_dest_map, removed_vertex_count, vert_group_map, &weld_mesh);
const int result_nverts = totvert - weld_mesh.vert_kill_len;
const int result_nedges = totedge - weld_mesh.edge_kill_len;
@ -1361,16 +1410,16 @@ static Mesh *create_merged_mesh(const Mesh &mesh,
/* Vertices. */
/* Be careful when editing this array, to avoid new allocations it uses the same buffer as
* #vert_dest_map. This map will be used to adjust the edges, polys and loops. */
MutableSpan<int> vert_final = vert_dest_map;
/* Be careful when setting values to this array as it uses the same buffer as #vert_group_map.
* This map will be used to adjust edges and loops to point to new vertex indices. */
MutableSpan<int> vert_final_map = vert_group_map;
int dest_index = 0;
for (int i = 0; i < totvert; i++) {
int source_index = i;
int count = 0;
while (i < totvert && vert_dest_map[i] == OUT_OF_CONTEXT) {
vert_final[i] = dest_index + count;
while (i < totvert && vert_group_map[i] == OUT_OF_CONTEXT) {
vert_final_map[i] = dest_index + count;
count++;
i++;
}
@ -1381,14 +1430,14 @@ static Mesh *create_merged_mesh(const Mesh &mesh,
if (i == totvert) {
break;
}
if (vert_dest_map[i] != ELEM_MERGED) {
struct WeldGroup *wgroup = &weld_mesh.vert_groups[vert_dest_map[i]];
if (vert_group_map[i] != ELEM_MERGED) {
const int *wgroup = &weld_mesh.vert_groups_offs[vert_group_map[i]];
customdata_weld(&mesh.vdata,
&result->vdata,
&weld_mesh.vert_groups_buffer[wgroup->ofs],
wgroup->len,
&weld_mesh.vert_groups_buffer[*wgroup],
*(wgroup + 1) - *wgroup,
dest_index);
vert_final[i] = dest_index;
vert_final_map[i] = dest_index;
dest_index++;
}
}
@ -1397,16 +1446,16 @@ static Mesh *create_merged_mesh(const Mesh &mesh,
/* Edges. */
/* Be careful when editing this array, to avoid new allocations it uses the same buffer as
* #edge_groups_map. This map will be used to adjust the polys and loops. */
MutableSpan<int> edge_final = weld_mesh.edge_groups_map;
/* Be careful when editing this array as it uses the same buffer as #WeldMesh::edge_groups_map.
* This map will be used to adjust edges and loops to point to new edge indices. */
MutableSpan<int> edge_final_map = weld_mesh.edge_groups_map;
dest_index = 0;
for (int i = 0; i < totedge; i++) {
const int source_index = i;
int count = 0;
while (i < totedge && weld_mesh.edge_groups_map[i] == OUT_OF_CONTEXT) {
edge_final[i] = dest_index + count;
edge_final_map[i] = dest_index + count;
count++;
i++;
}
@ -1415,25 +1464,28 @@ static Mesh *create_merged_mesh(const Mesh &mesh,
MEdge *me = &dst_edges[dest_index];
dest_index += count;
for (; count--; me++) {
me->v1 = vert_final[me->v1];
me->v2 = vert_final[me->v2];
me->v1 = vert_final_map[me->v1];
me->v2 = vert_final_map[me->v2];
}
}
if (i == totedge) {
break;
}
if (weld_mesh.edge_groups_map[i] != ELEM_MERGED) {
struct WeldGroupEdge *wegrp = &weld_mesh.edge_groups[weld_mesh.edge_groups_map[i]];
const int wegpr_index = weld_mesh.edge_groups_map[i];
const int wegrp_offs = weld_mesh.edge_groups_offs[wegpr_index];
const int wegrp_len = weld_mesh.edge_groups_offs[wegpr_index + 1] - wegrp_offs;
int2 &wegrp_verts = weld_mesh.edge_groups_verts[wegpr_index];
customdata_weld(&mesh.edata,
&result->edata,
&weld_mesh.edge_groups_buffer[wegrp->group.ofs],
wegrp->group.len,
&weld_mesh.edge_groups_buffer[wegrp_offs],
wegrp_len,
dest_index);
MEdge *me = &dst_edges[dest_index];
me->v1 = vert_final[wegrp->v1];
me->v2 = vert_final[wegrp->v2];
me->v1 = vert_final_map[wegrp_verts[0]];
me->v2 = vert_final_map[wegrp_verts[1]];
edge_final[i] = dest_index;
edge_final_map[i] = dest_index;
dest_index++;
}
}
@ -1454,8 +1506,8 @@ static Mesh *create_merged_mesh(const Mesh &mesh,
int mp_loop_len = mp.totloop;
CustomData_copy_data(&mesh.ldata, &result->ldata, mp.loopstart, loop_cur, mp_loop_len);
for (; mp_loop_len--; loop_cur++) {
dst_corner_verts[loop_cur] = vert_final[dst_corner_verts[loop_cur]];
dst_corner_edges[loop_cur] = edge_final[dst_corner_edges[loop_cur]];
dst_corner_verts[loop_cur] = vert_final_map[dst_corner_verts[loop_cur]];
dst_corner_edges[loop_cur] = edge_final_map[dst_corner_edges[loop_cur]];
}
}
else {
@ -1477,8 +1529,8 @@ static Mesh *create_merged_mesh(const Mesh &mesh,
while (weld_iter_loop_of_poly_next(iter)) {
customdata_weld(
&mesh.ldata, &result->ldata, group_buffer.data(), iter.group_len, loop_cur);
dst_corner_verts[loop_cur] = vert_final[iter.v];
dst_corner_edges[loop_cur] = edge_final[iter.e];
dst_corner_verts[loop_cur] = vert_final_map[iter.v];
dst_corner_edges[loop_cur] = edge_final_map[iter.e];
loop_cur++;
}
}
@ -1510,8 +1562,8 @@ static Mesh *create_merged_mesh(const Mesh &mesh,
}
while (weld_iter_loop_of_poly_next(iter)) {
customdata_weld(&mesh.ldata, &result->ldata, group_buffer.data(), iter.group_len, loop_cur);
dst_corner_verts[loop_cur] = vert_final[iter.v];
dst_corner_edges[loop_cur] = edge_final[iter.e];
dst_corner_verts[loop_cur] = vert_final_map[iter.v];
dst_corner_edges[loop_cur] = edge_final_map[iter.e];
loop_cur++;
}

View File

@ -3885,7 +3885,7 @@ void GEO_uv_parametrizer_face_add(ParamHandle *phandle,
while (i >= 0) {
/* Just check the "ears" of the n-gon.
* For quads, this is sufficient.
* For pents and higher, we might miss internal duplicate triangles, but note
* For pentagons and higher, we might miss internal duplicate triangles, but note
* that such cases are rare if the source geometry is manifold and non-intersecting. */
int pm = permute.size();
BLI_assert(pm > 3);

View File

@ -4606,7 +4606,7 @@ static void lineart_create_edges_from_isec_data(LineartIsecData *d)
e->t1 = is->tri1;
e->t2 = is->tri2;
/* This is so we can also match intersection edges from shadow to later viewing stage. */
e->edge_identifier = (((uint64_t)e->t1->target_reference) << 32) | e->t2->target_reference;
e->edge_identifier = ((uint64_t(e->t1->target_reference)) << 32) | e->t2->target_reference;
e->flags = LRT_EDGE_FLAG_INTERSECTION;
e->intersection_mask = (is->tri1->intersection_mask | is->tri2->intersection_mask);
BLI_addtail(&e->segments, es);

View File

@ -3,13 +3,13 @@
/** Method used to reference paths. Equivalent of bpy_extras.io_utils.path_reference_mode. */
typedef enum {
/** Use Relative paths with subdirectories only. */
/** Use relative paths with subdirectories only. */
PATH_REFERENCE_AUTO = 0,
/** Always write absolute paths. */
PATH_REFERENCE_ABSOLUTE = 1,
/** Write relative paths where possible. */
PATH_REFERENCE_RELATIVE = 2,
/** Match Absolute/Relative setting with input path. */
/** Match absolute/relative setting with input path. */
PATH_REFERENCE_MATCH = 3,
/** Filename only. */
PATH_REFERENCE_STRIP = 4,

View File

@ -123,6 +123,7 @@ set(LIB
list(APPEND LIB
${BOOST_LIBRARIES}
${BOOST_PYTHON_LIBRARIES}
${PYTHON_LIBRARIES}
)

View File

@ -450,7 +450,9 @@ bool USD_import(struct bContext *C,
* USD reader is compatible with the type of the given (currently unused) 'ob'
* Object parameter, similar to the logic in get_abc_reader() in the
* Alembic importer code. */
static USDPrimReader *get_usd_reader(CacheReader *reader, Object * /* ob */, const char **err_str)
static USDPrimReader *get_usd_reader(CacheReader *reader,
const Object * /* ob */,
const char **err_str)
{
USDPrimReader *usd_reader = reinterpret_cast<USDPrimReader *>(reader);
pxr::UsdPrim iobject = usd_reader->prim();
@ -479,8 +481,11 @@ struct Mesh *USD_read_mesh(struct CacheReader *reader,
return usd_reader->read_mesh(existing_mesh, time, read_flag, err_str);
}
bool USD_mesh_topology_changed(
CacheReader *reader, Object *ob, Mesh *existing_mesh, const double time, const char **err_str)
bool USD_mesh_topology_changed(CacheReader *reader,
const Object *ob,
const Mesh *existing_mesh,
const double time,
const char **err_str)
{
USDGeomReader *usd_reader = dynamic_cast<USDGeomReader *>(get_usd_reader(reader, ob, err_str));

View File

@ -107,8 +107,8 @@ struct Mesh *USD_read_mesh(struct CacheReader *reader,
int read_flag);
bool USD_mesh_topology_changed(struct CacheReader *reader,
struct Object *ob,
struct Mesh *existing_mesh,
const struct Object *ob,
const struct Mesh *existing_mesh,
double time,
const char **err_str);

View File

@ -280,42 +280,14 @@ typedef enum eNodeSocketFlag {
SOCK_HIDE_LABEL = (1 << 12),
} eNodeSocketFlag;
/** TODO: Limit data in #bNode to what we want to see saved. */
typedef struct bNode {
struct bNode *next, *prev;
/** User-defined properties. */
IDProperty *prop;
/** Runtime type information. */
struct bNodeType *typeinfo;
/** Runtime type identifier. */
char idname[64];
/** MAX_NAME. */
char name[64];
int flag;
short type;
char _pad2[6];
/** Custom user-defined color. */
float color[3];
/* Input and output #bNodeSocket. */
ListBase inputs, outputs;
/** Parent node. */
struct bNode *parent;
/** Optional link to libdata. */
struct ID *id;
/** Custom data, must be struct, for storage in file. */
void *storage;
/** Root offset for drawing (parent space). */
float locx, locy;
/** Node custom width and height. */
float width, height;
/** Additional offset from loc. */
float offsetx, offsety;
/** The node's name for unique identification and string lookup. MAX_NAME. */
char name[64];
/**
* A value that uniquely identifies a node in a node tree even when the name changes.
@ -326,11 +298,62 @@ typedef struct bNode {
*/
int32_t identifier;
int flag;
/**
* String identifier of the type like "FunctionNodeCompare". Stored in files to allow retrieving
* the node type for node types including custom nodes defined in Python by addons.
*/
char idname[64];
/** Type information retrieved from the #idname. TODO: Move to runtime data. */
struct bNodeType *typeinfo;
/**
* Integer type used for builtin nodes, allowing cheaper lookup and changing ID names with
* versioning code. Avoid using directly if possible, since may not match runtime node type if it
* wasn't found.
*/
int16_t type;
char _pad1[2];
/** Used for some builtin nodes that store properties but don't have a storage struct . */
int16_t custom1, custom2;
float custom3, custom4;
/** Optional link to libdata. */
struct ID *id;
/** Custom data struct for node properties for storage in files. */
void *storage;
/**
* Custom properties often defined by addons to store arbitrary data on nodes. A non-builtin
* equivalent to #storage.
*/
IDProperty *prop;
/** Parent node (for frame nodes). */
struct bNode *parent;
/** Root location in the node canvas (in parent space). */
float locx, locy;
/**
* Custom width and height controlled by users. Height is calculate automatically for most
* nodes.
*/
float width, height;
/** Additional offset from loc. TODO: Redundant with #locx and #locy, remove/deprecate. */
float offsetx, offsety;
/** Custom user-defined label, MAX_NAME. */
char label[64];
/** To be abused for buttons. */
short custom1, custom2;
float custom3, custom4;
/** Custom user-defined color. */
float color[3];
char _pad2[4];
bNodeRuntimeHandle *runtime;
@ -822,7 +845,7 @@ typedef struct NodeBlurData {
typedef struct NodeDBlurData {
float center_x, center_y, distance, angle, spin, zoom;
short iter;
char wrap, _pad;
char _pad[2];
} NodeDBlurData;
typedef struct NodeBilateralBlurData {

View File

@ -472,7 +472,7 @@ static void rna_def_area_light(BlenderRNA *brna)
prop = RNA_def_property(srna, "spread", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "area_spread");
RNA_def_property_range(prop, DEG2RADF(1.0f), DEG2RADF(180.0f));
RNA_def_property_range(prop, DEG2RADF(0.0f), DEG2RADF(180.0f));
RNA_def_property_ui_text(
prop,
"Spread",

View File

@ -2202,6 +2202,19 @@ static const EnumPropertyItem *rna_GeometryNodeAttributeType_type_with_socket_it
generic_attribute_type_supported_with_socket);
}
static bool rna_GeometryNodeBlurAttribute_data_type_supported(const EnumPropertyItem *item)
{
return ELEM(item->value, CD_PROP_FLOAT, CD_PROP_FLOAT3, CD_PROP_COLOR, CD_PROP_INT32);
}
static const EnumPropertyItem *rna_GeometryNodeBlurAttribute_data_type_itemf(
bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
{
*r_free = true;
return itemf_function_check(rna_enum_attribute_type_items,
rna_GeometryNodeBlurAttribute_data_type_supported);
}
static bool attribute_statistic_type_supported(const EnumPropertyItem *item)
{
return ELEM(item->value, CD_PROP_FLOAT, CD_PROP_FLOAT3);
@ -7787,11 +7800,6 @@ static void def_cmp_dblur(StructRNA *srna)
RNA_def_property_ui_text(prop, "Iterations", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "use_wrap", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "wrap", 1);
RNA_def_property_ui_text(prop, "Wrap", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "center_x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "center_x");
RNA_def_property_range(prop, 0.0f, 1.0f);
@ -9521,6 +9529,19 @@ static void def_geo_accumulate_field(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_geo_blur_attribute(StructRNA *srna)
{
PropertyRNA *prop;
prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "custom1");
RNA_def_property_enum_items(prop, rna_enum_attribute_type_items);
RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeBlurAttribute_data_type_itemf");
RNA_def_property_enum_default(prop, CD_PROP_FLOAT);
RNA_def_property_ui_text(prop, "Data Type", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_GeometryNode_socket_update");
}
static void def_fn_random_value(StructRNA *srna)
{
PropertyRNA *prop;

View File

@ -292,7 +292,7 @@ static void displaceModifier_do(DisplaceModifierData *dmd,
Tex *tex_target = dmd->texture;
if (tex_target != nullptr) {
tex_co = static_cast<float(*)[3]>(
MEM_calloc_arrayN((size_t)verts_num, sizeof(*tex_co), "displaceModifier_do tex_co"));
MEM_calloc_arrayN(size_t(verts_num), sizeof(*tex_co), "displaceModifier_do tex_co"));
MOD_get_texture_coords((MappingInfoModifierData *)dmd, ctx, ob, mesh, vertexCos, tex_co);
MOD_init_texture((MappingInfoModifierData *)dmd, ctx);

View File

@ -283,6 +283,7 @@ DefNode(FunctionNode, FN_NODE_VALUE_TO_STRING, 0, "VALUE_TO_STRING", ValueToStri
DefNode(GeometryNode, GEO_NODE_ACCUMULATE_FIELD, def_geo_accumulate_field, "ACCUMULATE_FIELD", AccumulateField, "Accumulate Field", "Add the values of an evaluated field together and output the running total for each element")
DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_DOMAIN_SIZE, def_geo_attribute_domain_size, "ATTRIBUTE_DOMAIN_SIZE", AttributeDomainSize, "Domain Size", "Retrieve the number of elements in a geometry for each attribute domain")
DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_STATISTIC, def_geo_attribute_statistic, "ATTRIBUTE_STATISTIC",AttributeStatistic, "Attribute Statistic","Calculate statistics about a data set from a field evaluated on a geometry")
DefNode(GeometryNode, GEO_NODE_BLUR_ATTRIBUTE, def_geo_blur_attribute, "BLUR_ATTRIBUTE", BlurAttribute, "Blur Attribute", "Mix attribute values of neighboring elements")
DefNode(GeometryNode, GEO_NODE_BOUNDING_BOX, 0, "BOUNDING_BOX", BoundBox, "Bounding Box", "Calculate the limits of a geometry's positions and generate a box mesh with those dimensions")
DefNode(GeometryNode, GEO_NODE_CAPTURE_ATTRIBUTE, def_geo_attribute_capture,"CAPTURE_ATTRIBUTE", CaptureAttribute, "Capture Attribute", "Store the result of a field on a geometry and output the data as a node socket. Allows remembering or interpolating data as the geometry changes, such as positions before deformation")
DefNode(GeometryNode, GEO_NODE_COLLECTION_INFO, def_geo_collection_info, "COLLECTION_INFO", CollectionInfo, "Collection Info", "Retrieve geometry from a collection")

View File

@ -46,7 +46,6 @@ static void node_composit_buts_dblur(uiLayout *layout, bContext * /*C*/, Pointer
uiLayout *col;
uiItemR(layout, ptr, "iterations", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
uiItemR(layout, ptr, "use_wrap", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
col = uiLayoutColumn(layout, true);
uiItemL(col, IFACE_("Center:"), ICON_NONE);

View File

@ -29,6 +29,7 @@ set(SRC
nodes/node_geo_attribute_capture.cc
nodes/node_geo_attribute_domain_size.cc
nodes/node_geo_attribute_statistic.cc
nodes/node_geo_blur_attribute.cc
nodes/node_geo_boolean.cc
nodes/node_geo_bounding_box.cc
nodes/node_geo_collection_info.cc

View File

@ -14,6 +14,7 @@ void register_geometry_nodes()
register_node_type_geo_attribute_capture();
register_node_type_geo_attribute_domain_size();
register_node_type_geo_attribute_statistic();
register_node_type_geo_blur_attribute();
register_node_type_geo_boolean();
register_node_type_geo_bounding_box();
register_node_type_geo_collection_info();

View File

@ -11,6 +11,7 @@ void register_node_type_geo_attribute_capture();
void register_node_type_geo_attribute_domain_size();
void register_node_type_geo_attribute_separate_xyz();
void register_node_type_geo_attribute_statistic();
void register_node_type_geo_blur_attribute();
void register_node_type_geo_boolean();
void register_node_type_geo_bounding_box();
void register_node_type_geo_collection_info();

View File

@ -0,0 +1,497 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_array.hh"
#include "BLI_generic_array.hh"
#include "BLI_index_mask.hh"
#include "BLI_index_range.hh"
#include "BLI_span.hh"
#include "BLI_task.hh"
#include "BLI_vector.hh"
#include "BLI_virtual_array.hh"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "BKE_attribute_math.hh"
#include "BKE_curves.hh"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "NOD_socket_search_link.hh"
#include "node_geometry_util.hh"
namespace blender::nodes::node_geo_blur_attribute_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Float>(N_("Value"), "Value_Float")
.supports_field()
.hide_value()
.is_default_link_socket();
b.add_input<decl::Int>(N_("Value"), "Value_Int")
.supports_field()
.hide_value()
.is_default_link_socket();
b.add_input<decl::Vector>(N_("Value"), "Value_Vector")
.supports_field()
.hide_value()
.is_default_link_socket();
b.add_input<decl::Color>(N_("Value"), "Value_Color")
.supports_field()
.hide_value()
.is_default_link_socket();
b.add_input<decl::Int>("Iterations")
.default_value(1)
.min(0)
.description(N_("How many times to blur the values for all elements"));
b.add_input<decl::Float>("Weight")
.default_value(1.0f)
.subtype(PROP_FACTOR)
.min(0.0f)
.max(1.0f)
.supports_field()
.description(N_("Relative mix weight of neighboring elements"));
b.add_output<decl::Float>(N_("Value"), "Value_Float").field_source().dependent_field();
b.add_output<decl::Int>(N_("Value"), "Value_Int").field_source().dependent_field();
b.add_output<decl::Vector>(N_("Value"), "Value_Vector").field_source().dependent_field();
b.add_output<decl::Color>(N_("Value"), "Value_Color").field_source().dependent_field();
}
static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
}
static void node_init(bNodeTree *UNUSED(tree), bNode *node)
{
node->custom1 = CD_PROP_FLOAT;
}
static void node_gather_link_searches(GatherLinkSearchOpParams &params)
{
const NodeDeclaration &declaration = *params.node_type().fixed_declaration;
search_link_ops_for_declarations(params, declaration.inputs().take_back(2));
const bNodeType &node_type = params.node_type();
const std::optional<eCustomDataType> type = node_data_type_to_custom_data_type(
(eNodeSocketDatatype)params.other_socket().type);
if (type && *type != CD_PROP_STRING) {
params.add_item(IFACE_("Value"), [node_type, type](LinkSearchOpParams &params) {
bNode &node = params.add_node(node_type);
node.custom1 = *type;
params.update_and_connect_available_socket(node, "Value");
});
}
}
static void node_update(bNodeTree *ntree, bNode *node)
{
const eCustomDataType data_type = static_cast<eCustomDataType>(node->custom1);
bNodeSocket *socket_value_float = (bNodeSocket *)node->inputs.first;
bNodeSocket *socket_value_int32 = socket_value_float->next;
bNodeSocket *socket_value_vector = socket_value_int32->next;
bNodeSocket *socket_value_color4f = socket_value_vector->next;
nodeSetSocketAvailability(ntree, socket_value_float, data_type == CD_PROP_FLOAT);
nodeSetSocketAvailability(ntree, socket_value_int32, data_type == CD_PROP_INT32);
nodeSetSocketAvailability(ntree, socket_value_vector, data_type == CD_PROP_FLOAT3);
nodeSetSocketAvailability(ntree, socket_value_color4f, data_type == CD_PROP_COLOR);
bNodeSocket *out_socket_value_float = (bNodeSocket *)node->outputs.first;
bNodeSocket *out_socket_value_int32 = out_socket_value_float->next;
bNodeSocket *out_socket_value_vector = out_socket_value_int32->next;
bNodeSocket *out_socket_value_color4f = out_socket_value_vector->next;
nodeSetSocketAvailability(ntree, out_socket_value_float, data_type == CD_PROP_FLOAT);
nodeSetSocketAvailability(ntree, out_socket_value_int32, data_type == CD_PROP_INT32);
nodeSetSocketAvailability(ntree, out_socket_value_vector, data_type == CD_PROP_FLOAT3);
nodeSetSocketAvailability(ntree, out_socket_value_color4f, data_type == CD_PROP_COLOR);
}
static Array<Vector<int>> build_vert_to_vert_by_edge_map(const Span<MEdge> edges,
const int verts_num)
{
Array<Vector<int>> map(verts_num);
for (const MEdge &edge : edges) {
map[edge.v1].append(edge.v2);
map[edge.v2].append(edge.v1);
}
return map;
}
static Array<Vector<int>> build_edge_to_edge_by_vert_map(const Span<MEdge> edges,
const int verts_num,
const IndexMask edge_mask)
{
Array<Vector<int>> map(edges.size());
Array<Vector<int>> vert_to_edge_map = bke::mesh_topology::build_vert_to_edge_map(edges,
verts_num);
threading::parallel_for(edge_mask.index_range(), 1024, [&](IndexRange range) {
for (const int edge_i : edge_mask.slice(range)) {
Vector<int> &self_edges = map[edge_i];
const Span<int> vert_1_edges = vert_to_edge_map[edges[edge_i].v1];
const Span<int> vert_2_edges = vert_to_edge_map[edges[edge_i].v2];
self_edges.reserve(vert_1_edges.size() - 1 + vert_2_edges.size() - 1);
for (const int i : vert_1_edges) {
if (i != edge_i) {
self_edges.append(i);
}
}
for (const int i : vert_2_edges) {
if (i != edge_i) {
self_edges.append(i);
}
}
}
});
return map;
}
static Array<Vector<int>> build_face_to_edge_by_loop_map(const Span<MPoly> polys,
const Span<MLoop> loops,
const int edges_num)
{
Array<Vector<int>> map(edges_num);
for (const int i : polys.index_range()) {
const MPoly &poly = polys[i];
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
map[loop.e].append(i);
}
}
return map;
}
static Array<Vector<int>> build_face_to_face_by_edge_map(const Span<MPoly> polys,
const Span<MLoop> loops,
const int edges_num,
const IndexMask poly_mask)
{
Array<Vector<int>> map(polys.size());
Array<Vector<int>> faces_by_edge = build_face_to_edge_by_loop_map(polys, loops, edges_num);
threading::parallel_for(poly_mask.index_range(), 1024, [&](IndexRange range) {
for (const int poly_i : poly_mask.slice(range)) {
const MPoly &poly = polys[poly_i];
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
const int edge_i = loop.e;
if (faces_by_edge[edge_i].size() > 1) {
for (const int neighbor : faces_by_edge[edge_i]) {
if (neighbor != poly_i) {
map[poly_i].append(neighbor);
}
}
}
}
}
});
return map;
}
static Array<Vector<int>> create_mesh_map(const Mesh &mesh,
const eAttrDomain domain,
const IndexMask mask)
{
switch (domain) {
case ATTR_DOMAIN_POINT: {
const Span<MEdge> edges = mesh.edges();
const int verts_num = mesh.totvert;
return build_vert_to_vert_by_edge_map(edges, verts_num);
}
case ATTR_DOMAIN_EDGE: {
const Span<MEdge> edges = mesh.edges();
const int verts_num = mesh.totvert;
return build_edge_to_edge_by_vert_map(edges, verts_num, mask);
}
case ATTR_DOMAIN_FACE: {
const Span<MPoly> polys = mesh.polys();
const Span<MLoop> loops = mesh.loops();
const int edges_num = mesh.totedge;
return build_face_to_face_by_edge_map(polys, loops, edges_num, mask);
}
case ATTR_DOMAIN_CORNER: {
return {};
}
default:
BLI_assert_unreachable();
return {};
}
}
template<typename T>
static void blur_on_mesh_exec(const Span<float> neighbor_weights,
const Span<Vector<int>> neighbors_map,
const int iterations,
MutableSpan<T> main_buffer,
MutableSpan<T> tmp_buffer)
{
MutableSpan<T> src = main_buffer;
MutableSpan<T> dst = tmp_buffer;
for ([[maybe_unused]] const int64_t iteration : IndexRange(iterations)) {
attribute_math::DefaultMixer<T> mixer{dst, IndexMask(0)};
threading::parallel_for(dst.index_range(), 1024, [&](const IndexRange range) {
for (const int64_t index : range) {
const Span<int> neighbors = neighbors_map[index];
const float neighbor_weight = neighbor_weights[index];
mixer.set(index, src[index], 1.0f);
for (const int neighbor : neighbors) {
mixer.mix_in(index, src[neighbor], neighbor_weight);
}
}
mixer.finalize(range);
});
std::swap(src, dst);
}
/* The last computed values are in #src now. If the main buffer is #dst, the values have to be
* copied once more. */
if (dst.data() == main_buffer.data()) {
threading::parallel_for(dst.index_range(), 1024, [&](const IndexRange range) {
initialized_copy_n(
src.data() + range.start(), range.size(), main_buffer.data() + range.start());
});
}
}
static void blur_on_mesh(const Mesh &mesh,
const eAttrDomain domain,
const int iterations,
const Span<float> neighbor_weights,
GMutableSpan main_buffer,
GMutableSpan tmp_buffer)
{
Array<Vector<int>> neighbors_map = create_mesh_map(mesh, domain, neighbor_weights.index_range());
if (neighbors_map.is_empty()) {
return;
}
attribute_math::convert_to_static_type(main_buffer.type(), [&](auto dummy) {
using T = decltype(dummy);
blur_on_mesh_exec<T>(neighbor_weights,
neighbors_map,
iterations,
main_buffer.typed<T>(),
tmp_buffer.typed<T>());
});
}
template<typename T>
static void blur_on_curve_exec(const bke::CurvesGeometry &curves,
const Span<float> neighbor_weights,
const int iterations,
MutableSpan<T> main_buffer,
MutableSpan<T> tmp_buffer)
{
MutableSpan<T> src = main_buffer;
MutableSpan<T> dst = tmp_buffer;
const VArray<bool> cyclic = curves.cyclic();
for ([[maybe_unused]] const int iteration : IndexRange(iterations)) {
attribute_math::DefaultMixer<T> mixer{dst, IndexMask(0)};
threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange range) {
for (const int curve_i : range) {
const IndexRange points = curves.points_for_curve(curve_i);
if (points.size() == 1) {
/* No mixing possible. */
const int point_i = points[0];
mixer.set(point_i, src[point_i], 1.0f);
continue;
}
/* Inner points. */
for (const int point_i : points.drop_front(1).drop_back(1)) {
const float neighbor_weight = neighbor_weights[point_i];
mixer.set(point_i, src[point_i], 1.0f);
mixer.mix_in(point_i, src[point_i - 1], neighbor_weight);
mixer.mix_in(point_i, src[point_i + 1], neighbor_weight);
}
const int first_i = points[0];
const float first_neighbor_weight = neighbor_weights[first_i];
const int last_i = points.last();
const float last_neighbor_weight = neighbor_weights[last_i];
if (cyclic[curve_i]) {
/* First point. */
mixer.set(first_i, src[first_i], 1.0f);
mixer.mix_in(first_i, src[first_i + 1], first_neighbor_weight);
mixer.mix_in(first_i, src[last_i], first_neighbor_weight);
/* Last point. */
mixer.set(last_i, src[last_i], 1.0f);
mixer.mix_in(last_i, src[last_i - 1], last_neighbor_weight);
mixer.mix_in(last_i, src[first_i], last_neighbor_weight);
}
else {
/* First point. */
mixer.set(first_i, src[first_i], 1.0f);
mixer.mix_in(first_i, src[first_i + 1], first_neighbor_weight);
/* Last point. */
mixer.set(last_i, src[last_i], 1.0f);
mixer.mix_in(last_i, src[last_i - 1], last_neighbor_weight);
}
}
mixer.finalize(curves.points_for_curves(range));
});
std::swap(src, dst);
}
/* The last computed values are in #src now. If the main buffer is #dst, the values have to be
* copied once more. */
if (dst.data() == main_buffer.data()) {
threading::parallel_for(dst.index_range(), 1024, [&](const IndexRange range) {
initialized_copy_n(
src.data() + range.start(), range.size(), main_buffer.data() + range.start());
});
}
}
static void blur_on_curves(const bke::CurvesGeometry &curves,
const int iterations,
const Span<float> neighbor_weights,
GMutableSpan main_buffer,
GMutableSpan tmp_buffer)
{
attribute_math::convert_to_static_type(main_buffer.type(), [&](auto dummy) {
using T = decltype(dummy);
blur_on_curve_exec<T>(
curves, neighbor_weights, iterations, main_buffer.typed<T>(), tmp_buffer.typed<T>());
});
}
class BlurAttributeFieldInput final : public bke::GeometryFieldInput {
private:
const Field<float> weight_field_;
const GField value_field_;
const int iterations_;
public:
BlurAttributeFieldInput(Field<float> weight_field, GField value_field, const int iterations)
: bke::GeometryFieldInput(value_field.cpp_type(), "Blur Attribute"),
weight_field_(std::move(weight_field)),
value_field_(std::move(value_field)),
iterations_(iterations)
{
}
GVArray get_varray_for_context(const bke::GeometryFieldContext &context,
const IndexMask /*mask*/) const final
{
const int64_t domain_size = context.attributes()->domain_size(context.domain());
GArray<> main_buffer(*type_, domain_size);
FieldEvaluator evaluator(context, domain_size);
evaluator.add_with_destination(value_field_, main_buffer.as_mutable_span());
evaluator.add(weight_field_);
evaluator.evaluate();
/* Blurring does not make sense with a less than 2 elements. */
if (domain_size <= 1) {
return GVArray::ForGArray(std::move(main_buffer));
}
if (iterations_ <= 0) {
return GVArray::ForGArray(std::move(main_buffer));
}
VArraySpan<float> neighbor_weights = evaluator.get_evaluated<float>(1);
GArray<> tmp_buffer(*type_, domain_size);
switch (context.type()) {
case GEO_COMPONENT_TYPE_MESH:
if (ELEM(context.domain(), ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE, ATTR_DOMAIN_FACE)) {
if (const Mesh *mesh = context.mesh()) {
blur_on_mesh(
*mesh, context.domain(), iterations_, neighbor_weights, main_buffer, tmp_buffer);
}
}
break;
case GEO_COMPONENT_TYPE_CURVE:
if (context.domain() == ATTR_DOMAIN_POINT) {
if (const bke::CurvesGeometry *curves = context.curves()) {
blur_on_curves(*curves, iterations_, neighbor_weights, main_buffer, tmp_buffer);
}
}
break;
default:
break;
}
return GVArray::ForGArray(std::move(main_buffer));
}
uint64_t hash() const override
{
return get_default_hash_3(iterations_, weight_field_, value_field_);
}
bool is_equal_to(const fn::FieldNode &other) const override
{
if (const BlurAttributeFieldInput *other_blur = dynamic_cast<const BlurAttributeFieldInput *>(
&other)) {
return weight_field_ == other_blur->weight_field_ &&
value_field_ == other_blur->value_field_ && iterations_ == other_blur->iterations_;
}
return false;
}
};
static StringRefNull identifier_suffix(eCustomDataType data_type)
{
switch (data_type) {
case CD_PROP_FLOAT:
return "Float";
case CD_PROP_INT32:
return "Int";
case CD_PROP_COLOR:
return "Color";
case CD_PROP_FLOAT3:
return "Vector";
default:
BLI_assert_unreachable();
return "";
}
}
static void node_geo_exec(GeoNodeExecParams params)
{
const eCustomDataType data_type = static_cast<eCustomDataType>(params.node().custom1);
const int iterations = params.extract_input<int>("Iterations");
Field<float> weight_field = params.extract_input<Field<float>>("Weight");
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
static const std::string identifier = "Value_" + identifier_suffix(data_type);
Field<T> value_field = params.extract_input<Field<T>>(identifier);
Field<T> output_field{std::make_shared<BlurAttributeFieldInput>(
std::move(weight_field), std::move(value_field), iterations)};
params.set_output(identifier, std::move(output_field));
});
}
} // namespace blender::nodes::node_geo_blur_attribute_cc
void register_node_type_geo_blur_attribute()
{
namespace file_ns = blender::nodes::node_geo_blur_attribute_cc;
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_BLUR_ATTRIBUTE, "Blur Attribute", NODE_CLASS_ATTRIBUTE);
ntype.declare = file_ns::node_declare;
ntype.initfunc = file_ns::node_init;
ntype.updatefunc = file_ns::node_update;
ntype.draw_buttons = file_ns::node_layout;
ntype.geometry_node_execute = file_ns::node_geo_exec;
ntype.gather_link_search_ops = file_ns::node_gather_link_searches;
nodeRegisterType(&ntype);
}

View File

@ -70,10 +70,13 @@ static void node_gather_link_searches(GatherLinkSearchOpParams &params)
node_storage(node).data_type = *type;
params.update_and_connect_available_socket(node, "Attribute");
});
params.add_item(IFACE_("Exists"), [node_type](LinkSearchOpParams &params) {
bNode &node = params.add_node(node_type);
params.update_and_connect_available_socket(node, "Exists");
});
params.add_item(
IFACE_("Exists"),
[node_type](LinkSearchOpParams &params) {
bNode &node = params.add_node(node_type);
params.update_and_connect_available_socket(node, "Exists");
},
-1);
}
}
}

View File

@ -373,8 +373,8 @@ static void calculate_cone_faces(const ConeConfig &config,
MutableSpan<int> corner_edges,
MutableSpan<MPoly> polys)
{
int rings_poly_start;
int rings_loop_start;
int rings_poly_start = 0;
int rings_loop_start = 0;
if (config.top_has_center_vert) {
rings_poly_start = config.circle_segments;
rings_loop_start = config.circle_segments * 3;

View File

@ -120,22 +120,32 @@ static void node_gather_link_searches(GatherLinkSearchOpParams &params)
});
}
else {
/* Make sure the switch input comes first in the search for boolean sockets. */
int true_false_weights = 0;
if (params.other_socket().type == SOCK_BOOLEAN) {
params.add_item(IFACE_("Switch"), [](LinkSearchOpParams &params) {
bNode &node = params.add_node("GeometryNodeSwitch");
params.update_and_connect_available_socket(node, "Switch");
});
true_false_weights--;
}
params.add_item(IFACE_("False"), [](LinkSearchOpParams &params) {
bNode &node = params.add_node("GeometryNodeSwitch");
node_storage(node).input_type = params.socket.type;
params.update_and_connect_available_socket(node, "False");
});
params.add_item(IFACE_("True"), [](LinkSearchOpParams &params) {
bNode &node = params.add_node("GeometryNodeSwitch");
node_storage(node).input_type = params.socket.type;
params.update_and_connect_available_socket(node, "True");
});
params.add_item(
IFACE_("False"),
[](LinkSearchOpParams &params) {
bNode &node = params.add_node("GeometryNodeSwitch");
node_storage(node).input_type = params.socket.type;
params.update_and_connect_available_socket(node, "False");
},
true_false_weights);
params.add_item(
IFACE_("True"),
[](LinkSearchOpParams &params) {
bNode &node = params.add_node("GeometryNodeSwitch");
node_storage(node).input_type = params.socket.type;
params.update_and_connect_available_socket(node, "True");
},
true_false_weights);
}
}

View File

@ -569,8 +569,7 @@ class LazyFunctionForViewerNode : public LazyFunction {
used_domain = *detected_domain;
}
else {
used_domain = type == GEO_COMPONENT_TYPE_MESH ? ATTR_DOMAIN_CORNER :
ATTR_DOMAIN_POINT;
used_domain = ATTR_DOMAIN_POINT;
}
}
bke::try_capture_field_on_geometry(

View File

@ -308,7 +308,7 @@ static bNodeSocket *node_find_linkable_socket(bNodeTree *ntree,
{
bNodeSocket *first = to_socket->in_out == SOCK_IN ?
static_cast<bNodeSocket *>(node->inputs.first) :
static_cast<bNodeSocket *>((node->outputs.first));
static_cast<bNodeSocket *>(node->outputs.first);
/* Wrap around the list end. */
bNodeSocket *socket_iter = to_socket->next ? to_socket->next : first;

View File

@ -141,55 +141,83 @@ class SocketSearchOp {
static void node_mix_gather_link_searches(GatherLinkSearchOpParams &params)
{
const eNodeSocketDatatype sock_type = static_cast<eNodeSocketDatatype>(
params.other_socket().type);
eNodeSocketDatatype type;
switch (eNodeSocketDatatype(params.other_socket().type)) {
case SOCK_BOOLEAN:
case SOCK_INT:
case SOCK_FLOAT:
type = SOCK_FLOAT;
break;
case SOCK_VECTOR:
type = SOCK_VECTOR;
break;
case SOCK_RGBA:
type = SOCK_RGBA;
break;
default:
return;
}
if (ELEM(sock_type, SOCK_BOOLEAN, SOCK_FLOAT, SOCK_RGBA, SOCK_VECTOR, SOCK_INT)) {
const eNodeSocketDatatype type = ELEM(sock_type, SOCK_BOOLEAN, SOCK_INT) ? SOCK_FLOAT :
sock_type;
const int weight = ELEM(params.other_socket().type, SOCK_RGBA) ? 0 : -1;
const std::string socket_name = params.in_out() == SOCK_IN ? "A" : "Result";
for (const EnumPropertyItem *item = rna_enum_ramp_blend_items; item->identifier != nullptr;
item++) {
if (item->name != nullptr && item->identifier[0] != '\0') {
params.add_item(CTX_IFACE_(BLT_I18NCONTEXT_ID_NODETREE, item->name),
SocketSearchOp{socket_name, item->value},
weight);
}
}
if (params.in_out() == SOCK_OUT) {
params.add_item(IFACE_("Result"), [type](LinkSearchOpParams &params) {
bNode &node = params.add_node("ShaderNodeMix");
node_storage(node).data_type = type;
params.update_and_connect_available_socket(node, "Result");
});
}
else {
if (ELEM(sock_type, SOCK_VECTOR, SOCK_RGBA)) {
params.add_item(IFACE_("Factor (Non-Uniform)"), [](LinkSearchOpParams &params) {
int weight = 0;
if (params.in_out() == SOCK_OUT) {
params.add_item(IFACE_("Result"), [type](LinkSearchOpParams &params) {
bNode &node = params.add_node("ShaderNodeMix");
node_storage(node).data_type = type;
params.update_and_connect_available_socket(node, "Result");
});
}
else {
params.add_item(
IFACE_("A"),
[type](LinkSearchOpParams &params) {
bNode &node = params.add_node("ShaderNodeMix");
node_storage(node).data_type = SOCK_VECTOR;
node_storage(node).factor_mode = NODE_MIX_MODE_NON_UNIFORM;
node_storage(node).data_type = type;
params.update_and_connect_available_socket(node, "A");
},
weight);
weight--;
params.add_item(
IFACE_("B"),
[type](LinkSearchOpParams &params) {
bNode &node = params.add_node("ShaderNodeMix");
node_storage(node).data_type = type;
params.update_and_connect_available_socket(node, "B");
},
weight);
weight--;
if (ELEM(type, SOCK_VECTOR, SOCK_RGBA)) {
params.add_item(
IFACE_("Factor (Non-Uniform)"),
[](LinkSearchOpParams &params) {
bNode &node = params.add_node("ShaderNodeMix");
node_storage(node).data_type = SOCK_VECTOR;
node_storage(node).factor_mode = NODE_MIX_MODE_NON_UNIFORM;
params.update_and_connect_available_socket(node, "Factor");
},
weight);
weight--;
}
params.add_item(
IFACE_("Factor"),
[type](LinkSearchOpParams &params) {
bNode &node = params.add_node("ShaderNodeMix");
node_storage(node).data_type = type;
params.update_and_connect_available_socket(node, "Factor");
});
}
params.add_item(IFACE_("Factor"), [type](LinkSearchOpParams &params) {
bNode &node = params.add_node("ShaderNodeMix");
node_storage(node).data_type = type;
params.update_and_connect_available_socket(node, "Factor");
});
params.add_item(IFACE_("A"), [type](LinkSearchOpParams &params) {
bNode &node = params.add_node("ShaderNodeMix");
node_storage(node).data_type = type;
params.update_and_connect_available_socket(node, "A");
});
params.add_item(IFACE_("B"), [type](LinkSearchOpParams &params) {
bNode &node = params.add_node("ShaderNodeMix");
node_storage(node).data_type = type;
params.update_and_connect_available_socket(node, "B");
});
},
weight);
weight--;
}
if (type != SOCK_RGBA) {
weight--;
}
const std::string socket_name = params.in_out() == SOCK_IN ? "A" : "Result";
for (const EnumPropertyItem *item = rna_enum_ramp_blend_items; item->identifier != nullptr;
item++) {
if (item->name != nullptr && item->identifier[0] != '\0') {
params.add_item(CTX_IFACE_(BLT_I18NCONTEXT_ID_NODETREE, item->name),
SocketSearchOp{socket_name, item->value},
weight);
}
}
}

View File

@ -36,7 +36,7 @@ static float noise(int n) /* fast integer noise */
int nn;
n = (n >> 13) ^ n;
nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
return 0.5f * ((float)nn / 1073741824.0f);
return 0.5f * (float(nn) / 1073741824.0f);
}
static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread)

View File

@ -28,8 +28,8 @@ static void rotate(float new_co[3], float a, const float ax[3], const float co[3
float perp[3];
float cp[3];
float cos_a = cosf(a * (float)(2 * M_PI));
float sin_a = sinf(a * (float)(2 * M_PI));
float cos_a = cosf(a * float(2 * M_PI));
float sin_a = sinf(a * float(2 * M_PI));
/* `x' = xcosa + n(n.x)(1-cosa) + (x*n)sina`. */

View File

@ -777,8 +777,8 @@ void RE_bake_pixels_populate(Mesh *me,
* up our intersection tests where a pixel gets in between 2 faces or the middle of a quad,
* camera aligned quads also have this problem but they are less common.
* Add a small offset to the UVs, fixes bug T18685. */
vec[a][0] = (uv[0] - bk_image->uv_offset[0]) * (float)bk_image->width - (0.5f + 0.001f);
vec[a][1] = (uv[1] - bk_image->uv_offset[1]) * (float)bk_image->height - (0.5f + 0.002f);
vec[a][0] = (uv[0] - bk_image->uv_offset[0]) * float(bk_image->width) - (0.5f + 0.001f);
vec[a][1] = (uv[1] - bk_image->uv_offset[1]) * float(bk_image->height) - (0.5f + 0.002f);
}
/* Rasterize triangle. */

View File

@ -420,8 +420,8 @@ static void *do_multires_bake_thread(void *data_v)
}
if (bkr->progress) {
*bkr->progress = ((float)bkr->baked_objects +
(float)bkr->baked_faces / handle->queue->tot_tri) /
*bkr->progress = (float(bkr->baked_objects) +
float(bkr->baked_faces) / handle->queue->tot_tri) /
bkr->tot_obj;
}
BLI_spin_unlock(&handle->queue->spin);
@ -622,10 +622,10 @@ static void interp_bilinear_grid(
float u, v;
float data[4][3];
x0 = (int)crn_x;
x0 = int(crn_x);
x1 = x0 >= (key->grid_size - 1) ? (key->grid_size - 1) : (x0 + 1);
y0 = (int)crn_y;
y0 = int(crn_y);
y1 = y0 >= (key->grid_size - 1) ? (key->grid_size - 1) : (y0 + 1);
u = crn_x - x0;