Merge branch 'refactor-mesh-position-generic' into refactor-mesh-corners-generic
This commit is contained in:
commit
a9b193f663
|
@ -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}:-:*:*:*:*:*:*")
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -809,6 +809,11 @@ void BlenderDisplayDriver::draw(const Params ¶ms)
|
|||
* 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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -64,10 +64,6 @@ void HdCyclesDisplayDriver::gl_context_create()
|
|||
#endif
|
||||
|
||||
if (!gl_pbo_id_) {
|
||||
if (glewInit() != GLEW_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
glGenBuffers(1, &gl_pbo_id_);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 "
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) /
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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'}},
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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}};
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -123,6 +123,7 @@ set(LIB
|
|||
|
||||
list(APPEND LIB
|
||||
${BOOST_LIBRARIES}
|
||||
${BOOST_PYTHON_LIBRARIES}
|
||||
${PYTHON_LIBRARIES}
|
||||
)
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 ¶ms)
|
||||
{
|
||||
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 ¶ms) {
|
||||
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);
|
||||
}
|
|
@ -70,10 +70,13 @@ static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms)
|
|||
node_storage(node).data_type = *type;
|
||||
params.update_and_connect_available_socket(node, "Attribute");
|
||||
});
|
||||
params.add_item(IFACE_("Exists"), [node_type](LinkSearchOpParams ¶ms) {
|
||||
bNode &node = params.add_node(node_type);
|
||||
params.update_and_connect_available_socket(node, "Exists");
|
||||
});
|
||||
params.add_item(
|
||||
IFACE_("Exists"),
|
||||
[node_type](LinkSearchOpParams ¶ms) {
|
||||
bNode &node = params.add_node(node_type);
|
||||
params.update_and_connect_available_socket(node, "Exists");
|
||||
},
|
||||
-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -120,22 +120,32 @@ static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms)
|
|||
});
|
||||
}
|
||||
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 ¶ms) {
|
||||
bNode &node = params.add_node("GeometryNodeSwitch");
|
||||
params.update_and_connect_available_socket(node, "Switch");
|
||||
});
|
||||
true_false_weights--;
|
||||
}
|
||||
params.add_item(IFACE_("False"), [](LinkSearchOpParams ¶ms) {
|
||||
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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -141,55 +141,83 @@ class SocketSearchOp {
|
|||
|
||||
static void node_mix_gather_link_searches(GatherLinkSearchOpParams ¶ms)
|
||||
{
|
||||
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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
int weight = 0;
|
||||
if (params.in_out() == SOCK_OUT) {
|
||||
params.add_item(IFACE_("Result"), [type](LinkSearchOpParams ¶ms) {
|
||||
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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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`. */
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue