Geometry Node: Multi-input socket tooltip #104468
|
@ -603,7 +603,10 @@ void ANIM_armature_bonecoll_name_set(bArmature *armature, BoneCollection *bcoll,
|
|||
|
||||
bonecoll_ensure_name_unique(armature, bcoll);
|
||||
|
||||
/* Bone collections can be reached via .collections (4.0+) and .collections_all (4.1+).
|
||||
* Animation data from 4.0 should have been versioned to only use `.collections_all`. */
|
||||
BKE_animdata_fix_paths_rename_all(&armature->id, "collections", old_name, bcoll->name);
|
||||
BKE_animdata_fix_paths_rename_all(&armature->id, "collections_all", old_name, bcoll->name);
|
||||
}
|
||||
|
||||
void ANIM_armature_bonecoll_remove_from_index(bArmature *armature, int index)
|
||||
|
|
|
@ -98,18 +98,19 @@ void BKE_gpencil_cache_data_init(Depsgraph *depsgraph, Object *ob)
|
|||
}
|
||||
if (mmd->cache_data) {
|
||||
BKE_shrinkwrap_free_tree(mmd->cache_data);
|
||||
MEM_SAFE_FREE(mmd->cache_data);
|
||||
MEM_delete(mmd->cache_data);
|
||||
mmd->cache_data = nullptr;
|
||||
}
|
||||
Object *ob_target = DEG_get_evaluated_object(depsgraph, ob);
|
||||
Mesh *target = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target);
|
||||
mmd->cache_data = static_cast<ShrinkwrapTreeData *>(
|
||||
MEM_callocN(sizeof(ShrinkwrapTreeData), __func__));
|
||||
mmd->cache_data = MEM_new<ShrinkwrapTreeData>(__func__);
|
||||
if (BKE_shrinkwrap_init_tree(
|
||||
mmd->cache_data, target, mmd->shrink_type, mmd->shrink_mode, false))
|
||||
{
|
||||
}
|
||||
else {
|
||||
MEM_SAFE_FREE(mmd->cache_data);
|
||||
MEM_delete(mmd->cache_data);
|
||||
mmd->cache_data = nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -136,7 +137,8 @@ void BKE_gpencil_cache_data_clear(Object *ob)
|
|||
ShrinkwrapGpencilModifierData *mmd = (ShrinkwrapGpencilModifierData *)md;
|
||||
if ((mmd) && (mmd->cache_data)) {
|
||||
BKE_shrinkwrap_free_tree(mmd->cache_data);
|
||||
MEM_SAFE_FREE(mmd->cache_data);
|
||||
MEM_delete(mmd->cache_data);
|
||||
mmd->cache_data = nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -276,12 +276,6 @@ static void compositor_engine_draw(void *data)
|
|||
* the GPU for extended periods of time and sub-optimally schedule work for execution. */
|
||||
GPU_flush();
|
||||
}
|
||||
else {
|
||||
/* Realtime Compositor is not supported on macOS with the OpenGL backend. */
|
||||
blender::StringRef("Viewport compositor is only supported on MacOS with the Metal Backend.")
|
||||
.copy(compositor_data->info, GPU_INFO_SIZE);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Execute Compositor render commands. */
|
||||
|
|
|
@ -3259,14 +3259,6 @@ void DRW_gpu_context_enable_ex(bool /*restore*/)
|
|||
void DRW_gpu_context_disable_ex(bool restore)
|
||||
{
|
||||
if (DST.system_gpu_context != nullptr) {
|
||||
#ifdef __APPLE__
|
||||
/* Need to flush before disabling draw context, otherwise it does not
|
||||
* always finish drawing and viewport can be empty or partially drawn */
|
||||
if (GPU_type_matches_ex(GPU_DEVICE_ANY, GPU_OS_MAC, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) {
|
||||
GPU_flush();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (BLI_thread_is_main() && restore) {
|
||||
wm_window_reset_drawable();
|
||||
}
|
||||
|
|
|
@ -1105,20 +1105,6 @@ void UI_widgetbase_draw_cache_end()
|
|||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
|
||||
/* Disable cached/instanced drawing and enforce single widget drawing pipeline.
|
||||
* Works around interface artifacts happening on certain driver and hardware
|
||||
* configurations. */
|
||||
static bool draw_widgetbase_batch_skip_draw_cache()
|
||||
{
|
||||
/* MacOS is known to have issues on Mac Mini and MacBook Pro with Intel Iris GPU.
|
||||
* For example, #78307. */
|
||||
if (GPU_type_matches_ex(GPU_DEVICE_INTEL, GPU_OS_MAC, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void draw_widgetbase_batch(uiWidgetBase *wtb)
|
||||
{
|
||||
wtb->uniform_params.tria_type = wtb->tria1.type;
|
||||
|
@ -1127,7 +1113,7 @@ static void draw_widgetbase_batch(uiWidgetBase *wtb)
|
|||
copy_v2_v2(wtb->uniform_params.tria1_center, wtb->tria1.center);
|
||||
copy_v2_v2(wtb->uniform_params.tria2_center, wtb->tria2.center);
|
||||
|
||||
if (g_widget_base_batch.enabled && !draw_widgetbase_batch_skip_draw_cache()) {
|
||||
if (g_widget_base_batch.enabled) {
|
||||
g_widget_base_batch.params[g_widget_base_batch.count] = wtb->uniform_params;
|
||||
g_widget_base_batch.count++;
|
||||
|
||||
|
|
|
@ -284,16 +284,6 @@ void immDrawPixelsTexTiled_scaling_clipping(IMMDrawPixelsTexState *state,
|
|||
immAttr2f(texco, left / float(tex_w), top / float(tex_h));
|
||||
immVertex2f(pos, rast_x + offset_left * xzoom, rast_y + top * yzoom * scaleY);
|
||||
immEnd();
|
||||
|
||||
/* NOTE: Weirdly enough this is only required on macOS. Without this there is some sort of
|
||||
* bleeding of data is happening from tiles which are drawn later on.
|
||||
* This doesn't seem to be too slow,
|
||||
* but still would be nice to have fast and nice solution. */
|
||||
#ifdef __APPLE__
|
||||
if (GPU_type_matches_ex(GPU_DEVICE_ANY, GPU_OS_MAC, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) {
|
||||
GPU_flush();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -105,12 +105,11 @@ static EnumPropertyItem solver_modes[] = {
|
|||
struct TrimOperation {
|
||||
gesture::Operation op;
|
||||
|
||||
/* Operation-generated geometry. */
|
||||
Mesh *mesh;
|
||||
float (*true_mesh_co)[3];
|
||||
|
||||
float depth_front;
|
||||
float depth_back;
|
||||
|
||||
/* Operator properties. */
|
||||
bool use_cursor_depth;
|
||||
|
||||
OperationType mode;
|
||||
|
@ -119,6 +118,7 @@ struct TrimOperation {
|
|||
ExtrudeMode extrude_mode;
|
||||
};
|
||||
|
||||
/* Recalculate the mesh normals for the generated trim mesh. */
|
||||
static void update_normals(gesture::GestureData &gesture_data)
|
||||
{
|
||||
TrimOperation *trim_operation = (TrimOperation *)gesture_data.operation;
|
||||
|
@ -151,8 +151,8 @@ static void update_normals(gesture::GestureData &gesture_data)
|
|||
trim_operation->mesh = result;
|
||||
}
|
||||
|
||||
/* Get the origin and normal that are going to be used for calculating the depth and position the
|
||||
* trimming geometry. */
|
||||
/* Get the origin and normal that are going to be used for calculating the depth and position of
|
||||
* the trimming geometry. */
|
||||
static void get_origin_and_normal(gesture::GestureData &gesture_data,
|
||||
float *r_origin,
|
||||
float *r_normal)
|
||||
|
@ -182,7 +182,10 @@ static void get_origin_and_normal(gesture::GestureData &gesture_data,
|
|||
}
|
||||
}
|
||||
|
||||
static void calculate_depth(gesture::GestureData &gesture_data)
|
||||
/* Calculates the depth of the drawn shape inside the scene.*/
|
||||
static void calculate_depth(gesture::GestureData &gesture_data,
|
||||
float &r_depth_front,
|
||||
float &r_depth_back)
|
||||
{
|
||||
TrimOperation *trim_operation = (TrimOperation *)gesture_data.operation;
|
||||
|
||||
|
@ -197,8 +200,8 @@ static void calculate_depth(gesture::GestureData &gesture_data)
|
|||
get_origin_and_normal(gesture_data, shape_origin, shape_normal);
|
||||
plane_from_point_normal_v3(shape_plane, shape_origin, shape_normal);
|
||||
|
||||
trim_operation->depth_front = FLT_MAX;
|
||||
trim_operation->depth_back = -FLT_MAX;
|
||||
float depth_front = FLT_MAX;
|
||||
float depth_back = -FLT_MAX;
|
||||
|
||||
for (int i = 0; i < totvert; i++) {
|
||||
PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i);
|
||||
|
@ -210,8 +213,8 @@ static void calculate_depth(gesture::GestureData &gesture_data)
|
|||
float world_space_vco[3];
|
||||
mul_v3_m4v3(world_space_vco, vc->obact->object_to_world().ptr(), vco);
|
||||
const float dist = dist_signed_to_plane_v3(world_space_vco, shape_plane);
|
||||
trim_operation->depth_front = min_ff(dist, trim_operation->depth_front);
|
||||
trim_operation->depth_back = max_ff(dist, trim_operation->depth_back);
|
||||
depth_front = min_ff(dist, depth_front);
|
||||
depth_back = max_ff(dist, depth_back);
|
||||
}
|
||||
|
||||
if (trim_operation->use_cursor_depth) {
|
||||
|
@ -225,15 +228,13 @@ static void calculate_depth(gesture::GestureData &gesture_data)
|
|||
mid_point_depth = ss->gesture_initial_hit ?
|
||||
dist_signed_to_plane_v3(world_space_gesture_initial_location,
|
||||
shape_plane) :
|
||||
(trim_operation->depth_back + trim_operation->depth_front) * 0.5f;
|
||||
(depth_back + depth_front) * 0.5f;
|
||||
}
|
||||
else {
|
||||
/* When using normal orientation, if the stroke started over the mesh, position the mid point
|
||||
* at 0 distance from the shape plane. This positions the trimming shape half inside of the
|
||||
* surface. */
|
||||
mid_point_depth = ss->gesture_initial_hit ?
|
||||
0.0f :
|
||||
(trim_operation->depth_back + trim_operation->depth_front) * 0.5f;
|
||||
mid_point_depth = ss->gesture_initial_hit ? 0.0f : (depth_back + depth_front) * 0.5f;
|
||||
}
|
||||
|
||||
float depth_radius;
|
||||
|
@ -260,9 +261,12 @@ static void calculate_depth(gesture::GestureData &gesture_data)
|
|||
}
|
||||
}
|
||||
|
||||
trim_operation->depth_front = mid_point_depth - depth_radius;
|
||||
trim_operation->depth_back = mid_point_depth + depth_radius;
|
||||
depth_front = mid_point_depth - depth_radius;
|
||||
depth_back = mid_point_depth + depth_radius;
|
||||
}
|
||||
|
||||
r_depth_front = depth_front;
|
||||
r_depth_back = depth_back;
|
||||
}
|
||||
|
||||
static void generate_geometry(gesture::GestureData &gesture_data)
|
||||
|
@ -281,20 +285,6 @@ static void generate_geometry(gesture::GestureData &gesture_data)
|
|||
trim_operation->true_mesh_co = static_cast<float(*)[3]>(
|
||||
MEM_malloc_arrayN(trim_totverts, sizeof(float[3]), "mesh orco"));
|
||||
|
||||
float depth_front = trim_operation->depth_front;
|
||||
float depth_back = trim_operation->depth_back;
|
||||
float pad_factor = 0.0f;
|
||||
|
||||
if (!trim_operation->use_cursor_depth) {
|
||||
pad_factor = (depth_back - depth_front) * 0.01f + 0.001f;
|
||||
|
||||
/* When using cursor depth, don't modify the depth set by the cursor radius. If full depth is
|
||||
* used, adding a little padding to the trimming shape can help avoiding booleans with coplanar
|
||||
* faces. */
|
||||
depth_front -= pad_factor;
|
||||
depth_back += pad_factor;
|
||||
}
|
||||
|
||||
float shape_origin[3];
|
||||
float shape_normal[3];
|
||||
float shape_plane[4];
|
||||
|
@ -306,6 +296,20 @@ static void generate_geometry(gesture::GestureData &gesture_data)
|
|||
/* Write vertices coordinates OperationType::Difference for the front face. */
|
||||
MutableSpan<float3> positions = trim_operation->mesh->vert_positions_for_write();
|
||||
|
||||
float depth_front;
|
||||
float depth_back;
|
||||
calculate_depth(gesture_data, depth_front, depth_back);
|
||||
|
||||
if (!trim_operation->use_cursor_depth) {
|
||||
float pad_factor = (depth_back - depth_front) * 0.01f + 0.001f;
|
||||
|
||||
/* When using cursor depth, don't modify the depth set by the cursor radius. If full depth is
|
||||
* used, adding a little padding to the trimming shape can help avoiding booleans with coplanar
|
||||
* faces. */
|
||||
depth_front -= pad_factor;
|
||||
depth_back += pad_factor;
|
||||
}
|
||||
|
||||
float depth_point[3];
|
||||
|
||||
/* Get origin point for OrientationType::View.
|
||||
|
@ -436,11 +440,16 @@ static void generate_geometry(gesture::GestureData &gesture_data)
|
|||
update_normals(gesture_data);
|
||||
}
|
||||
|
||||
static void free_geometry(gesture::GestureData &gesture_data)
|
||||
static void gesture_begin(bContext &C, gesture::GestureData &gesture_data)
|
||||
{
|
||||
TrimOperation *trim_operation = (TrimOperation *)gesture_data.operation;
|
||||
BKE_id_free(nullptr, trim_operation->mesh);
|
||||
MEM_freeN(trim_operation->true_mesh_co);
|
||||
Object *object = gesture_data.vc.obact;
|
||||
SculptSession *ss = object->sculpt;
|
||||
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(&C);
|
||||
generate_geometry(gesture_data);
|
||||
SCULPT_topology_islands_invalidate(ss);
|
||||
BKE_sculpt_update_object_for_edit(depsgraph, gesture_data.vc.obact, false);
|
||||
undo::push_node(gesture_data.vc.obact, nullptr, undo::Type::Geometry);
|
||||
}
|
||||
|
||||
static int bm_face_isect_pair(BMFace *f, void * /*user_data*/)
|
||||
|
@ -545,19 +554,6 @@ static void apply_trim(gesture::GestureData &gesture_data)
|
|||
result, static_cast<Mesh *>(gesture_data.vc.obact->data), gesture_data.vc.obact);
|
||||
}
|
||||
|
||||
static void gesture_begin(bContext &C, gesture::GestureData &gesture_data)
|
||||
{
|
||||
Object *object = gesture_data.vc.obact;
|
||||
SculptSession *ss = object->sculpt;
|
||||
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(&C);
|
||||
calculate_depth(gesture_data);
|
||||
generate_geometry(gesture_data);
|
||||
SCULPT_topology_islands_invalidate(ss);
|
||||
BKE_sculpt_update_object_for_edit(depsgraph, gesture_data.vc.obact, false);
|
||||
undo::push_node(gesture_data.vc.obact, nullptr, undo::Type::Geometry);
|
||||
}
|
||||
|
||||
static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureData &gesture_data)
|
||||
{
|
||||
TrimOperation *trim_operation = (TrimOperation *)gesture_data.operation;
|
||||
|
@ -570,6 +566,13 @@ static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureDa
|
|||
apply_trim(gesture_data);
|
||||
}
|
||||
|
||||
static void free_geometry(gesture::GestureData &gesture_data)
|
||||
{
|
||||
TrimOperation *trim_operation = (TrimOperation *)gesture_data.operation;
|
||||
BKE_id_free(nullptr, trim_operation->mesh);
|
||||
MEM_freeN(trim_operation->true_mesh_co);
|
||||
}
|
||||
|
||||
static void gesture_end(bContext & /*C*/, gesture::GestureData &gesture_data)
|
||||
{
|
||||
Object *object = gesture_data.vc.obact;
|
||||
|
|
|
@ -1385,7 +1385,8 @@ static void create_inspection_string_for_generic_value(const bNodeSocket &socket
|
|||
((*static_cast<bool *>(socket_value)) ? TIP_("True") : TIP_("False")));
|
||||
}
|
||||
else if (socket_type.is<float4x4>()) {
|
||||
const float4x4 &value = *static_cast<const float4x4 *>(socket_value);
|
||||
/* Transpose to be able to print row by row. */
|
||||
const float4x4 value = math::transpose(*static_cast<const float4x4 *>(socket_value));
|
||||
ss << value[0] << ",\n";
|
||||
ss << value[1] << ",\n";
|
||||
ss << value[2] << ",\n";
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "BLI_math_matrix.hh"
|
||||
#include "BLI_math_quaternion_types.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
|
@ -395,7 +396,8 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer {
|
|||
UI_but_func_tooltip_set(
|
||||
but,
|
||||
[](bContext * /*C*/, void *argN, const char * /*tip*/) {
|
||||
const float4x4 &value = *static_cast<const float4x4 *>(argN);
|
||||
/* Transpose to be able to print row by row. */
|
||||
const float4x4 value = math::transpose(*static_cast<const float4x4 *>(argN));
|
||||
std::stringstream ss;
|
||||
ss << value[0] << ",\n";
|
||||
ss << value[1] << ",\n";
|
||||
|
|
|
@ -238,6 +238,10 @@ ReverseUVSampler::Result ReverseUVSampler::sample(const float2 &query_uv) const
|
|||
* the lookup can fail for floating point accuracy reasons when the uv is almost exact on an
|
||||
* edge. */
|
||||
const float edge_epsilon = 0.00001f;
|
||||
/* If uv triangles are very small, it may look like the query hits multiple triangles due to
|
||||
* floating point precision issues. Better just pick one of the triangles instead of failing the
|
||||
* entire operation in this case. */
|
||||
const float area_epsilon = 0.00001f;
|
||||
|
||||
for (const int tri_i : tri_indices) {
|
||||
const int3 &tri = corner_tris_[tri_i];
|
||||
|
@ -260,8 +264,14 @@ ReverseUVSampler::Result ReverseUVSampler::sample(const float2 &query_uv) const
|
|||
const float worse_dist = std::max(dist, best_dist);
|
||||
/* Allow ignoring multiple triangle intersections if the uv is almost exactly on an edge. */
|
||||
if (worse_dist < -edge_epsilon) {
|
||||
/* The uv sample is in multiple triangles. */
|
||||
return Result{ResultType::Multiple};
|
||||
const int3 &best_tri = corner_tris_[tri_i];
|
||||
const float best_tri_area = area_tri_v2(
|
||||
uv_map_[best_tri[0]], uv_map_[best_tri[1]], uv_map_[best_tri[2]]);
|
||||
const float current_tri_area = area_tri_v2(uv_0, uv_1, uv_2);
|
||||
if (best_tri_area > area_epsilon && current_tri_area > area_epsilon) {
|
||||
/* The uv sample is in multiple triangles. */
|
||||
return Result{ResultType::Multiple};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -139,12 +139,12 @@ static void bake_modifier(Main * /*bmain*/,
|
|||
/* Recalculate shrinkwrap data. */
|
||||
if (mmd->cache_data) {
|
||||
BKE_shrinkwrap_free_tree(mmd->cache_data);
|
||||
MEM_SAFE_FREE(mmd->cache_data);
|
||||
MEM_delete(mmd->cache_data);
|
||||
mmd->cache_data = nullptr;
|
||||
}
|
||||
Object *ob_target = DEG_get_evaluated_object(depsgraph, mmd->target);
|
||||
Mesh *target = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target);
|
||||
mmd->cache_data = static_cast<ShrinkwrapTreeData *>(
|
||||
MEM_callocN(sizeof(ShrinkwrapTreeData), __func__));
|
||||
mmd->cache_data = MEM_new<ShrinkwrapTreeData>(__func__);
|
||||
if (BKE_shrinkwrap_init_tree(
|
||||
mmd->cache_data, target, mmd->shrink_type, mmd->shrink_mode, false))
|
||||
{
|
||||
|
@ -157,7 +157,8 @@ static void bake_modifier(Main * /*bmain*/,
|
|||
/* Free data. */
|
||||
if (mmd->cache_data) {
|
||||
BKE_shrinkwrap_free_tree(mmd->cache_data);
|
||||
MEM_SAFE_FREE(mmd->cache_data);
|
||||
MEM_delete(mmd->cache_data);
|
||||
mmd->cache_data = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -172,7 +173,7 @@ static void free_data(GpencilModifierData *md)
|
|||
ShrinkwrapGpencilModifierData *mmd = (ShrinkwrapGpencilModifierData *)md;
|
||||
if (mmd->cache_data) {
|
||||
BKE_shrinkwrap_free_tree(mmd->cache_data);
|
||||
MEM_SAFE_FREE(mmd->cache_data);
|
||||
MEM_delete(mmd->cache_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -467,7 +467,6 @@ void gpu_shader_create_info_init()
|
|||
GPU_OS_ANY,
|
||||
GPU_DRIVER_ANY,
|
||||
GPU_BACKEND_OPENGL) ||
|
||||
GPU_type_matches_ex(GPU_DEVICE_ANY, GPU_OS_MAC, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL) ||
|
||||
GPU_crappy_amd_driver())
|
||||
{
|
||||
draw_modelmat = draw_modelmat_legacy;
|
||||
|
|
|
@ -1902,7 +1902,7 @@ void MSLGeneratorInterface::prepare_from_createinfo(const shader::ShaderCreateIn
|
|||
case shader::ShaderCreateInfo::Resource::BindType::IMAGE: {
|
||||
/* Flatten qualifier flags into final access state. */
|
||||
MSLTextureSamplerAccess access;
|
||||
if (bool(res.image.qualifiers & Qualifier::READ_WRITE)) {
|
||||
if ((res.image.qualifiers & Qualifier::READ_WRITE) == Qualifier::READ_WRITE) {
|
||||
access = MSLTextureSamplerAccess::TEXTURE_ACCESS_READWRITE;
|
||||
}
|
||||
else if (bool(res.image.qualifiers & Qualifier::WRITE)) {
|
||||
|
|
|
@ -437,6 +437,12 @@ static const char *load_face_element(PlyReadBuffer &file,
|
|||
if (count < 1 || count > 255) {
|
||||
return "Invalid face size, must be between 1 and 255";
|
||||
}
|
||||
/* Previous python based importer was accepting faces with fewer
|
||||
* than 3 vertices, and silently dropping them. */
|
||||
if (count < 3) {
|
||||
fprintf(stderr, "PLY Importer: ignoring face %i (%i vertices)\n", i, count);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < count; j++) {
|
||||
int index;
|
||||
|
@ -467,15 +473,22 @@ static const char *load_face_element(PlyReadBuffer &file,
|
|||
|
||||
scratch.resize(count * data_type_size[prop.type]);
|
||||
file.read_bytes(scratch.data(), scratch.size());
|
||||
ptr = scratch.data();
|
||||
if (header.type == PlyFormatType::BINARY_BE) {
|
||||
endian_switch_array((uint8_t *)ptr, data_type_size[prop.type], count);
|
||||
/* Previous python based importer was accepting faces with fewer
|
||||
* than 3 vertices, and silently dropping them. */
|
||||
if (count < 3) {
|
||||
fprintf(stderr, "PLY Importer: ignoring face %i (%i vertices)\n", i, count);
|
||||
}
|
||||
for (int j = 0; j < count; ++j) {
|
||||
uint32_t index = get_binary_value<uint32_t>(prop.type, ptr);
|
||||
data->face_vertices.append(index);
|
||||
else {
|
||||
ptr = scratch.data();
|
||||
if (header.type == PlyFormatType::BINARY_BE) {
|
||||
endian_switch_array((uint8_t *)ptr, data_type_size[prop.type], count);
|
||||
}
|
||||
for (int j = 0; j < count; ++j) {
|
||||
uint32_t index = get_binary_value<uint32_t>(prop.type, ptr);
|
||||
data->face_vertices.append(index);
|
||||
}
|
||||
data->face_sizes.append(count);
|
||||
}
|
||||
data->face_sizes.append(count);
|
||||
|
||||
/* Skip any properties after vertex indices. */
|
||||
for (int j = prop_index + 1; j < element.properties.size(); j++) {
|
||||
|
|
|
@ -909,8 +909,7 @@ void USDMeshReader::read_custom_data(const ImportSettings *settings,
|
|||
|
||||
/* To avoid unnecessarily reloading static primvars during animation,
|
||||
* early out if not first load and this primvar isn't animated. */
|
||||
const bool is_time_varying = primvar_varying_map_.lookup_default(name, false);
|
||||
if (!new_mesh && !is_time_varying) {
|
||||
if (!new_mesh && primvar_varying_map_.contains(name) && !primvar_varying_map_.lookup(name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -69,11 +69,6 @@ set(SRC
|
|||
dna_utils.cc
|
||||
makesdna.cc
|
||||
${SRC_BLENLIB}
|
||||
../../../../intern/guardedalloc/intern/leak_detector.cc
|
||||
../../../../intern/guardedalloc/intern/mallocn.c
|
||||
../../../../intern/guardedalloc/intern/mallocn_guarded_impl.c
|
||||
../../../../intern/guardedalloc/intern/mallocn_lockfree_impl.c
|
||||
../../../../intern/guardedalloc/intern/memory_usage.cc
|
||||
${dna_header_include_file}
|
||||
${dna_header_string_file}
|
||||
)
|
||||
|
|
|
@ -222,12 +222,6 @@ set(SRC
|
|||
${DEFSRC}
|
||||
${APISRC}
|
||||
../../../../intern/clog/clog.c
|
||||
../../../../intern/guardedalloc/intern/leak_detector.cc
|
||||
../../../../intern/guardedalloc/intern/mallocn.c
|
||||
../../../../intern/guardedalloc/intern/mallocn_guarded_impl.c
|
||||
../../../../intern/guardedalloc/intern/mallocn_lockfree_impl.c
|
||||
../../../../intern/guardedalloc/intern/memory_usage.cc
|
||||
|
||||
# Needed for defaults.
|
||||
../../../../release/datafiles/userdef/userdef_default.c
|
||||
../../../../release/datafiles/userdef/userdef_default_theme.c
|
||||
|
|
|
@ -74,7 +74,7 @@ static void free_data(ModifierData *md)
|
|||
|
||||
if (smd->cache_data) {
|
||||
BKE_shrinkwrap_free_tree(smd->cache_data);
|
||||
MEM_SAFE_FREE(smd->cache_data);
|
||||
MEM_delete(smd->cache_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,17 +196,18 @@ static void ensure_shrinkwrap_cache_data(GreasePencilShrinkwrapModifierData &smd
|
|||
{
|
||||
if (smd.cache_data) {
|
||||
BKE_shrinkwrap_free_tree(smd.cache_data);
|
||||
MEM_SAFE_FREE(smd.cache_data);
|
||||
MEM_delete(smd.cache_data);
|
||||
smd.cache_data = nullptr;
|
||||
}
|
||||
Object *target_ob = DEG_get_evaluated_object(ctx.depsgraph, smd.target);
|
||||
Mesh *target_mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(target_ob);
|
||||
|
||||
smd.cache_data = static_cast<ShrinkwrapTreeData *>(
|
||||
MEM_callocN(sizeof(ShrinkwrapTreeData), __func__));
|
||||
smd.cache_data = MEM_new<ShrinkwrapTreeData>(__func__);
|
||||
const bool tree_ok = BKE_shrinkwrap_init_tree(
|
||||
smd.cache_data, target_mesh, smd.shrink_type, smd.shrink_mode, false);
|
||||
if (!tree_ok) {
|
||||
MEM_SAFE_FREE(smd.cache_data);
|
||||
MEM_delete(smd.cache_data);
|
||||
smd.cache_data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,9 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Matrix>("Matrix");
|
||||
b.add_output<decl::Matrix>("Matrix");
|
||||
b.add_output<decl::Matrix>("Matrix").description(
|
||||
"The inverted matrix or the identity matrix if the input is not invertable");
|
||||
b.add_output<decl::Bool>("Invertable").description("True if the input matrix is invertable");
|
||||
}
|
||||
|
||||
static void search_link_ops(GatherLinkSearchOpParams ¶ms)
|
||||
|
@ -24,10 +26,45 @@ static void search_link_ops(GatherLinkSearchOpParams ¶ms)
|
|||
}
|
||||
}
|
||||
|
||||
class InvertMatrixFunction : public mf::MultiFunction {
|
||||
public:
|
||||
InvertMatrixFunction()
|
||||
{
|
||||
static mf::Signature signature = []() {
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Invert Matrix", signature};
|
||||
builder.single_input<float4x4>("Matrix");
|
||||
builder.single_output<float4x4>("Matrix", mf::ParamFlag::SupportsUnusedOutput);
|
||||
builder.single_output<bool>("Invertable", mf::ParamFlag::SupportsUnusedOutput);
|
||||
return signature;
|
||||
}();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
|
||||
{
|
||||
const VArraySpan<float4x4> in_matrices = params.readonly_single_input<float4x4>(0, "Matrix");
|
||||
MutableSpan<float4x4> out_matrices = params.uninitialized_single_output_if_required<float4x4>(
|
||||
1, "Matrix");
|
||||
MutableSpan<bool> out_invertable = params.uninitialized_single_output_if_required<bool>(
|
||||
2, "Invertable");
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const float4x4 &matrix = in_matrices[i];
|
||||
bool success;
|
||||
float4x4 inverted_matrix = math::invert(matrix, success);
|
||||
if (!out_matrices.is_empty()) {
|
||||
out_matrices[i] = success ? inverted_matrix : float4x4::identity();
|
||||
}
|
||||
if (!out_invertable.is_empty()) {
|
||||
out_invertable[i] = success;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static auto fn = mf::build::SI1_SO<float4x4, float4x4>(
|
||||
"Invert Matrix", [](float4x4 matrix) { return math::invert(matrix); });
|
||||
static InvertMatrixFunction fn;
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue