Overlay-Next: Initial implementation #107045

Closed
Clément Foucault wants to merge 28 commits from fclem/blender:overlay-next into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
182 changed files with 2627 additions and 1991 deletions
Showing only changes of commit 953cef7b7a - Show all commits

View File

@ -231,7 +231,7 @@ class FileBlockHeader:
self.SDNAIndex = 0
self.Count = 0
self.FileOffset = handle.tell()
#self.Code += ' ' * (4 - len(self.Code))
# self.Code += ' ' * (4 - len(self.Code))
log.debug("found blend-file-block-fileheader {0} {1}".format(self.Code, self.FileOffset))
def skip(self, handle):

View File

@ -182,7 +182,7 @@ class Device {
{
}
/* Return true if device is ready for rendering, or report status if not. */
/* Report status and return true if device is ready for rendering. */
virtual bool is_ready(string & /*status*/) const
{
return true;

View File

@ -490,6 +490,9 @@ bool MetalDevice::make_source_and_check_if_compile_needed(MetalPipelineType pso_
MD5Hash md5;
md5.append(constant_values);
md5.append(source[pso_type]);
if (use_metalrt) {
md5.append(string_printf("metalrt_features=%d", kernel_features & METALRT_FEATURE_MASK));
}
kernels_md5[pso_type] = md5.get_hex();
return MetalDeviceKernels::should_load_kernels(this, pso_type);
@ -934,6 +937,17 @@ bool MetalDevice::is_ready(string &status) const
DEVICE_KERNEL_NUM);
return false;
}
if (int num_requests = MetalDeviceKernels::num_incomplete_specialization_requests()) {
status = string_printf("%d kernels to optimize", num_requests);
}
else if (kernel_specialization_level == PSO_SPECIALIZED_INTERSECT) {
status = "Using optimized intersection kernels";
}
else if (kernel_specialization_level == PSO_SPECIALIZED_SHADE) {
status = "Using optimized kernels";
}
metal_printf("MetalDevice::is_ready(...) --> true\n");
return true;
}
@ -970,7 +984,7 @@ void MetalDevice::optimize_for_scene(Scene *scene)
}
if (specialize_in_background) {
if (!MetalDeviceKernels::any_specialization_happening_now()) {
if (MetalDeviceKernels::num_incomplete_specialization_requests() == 0) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
specialize_kernels_fn);
}

View File

@ -63,8 +63,7 @@ enum MetalPipelineType {
};
# define METALRT_FEATURE_MASK \
(KERNEL_FEATURE_HAIR | KERNEL_FEATURE_HAIR_THICK | KERNEL_FEATURE_POINTCLOUD | \
KERNEL_FEATURE_OBJECT_MOTION)
(KERNEL_FEATURE_HAIR | KERNEL_FEATURE_HAIR_THICK | KERNEL_FEATURE_POINTCLOUD)
const char *kernel_type_as_string(MetalPipelineType pso_type);
@ -81,7 +80,7 @@ struct MetalKernelPipeline {
KernelData kernel_data_;
bool use_metalrt;
uint32_t metalrt_features = 0;
uint32_t kernel_features = 0;
int threads_per_threadgroup;
@ -104,7 +103,7 @@ struct MetalKernelPipeline {
/* Cache of Metal kernels for each DeviceKernel. */
namespace MetalDeviceKernels {
bool any_specialization_happening_now();
int num_incomplete_specialization_requests();
int get_loaded_kernel_count(MetalDevice const *device, MetalPipelineType pso_type);
bool should_load_kernels(MetalDevice const *device, MetalPipelineType pso_type);
bool load(MetalDevice *device, MetalPipelineType pso_type);

View File

@ -344,9 +344,7 @@ void ShaderCache::load_kernel(DeviceKernel device_kernel,
/* metalrt options */
pipeline->use_metalrt = device->use_metalrt;
pipeline->metalrt_features = device->use_metalrt ?
(device->kernel_features & METALRT_FEATURE_MASK) :
0;
pipeline->kernel_features = device->kernel_features;
{
thread_scoped_lock lock(cache_mutex);
@ -357,65 +355,36 @@ void ShaderCache::load_kernel(DeviceKernel device_kernel,
MetalKernelPipeline *ShaderCache::get_best_pipeline(DeviceKernel kernel, const MetalDevice *device)
{
/* metalrt options */
bool use_metalrt = device->use_metalrt;
bool device_metalrt_hair = use_metalrt && device->kernel_features & KERNEL_FEATURE_HAIR;
bool device_metalrt_hair_thick = use_metalrt &&
device->kernel_features & KERNEL_FEATURE_HAIR_THICK;
bool device_metalrt_pointcloud = use_metalrt &&
device->kernel_features & KERNEL_FEATURE_POINTCLOUD;
bool device_metalrt_motion = use_metalrt &&
device->kernel_features & KERNEL_FEATURE_OBJECT_MOTION;
MetalKernelPipeline *best_pipeline = nullptr;
while (!best_pipeline) {
while (running) {
/* Search all loaded pipelines with matching kernels_md5 checksums. */
MetalKernelPipeline *best_match = nullptr;
{
thread_scoped_lock lock(cache_mutex);
for (auto &pipeline : pipelines[kernel]) {
if (!pipeline->loaded) {
/* still loading - ignore */
continue;
}
bool pipeline_metalrt_hair = pipeline->metalrt_features & KERNEL_FEATURE_HAIR;
bool pipeline_metalrt_hair_thick = pipeline->metalrt_features & KERNEL_FEATURE_HAIR_THICK;
bool pipeline_metalrt_pointcloud = pipeline->metalrt_features & KERNEL_FEATURE_POINTCLOUD;
bool pipeline_metalrt_motion = use_metalrt &&
pipeline->metalrt_features & KERNEL_FEATURE_OBJECT_MOTION;
if (pipeline->use_metalrt != use_metalrt || pipeline_metalrt_hair != device_metalrt_hair ||
pipeline_metalrt_hair_thick != device_metalrt_hair_thick ||
pipeline_metalrt_pointcloud != device_metalrt_pointcloud ||
pipeline_metalrt_motion != device_metalrt_motion) {
/* wrong combination of metalrt options */
continue;
}
if (pipeline->pso_type != PSO_GENERIC) {
if (pipeline->kernels_md5 == device->kernels_md5[PSO_SPECIALIZED_INTERSECT] ||
pipeline->kernels_md5 == device->kernels_md5[PSO_SPECIALIZED_SHADE]) {
best_pipeline = pipeline.get();
for (auto &candidate : pipelines[kernel]) {
if (candidate->loaded &&
candidate->kernels_md5 == device->kernels_md5[candidate->pso_type]) {
/* Replace existing match if candidate is more specialized. */
if (!best_match || candidate->pso_type > best_match->pso_type) {
best_match = candidate.get();
}
}
else if (!best_pipeline) {
best_pipeline = pipeline.get();
}
}
}
if (!best_pipeline) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (best_match) {
if (best_match->usage_count == 0 && best_match->pso_type != PSO_GENERIC) {
metal_printf("Swapping in %s version of %s\n",
kernel_type_as_string(best_match->pso_type),
device_kernel_as_string(kernel));
}
best_match->usage_count += 1;
return best_match;
}
}
if (best_pipeline->usage_count == 0 && best_pipeline->pso_type != PSO_GENERIC) {
metal_printf("Swapping in %s version of %s\n",
kernel_type_as_string(best_pipeline->pso_type),
device_kernel_as_string(kernel));
/* Spin until a matching kernel is loaded, or we're shutting down. */
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
best_pipeline->usage_count += 1;
return best_pipeline;
return nullptr;
}
bool MetalKernelPipeline::should_use_binary_archive() const
@ -570,18 +539,14 @@ void MetalKernelPipeline::compile()
NSArray *table_functions[METALRT_TABLE_NUM] = {nil};
NSArray *linked_functions = nil;
bool metalrt_hair = use_metalrt && (metalrt_features & KERNEL_FEATURE_HAIR);
bool metalrt_hair_thick = use_metalrt && (metalrt_features & KERNEL_FEATURE_HAIR_THICK);
bool metalrt_pointcloud = use_metalrt && (metalrt_features & KERNEL_FEATURE_POINTCLOUD);
if (use_metalrt) {
id<MTLFunction> curve_intersect_default = nil;
id<MTLFunction> curve_intersect_shadow = nil;
id<MTLFunction> point_intersect_default = nil;
id<MTLFunction> point_intersect_shadow = nil;
if (metalrt_hair) {
if (kernel_features & KERNEL_FEATURE_HAIR) {
/* Add curve intersection programs. */
if (metalrt_hair_thick) {
if (kernel_features & KERNEL_FEATURE_HAIR_THICK) {
/* Slower programs for thick hair since that also slows down ribbons.
* Ideally this should not be needed. */
curve_intersect_default = rt_intersection_function[METALRT_FUNC_CURVE_ALL];
@ -592,7 +557,7 @@ void MetalKernelPipeline::compile()
curve_intersect_shadow = rt_intersection_function[METALRT_FUNC_CURVE_RIBBON_SHADOW];
}
}
if (metalrt_pointcloud) {
if (kernel_features & KERNEL_FEATURE_POINTCLOUD) {
point_intersect_default = rt_intersection_function[METALRT_FUNC_POINT];
point_intersect_shadow = rt_intersection_function[METALRT_FUNC_POINT_SHADOW];
}
@ -682,15 +647,6 @@ void MetalKernelPipeline::compile()
local_md5.append((uint8_t *)&this->threads_per_threadgroup,
sizeof(this->threads_per_threadgroup));
string options;
if (use_metalrt && kernel_has_intersection(device_kernel)) {
/* incorporate any MetalRT specializations into the archive name */
options += string_printf(".hair_%d.hair_thick_%d.pointcloud_%d",
metalrt_hair ? 1 : 0,
metalrt_hair_thick ? 1 : 0,
metalrt_pointcloud ? 1 : 0);
}
/* Replace non-alphanumerical characters with underscores. */
string device_name = [mtlDevice.name UTF8String];
for (char &c : device_name) {
@ -702,7 +658,7 @@ void MetalKernelPipeline::compile()
metalbin_name = device_name;
metalbin_name = path_join(metalbin_name, device_kernel_as_string(device_kernel));
metalbin_name = path_join(metalbin_name, kernel_type_as_string(pso_type));
metalbin_name = path_join(metalbin_name, local_md5.get_hex() + options + ".bin");
metalbin_name = path_join(metalbin_name, local_md5.get_hex() + ".bin");
metalbin_path = path_cache_get(path_join("kernels", metalbin_name));
path_create_directories(metalbin_path);
@ -860,16 +816,15 @@ void MetalDeviceKernels::wait_for_all()
}
}
bool MetalDeviceKernels::any_specialization_happening_now()
int MetalDeviceKernels::num_incomplete_specialization_requests()
{
/* Return true if any ShaderCaches have ongoing specialization requests (typically there will be
* only 1). */
int total = 0;
for (int i = 0; i < g_shaderCacheCount; i++) {
if (g_shaderCache[i].second->incomplete_specialization_requests > 0) {
return true;
}
total += g_shaderCache[i].second->incomplete_specialization_requests;
}
return false;
return total;
}
int MetalDeviceKernels::get_loaded_kernel_count(MetalDevice const *device,

View File

@ -706,6 +706,12 @@ void Session::update_status_time(bool show_pause, bool show_done)
string_printf("Sample %d/%d", current_sample, num_samples));
}
/* Append any device-specific status (such as background kernel optimization) */
string device_status;
if (device->is_ready(device_status) && !device_status.empty()) {
substatus += string_printf(" (%s)", device_status.c_str());
}
/* TODO(sergey): Denoising status from the path trace. */
if (show_pause) {

View File

@ -33,7 +33,8 @@ aggressive = 2
# Exclude:
# - `./extern/` because it's maintained separately.
# - `./scripts/addons*` & `./tools/` because they are external repositories
# - `./tools/svn_rev_map/` contains data-files which are slow to re-format and don't benefit from formatting.
# - `./scripts/addons*` because it is an external repository.
# which can contain their own configuration and be handled separately.
# - `./scripts/modules/rna_manual_reference.py` because it's a generated data-file.
exclude = """
@ -41,7 +42,8 @@ exclude = """
./scripts/addons/*,
./scripts/addons_contrib/*,
./scripts/modules/rna_manual_reference.py,
./tools/*,
./tools/svn_rev_map/sha1_to_rev.py,
./tools/svn_rev_map/rev_to_sha1.py,
"""
# Omit settings such as `jobs`, `in_place` & `recursive` as they can cause editor utilities that auto-format on save

View File

@ -20,7 +20,7 @@ from freestyle.types import IntegrationType, Operators, Stroke
Operators.select(QuantitativeInvisibilityUP1D(0))
Operators.bidirectional_chain(ChainSilhouetteIterator())
#Operators.sequential_split(pyVertexNatureUP0D(Nature.VIEW_VERTEX), 2)
# Operators.sequential_split(pyVertexNatureUP0D(Nature.VIEW_VERTEX), 2)
Operators.sort(pyZBP1D())
shaders_list = [
ConstantThicknessShader(3),

View File

@ -76,7 +76,7 @@ class DataPathBuilder:
break
if type_ok:
try:
#print("base." + item_new)
# print("base." + item_new)
base_new = eval("base." + item_new)
break # found, don't keep looking
except:

View File

@ -92,7 +92,7 @@ def module_list(path):
folder_list = []
else:
folder_list = []
#folder_list = glob.glob(os.path.join(path,'*'))
# folder_list = glob.glob(os.path.join(path,'*'))
folder_list = [
p for p in folder_list
if (os.path.exists(os.path.join(path, p, '__init__.py')) or

View File

@ -559,7 +559,7 @@ def dump_py_messages_from_files(msgs, reports, files, settings):
# foobar(text="Foo", text_ctxt=i18n_ctxt.id_object)
if type(node) == ast.Attribute:
if node.attr in i18n_ctxt_ids:
#print(node, node.attr, getattr(i18n_contexts, node.attr))
# print(node, node.attr, getattr(i18n_contexts, node.attr))
return getattr(i18n_contexts, node.attr)
return i18n_contexts.default

View File

@ -7,7 +7,7 @@ import os
import re
import struct
import tempfile
#import time
# import time
from bl_i18n_utils import (
settings,
@ -173,7 +173,7 @@ def list_po_dir(root_path, settings):
isocodes = dict(e for e in isocodes if os.path.isfile(e[1]))
for num_id, name, uid in settings.LANGUAGES[2:]: # Skip "default" and "en" languages!
best_po = find_best_isocode_matches(uid, isocodes)
#print(uid, "->", best_po)
# print(uid, "->", best_po)
if best_po:
isocode = best_po[0]
yield (True, uid, num_id, name, isocode, isocodes[isocode])
@ -438,7 +438,7 @@ class I18nMessages:
# Avoid parsing again!
# Keys should be (pseudo) file-names, values are tuples (hash, I18nMessages)
# Note: only used by po parser currently!
#_parser_cache = {}
# _parser_cache = {}
def __init__(self, uid=None, kind=None, key=None, src=None, settings=settings):
self.settings = settings
@ -791,7 +791,7 @@ class I18nMessages:
k &= src_to_msg[src_enum]
msgmap["enum_label"]["key"] = k
rlbl = getattr(msgs, msgmap["rna_label"]["msgstr"])
#print("rna label: " + rlbl, rlbl in msgid_to_msg, rlbl in msgstr_to_msg)
# print("rna label: " + rlbl, rlbl in msgid_to_msg, rlbl in msgstr_to_msg)
if rlbl:
k = ctxt_to_msg[rna_ctxt].copy()
if k and rlbl in msgid_to_msg:
@ -831,7 +831,7 @@ class I18nMessages:
# Tips (they never have a specific context).
etip = getattr(msgs, msgmap["enum_tip"]["msgstr"])
#print("enum tip: " + etip)
# print("enum tip: " + etip)
if etip:
k = ctxt_to_msg[self.settings.DEFAULT_CONTEXT].copy()
if etip in msgid_to_msg:
@ -845,7 +845,7 @@ class I18nMessages:
k &= src_to_msg[src_enum]
msgmap["enum_tip"]["key"] = k
rtip = getattr(msgs, msgmap["rna_tip"]["msgstr"])
#print("rna tip: " + rtip)
# print("rna tip: " + rtip)
if rtip:
k = ctxt_to_msg[self.settings.DEFAULT_CONTEXT].copy()
if k and rtip in msgid_to_msg:
@ -860,7 +860,7 @@ class I18nMessages:
msgmap["rna_tip"]["key"] = k
# print(k)
btip = getattr(msgs, msgmap["but_tip"]["msgstr"])
#print("button tip: " + btip)
# print("button tip: " + btip)
if btip and btip not in {rtip, etip}:
k = ctxt_to_msg[self.settings.DEFAULT_CONTEXT].copy()
if btip in msgid_to_msg:
@ -1038,7 +1038,7 @@ class I18nMessages:
msgstr_lines.append(line)
else:
self.parsing_errors.append((line_nr, "regular string outside msgctxt, msgid or msgstr scope"))
#self.parsing_errors += (str(comment_lines), str(msgctxt_lines), str(msgid_lines), str(msgstr_lines))
# self.parsing_errors += (str(comment_lines), str(msgctxt_lines), str(msgid_lines), str(msgstr_lines))
# If no final empty line, last message is not finalized!
if reading_msgstr:

View File

@ -69,7 +69,7 @@ def language_menu(args, settings):
continue
for po_path in os.listdir(po_dir):
uid = po_to_uid.get(po_path, None)
#print("Checking %s, found uid %s" % (po_path, uid))
# print("Checking %s, found uid %s" % (po_path, uid))
po_path = os.path.join(settings.TRUNK_PO_DIR, po_path)
if uid is not None:
po = utils_i18n.I18nMessages(uid=uid, kind='PO', src=po_path, settings=settings)

View File

@ -60,4 +60,22 @@ def keyconfig_update(keyconfig_data, keyconfig_version):
}.get(item_event.get("type")):
item_event["type"] = ty_new
if keyconfig_version <= (3, 6, 0):
# The modal keys "Vert/Edge Slide" and "TrackBall" didn't exist until then.
# The operator reused the "Move" and "Rotate" respectively.
if not has_copy:
keyconfig_data = copy.deepcopy(keyconfig_data)
has_copy = True
for km_name, _km_parms, km_items_data in keyconfig_data:
if km_name == "Transform Modal Map":
km_items = km_items_data["items"]
for (item_modal, item_event, _item_prop) in km_items:
if item_modal == 'TRANSLATE':
km_items.append(('VERT_EDGE_SLIDE', item_event, None))
elif item_modal == 'ROTATE':
km_items.append(('TRACKBALL', item_event, None))
break
return keyconfig_data

View File

@ -392,7 +392,7 @@ def ngon_tessellate(from_data, indices, fix_loops=True, debug_print=True):
fill = tessellate_polygon([[v[0] for v in loop] for loop in loop_list])
# draw_loops(loop_list)
#raise Exception("done loop")
# raise Exception("done loop")
# map to original indices
fill = [[vert_map[i] for i in f] for f in fill]

View File

@ -329,8 +329,11 @@ def banner(context):
"",
)
# NOTE: Using `OUTPUT` style (intended for the `stdout` is also valid).
# Using `INFO` has a slight advantage that it's excluded by the "Copy as Script" operator.
# As the banner isn't useful to include in a script - leave it out.
for line in message:
add_scrollback(line, 'OUTPUT')
add_scrollback(line, 'INFO')
sc.prompt = PROMPT

View File

@ -25,8 +25,8 @@ def compat_str(text, line_length=0):
text_ls.append(text)
text = '\n '.join(text_ls)
#text = text.replace('.', '.\n')
#text = text.replace(']', ']\n')
# text = text.replace('.', '.\n')
# text = text.replace(']', ']\n')
text = text.replace("\n", "\\n")
text = text.replace('"', '\\"')
return text
@ -135,7 +135,7 @@ def graph_armature(obj, filepath, FAKE_PARENT=True, CONSTRAINTS=True, DRIVERS=Tr
if not rna_path.startswith("pose.bones["):
return None
#rna_path_bone = rna_path[:rna_path.index("]") + 1]
# rna_path_bone = rna_path[:rna_path.index("]") + 1]
# return obj.path_resolve(rna_path_bone)
bone_name = rna_path.split("[")[1].split("]")[0]
return obj.pose.bones[bone_name[1:-1]]

View File

@ -629,7 +629,7 @@ def BuildRNAInfo():
except:
return "" # invalid id
#structs = [(base_id(rna_struct), rna_struct.identifier, rna_struct) for rna_struct in bpy.doc.structs.values()]
# structs = [(base_id(rna_struct), rna_struct.identifier, rna_struct) for rna_struct in bpy.doc.structs.values()]
'''
structs = []
for rna_struct in bpy.doc.structs.values():
@ -703,7 +703,7 @@ def BuildRNAInfo():
# Store a list of functions, remove inherited later
# NOT USED YET
## rna_functions_dict[identifier] = get_direct_functions(rna_struct)
# rna_functions_dict[identifier] = get_direct_functions(rna_struct)
# fill in these later
rna_children_dict[identifier] = []
@ -786,7 +786,7 @@ def BuildRNAInfo():
# if rna_struct.nested:
# continue
#write_struct(rna_struct, '')
# write_struct(rna_struct, '')
info_struct = GetInfoStructRNA(rna_struct)
if rna_base:
info_struct.base = GetInfoStructRNA(rna_struct_dict[rna_base])

View File

@ -5789,7 +5789,9 @@ def km_transform_modal_map(_params):
("PLANE_Z", {"type": 'Z', "value": 'PRESS', "shift": True}, None),
("CONS_OFF", {"type": 'C', "value": 'PRESS'}, None),
("TRANSLATE", {"type": 'G', "value": 'PRESS'}, None),
("VERT_EDGE_SLIDE", {"type": 'G', "value": 'PRESS'}, None),
("ROTATE", {"type": 'R', "value": 'PRESS'}, None),
("TRACKBALL", {"type": 'R', "value": 'PRESS'}, None),
("RESIZE", {"type": 'S', "value": 'PRESS'}, None),
("SNAP_TOGGLE", {"type": 'TAB', "value": 'PRESS', "shift": True}, None),
("SNAP_INV_ON", {"type": 'LEFT_CTRL', "value": 'PRESS', "any": True}, None),

View File

@ -3971,7 +3971,9 @@ def km_transform_modal_map(_params):
("PLANE_Z", {"type": 'Z', "value": 'PRESS', "shift": True}, None),
("CONS_OFF", {"type": 'C', "value": 'PRESS'}, None),
("TRANSLATE", {"type": 'G', "value": 'PRESS'}, None),
("VERT_EDGE_SLIDE", {"type": 'G', "value": 'PRESS'}, None),
("ROTATE", {"type": 'R', "value": 'PRESS'}, None),
("TRACKBALL", {"type": 'R', "value": 'PRESS'}, None),
("RESIZE", {"type": 'S', "value": 'PRESS'}, None),
("SNAP_TOGGLE", {"type": 'TAB', "value": 'PRESS', "shift": True}, None),
("SNAP_INV_ON", {"type": 'LEFT_CTRL', "value": 'PRESS', "any": True}, None),

View File

@ -164,7 +164,7 @@ class RandomizeLocRotSize(Operator):
scale = None if not self.use_scale else self.scale
scale_even = self.scale_even
#scale_min = self.scale_min
# scale_min = self.scale_min
scale_min = 0
randomize_selected(context, seed, delta,

View File

@ -165,9 +165,9 @@ class prettyface:
def set_uv(f, p1, p2, p3):
# cos =
#v1 = cos[0]-cos[1]
#v2 = cos[1]-cos[2]
#v3 = cos[2]-cos[0]
# v1 = cos[0]-cos[1]
# v2 = cos[1]-cos[2]
# v3 = cos[2]-cos[0]
# angles_co = get_tri_angles(*[v.co for v in f])
angles_co = get_tri_angles(*[f.id_data.vertices[v].co for v in f.vertices]) # XXX25

View File

@ -132,7 +132,6 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
rows=rows,
)
col = row.column(align=True)
col.operator("pose.group_add", icon='ADD', text="")
col.operator("pose.group_remove", icon='REMOVE', text="")
@ -218,7 +217,7 @@ class DATA_PT_iksolver_itasc(ArmatureButtonsPanel, Panel):
class DATA_PT_motion_paths(MotionPathButtonsPanel, Panel):
#bl_label = "Bones Motion Paths"
# bl_label = "Bones Motion Paths"
bl_options = {'DEFAULT_CLOSED'}
bl_context = "data"
@ -240,7 +239,7 @@ class DATA_PT_motion_paths(MotionPathButtonsPanel, Panel):
class DATA_PT_motion_paths_display(MotionPathButtonsPanel_display, Panel):
#bl_label = "Bones Motion Paths"
# bl_label = "Bones Motion Paths"
bl_context = "data"
bl_parent_id = "DATA_PT_motion_paths"
bl_options = {'DEFAULT_CLOSED'}

View File

@ -190,7 +190,7 @@ class MASK_PT_point:
col = layout.column()
# Currently only parenting the movie-clip is allowed,
# so do not over-complicate things for now by using single template_ID
#col.template_any_ID(parent, "id", "id_type", text="")
# col.template_any_ID(parent, "id", "id_type", text="")
col.label(text="Parent:")
col.prop(parent, "id", text="")

View File

@ -325,7 +325,7 @@ class OBJECT_PT_lineart(ObjectButtonsPanel, Panel):
class OBJECT_PT_motion_paths(MotionPathButtonsPanel, Panel):
#bl_label = "Object Motion Paths"
# bl_label = "Object Motion Paths"
bl_context = "object"
bl_options = {'DEFAULT_CLOSED'}
@ -344,7 +344,7 @@ class OBJECT_PT_motion_paths(MotionPathButtonsPanel, Panel):
class OBJECT_PT_motion_paths_display(MotionPathButtonsPanel_display, Panel):
#bl_label = "Object Motion Paths"
# bl_label = "Object Motion Paths"
bl_context = "object"
bl_parent_id = "OBJECT_PT_motion_paths"
bl_options = {'DEFAULT_CLOSED'}

View File

@ -879,7 +879,7 @@ class PHYSICS_PT_mesh(PhysicButtonsPanel, Panel):
col.prop(domain, "mesh_concave_lower", text="Lower")
# TODO (sebbas): for now just interpolate any upres grids, ie not sampling highres grids
#col.prop(domain, "highres_sampling", text="Flow Sampling:")
# col.prop(domain, "highres_sampling", text="Flow Sampling:")
if domain.cache_type == 'MODULAR':
col.separator()

View File

@ -25,7 +25,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 0
#define BLENDER_FILE_SUBVERSION 1
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file

View File

@ -97,7 +97,7 @@ typedef struct ClothVertex {
float tv[3]; /* temporary "velocity", mostly used as tv = tx-txold */
float mass; /* mass / weight of the vertex */
float goal; /* goal, from SB */
float impulse[3]; /* used in collision.c */
float impulse[3]; /* used in collision.cc */
float xrest[3]; /* rest position of the vertex */
float dcvel[3]; /* delta velocities to be applied by collision response */
unsigned int impulse_count; /* same as above */
@ -196,7 +196,7 @@ typedef enum {
} CLOTH_SPRINGS_FLAGS;
/* -------------------------------------------------------------------- */
/* collision.c */
/* collision.cc */
struct CollPair;
@ -232,7 +232,7 @@ void clothModifier_do(struct ClothModifierData *clmd,
int cloth_uses_vgroup(struct ClothModifierData *clmd);
/* Needed for collision.c */
/* Needed for collision.cc */
void bvhtree_update_from_cloth(struct ClothModifierData *clmd, bool moving, bool self);
/* Needed for button_object.c */

View File

@ -18,7 +18,7 @@ struct MVertTri;
struct Object;
////////////////////////////////////////
// used for collisions in collision.c
// used for collisions in collision.cc
////////////////////////////////////////
/* COLLISION FLAGS */
@ -32,9 +32,9 @@ typedef enum {
} COLLISION_FLAGS;
////////////////////////////////////////
// used for collisions in collision.c
// used for collisions in collision.cc
////////////////////////////////////////
/* used for collisions in collision.c */
/* used for collisions in collision.cc */
typedef struct CollPair {
unsigned int face1; /* cloth face */
unsigned int face2; /* object face */
@ -58,7 +58,7 @@ typedef struct CollPair {
int pointsb[4];
} CollPair;
/* used for collisions in collision.c */
/* used for collisions in collision.cc */
typedef struct EdgeCollPair {
unsigned int p11, p12, p21, p22;
float normal[3];
@ -68,7 +68,7 @@ typedef struct EdgeCollPair {
float pa[3], pb[3]; /* collision point p1 on face1, p2 on face2 */
} EdgeCollPair;
/* used for collisions in collision.c */
/* used for collisions in collision.cc */
typedef struct FaceCollPair {
unsigned int p11, p12, p13, p21;
float normal[3];
@ -85,7 +85,7 @@ typedef struct FaceCollPair {
/////////////////////////////////////////////////
/////////////////////////////////////////////////
// used in modifier.cc from collision.c
// used in modifier.cc from collision.cc
/////////////////////////////////////////////////
struct BVHTree *bvhtree_build_from_mvert(const float (*positions)[3],

View File

@ -138,6 +138,13 @@ typedef struct Main {
*/
bool is_locked_for_linking;
/**
* When set, indicates that an unrecoverable error/data corruption was detected.
* Should only be set by readfile code, and used by upper-level code (typically #setup_app_data)
* to cancel a file reading operation.
*/
bool is_read_invalid;
/**
* True if this main is the 'GMAIN' of current Blender.
*

View File

@ -99,6 +99,9 @@ void BKE_mesh_legacy_attribute_strings_to_flags(struct Mesh *mesh);
void BKE_mesh_legacy_sharp_edges_to_flags(struct Mesh *mesh);
void BKE_mesh_legacy_sharp_edges_from_flags(struct Mesh *mesh);
void BKE_mesh_legacy_uv_seam_to_flags(struct Mesh *mesh);
void BKE_mesh_legacy_uv_seam_from_flags(struct Mesh *mesh);
struct MVert *BKE_mesh_legacy_convert_positions_to_verts(
Mesh *mesh,
blender::ResourceScope &temp_arrays_for_convert,

View File

@ -260,6 +260,7 @@ typedef bool (*MeshRemapIslandsCalc)(const float (*vert_positions)[3],
int totvert,
const struct MEdge *edges,
int totedge,
const bool *uv_seams,
const struct MPoly *polys,
int totpoly,
const struct MLoop *loops,
@ -277,6 +278,7 @@ bool BKE_mesh_calc_islands_loop_poly_edgeseam(const float (*vert_positions)[3],
int totvert,
const struct MEdge *edges,
int totedge,
const bool *uv_seams,
const struct MPoly *polys,
int totpoly,
const struct MLoop *loops,
@ -300,6 +302,7 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3],
int totvert,
struct MEdge *edges,
int totedge,
const bool *uv_seams,
struct MPoly *polys,
int totpoly,
struct MLoop *loops,

View File

@ -6,6 +6,7 @@
#include <mutex>
#include "BLI_cache_mutex.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_multi_value_map.hh"
#include "BLI_resource_scope.hh"
#include "BLI_utility_mixins.hh"
@ -150,6 +151,13 @@ class bNodeTreeRuntime : NonCopyable, NonMovable {
Vector<bNode *> root_frames;
Vector<bNodeSocket *> interface_inputs;
Vector<bNodeSocket *> interface_outputs;
/**
* The location of all sockets in the tree, calculated while drawing the nodes.
* Indexed with #bNodeSocket::index_in_tree(). In the node tree's "world space"
* (the same as #bNode::runtime::totr).
*/
Vector<float2> all_socket_locations;
};
/**

View File

@ -95,7 +95,6 @@ typedef struct CCGDerivedMesh {
struct CCGFace *face;
} * faceMap;
short *edgeFlags;
struct DMFlagMat *faceFlags;
int *reverseFaceMap;

View File

@ -92,7 +92,7 @@ set(SRC
intern/cdderivedmesh.cc
intern/cloth.cc
intern/collection.c
intern/collision.c
intern/collision.cc
intern/colorband.c
intern/colortools.c
intern/compute_contexts.cc

View File

@ -476,6 +476,13 @@ void BKE_blendfile_read_setup_ex(bContext *C,
const bool startup_update_defaults,
const char *startup_app_template)
{
if (bfd->main->is_read_invalid) {
BKE_reports_prepend(reports->reports,
"File could not be read, critical data corruption detected");
BLO_blendfiledata_free(bfd);
return;
}
if (startup_update_defaults) {
if ((params->skip_flags & BLO_READ_SKIP_DATA) == 0) {
BLO_update_defaults_startup_blend(bfd->main, startup_app_template);
@ -503,6 +510,10 @@ struct BlendFileData *BKE_blendfile_read(const char *filepath,
}
BlendFileData *bfd = BLO_read_from_file(filepath, eBLOReadSkip(params->skip_flags), reports);
if (bfd && bfd->main->is_read_invalid) {
BLO_blendfiledata_free(bfd);
bfd = nullptr;
}
if (bfd) {
handle_subversion_warning(bfd->main, reports);
}
@ -519,6 +530,10 @@ struct BlendFileData *BKE_blendfile_read_from_memory(const void *filebuf,
{
BlendFileData *bfd = BLO_read_from_memory(
filebuf, filelength, eBLOReadSkip(params->skip_flags), reports);
if (bfd && bfd->main->is_read_invalid) {
BLO_blendfiledata_free(bfd);
bfd = nullptr;
}
if (bfd) {
/* Pass. */
}
@ -535,6 +550,10 @@ struct BlendFileData *BKE_blendfile_read_from_memfile(Main *bmain,
{
BlendFileData *bfd = BLO_read_from_memfile(
bmain, BKE_main_blendfile_path(bmain), memfile, params, reports);
if (bfd && bfd->main->is_read_invalid) {
BLO_blendfiledata_free(bfd);
bfd = nullptr;
}
if (bfd) {
/* Removing the unused workspaces, screens and wm is useless here, setup_app_data will switch
* those lists with the ones from old bmain, which freeing is much more efficient than

View File

@ -580,7 +580,7 @@ static void bvhtree_from_mesh_setup_data(BVHTree *tree,
const MEdge *edge,
const MFace *face,
const MLoop *loop,
const MLoopTri *looptri,
const Span<MLoopTri> looptris,
BVHTreeFromMesh *r_data)
{
memset(r_data, 0, sizeof(*r_data));
@ -591,7 +591,7 @@ static void bvhtree_from_mesh_setup_data(BVHTree *tree,
r_data->edge = edge;
r_data->face = face;
r_data->loop = loop;
r_data->looptri = looptri;
r_data->looptri = looptris.data();
switch (bvh_cache_type) {
case BVHTREE_FROM_VERTS:
@ -779,7 +779,7 @@ BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data,
if (data) {
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_setup_data(
tree, BVHTREE_FROM_VERTS, vert_positions, nullptr, nullptr, nullptr, nullptr, data);
tree, BVHTREE_FROM_VERTS, vert_positions, nullptr, nullptr, nullptr, {}, data);
}
return tree;
@ -914,7 +914,7 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
if (data) {
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_setup_data(
tree, BVHTREE_FROM_EDGES, vert_positions, edge, nullptr, nullptr, nullptr, data);
tree, BVHTREE_FROM_EDGES, vert_positions, edge, nullptr, nullptr, {}, data);
}
return tree;
@ -1037,16 +1037,15 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(float epsilon,
int axis,
const float (*positions)[3],
const MLoop *mloop,
const MLoopTri *looptri,
const int looptri_num,
const Span<MLoopTri> looptris,
const BitSpan looptri_mask,
int looptri_num_active)
{
if (!looptri_mask.is_empty()) {
BLI_assert(IN_RANGE_INCL(looptri_num_active, 0, looptri_num));
BLI_assert(IN_RANGE_INCL(looptri_num_active, 0, looptris.size()));
}
else {
looptri_num_active = looptri_num;
looptri_num_active = looptris.size();
}
if (looptri_num_active == 0) {
return nullptr;
@ -1059,16 +1058,16 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(float epsilon,
return nullptr;
}
if (positions && looptri) {
for (int i = 0; i < looptri_num; i++) {
if (positions && !looptris.is_empty()) {
for (const int i : looptris.index_range()) {
float co[3][3];
if (!looptri_mask.is_empty() && !looptri_mask[i]) {
continue;
}
copy_v3_v3(co[0], positions[mloop[looptri[i].tri[0]].v]);
copy_v3_v3(co[1], positions[mloop[looptri[i].tri[1]].v]);
copy_v3_v3(co[2], positions[mloop[looptri[i].tri[2]].v]);
copy_v3_v3(co[0], positions[mloop[looptris[i].tri[0]].v]);
copy_v3_v3(co[1], positions[mloop[looptris[i].tri[1]].v]);
copy_v3_v3(co[2], positions[mloop[looptris[i].tri[2]].v]);
BLI_bvhtree_insert(tree, i, co[0], 3);
}
@ -1121,8 +1120,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
axis,
vert_positions,
mloop,
looptri,
looptri_num,
{looptri, looptri_num},
looptri_mask,
looptri_num_active);
@ -1130,8 +1128,14 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
if (data) {
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_setup_data(
tree, BVHTREE_FROM_LOOPTRI, vert_positions, nullptr, nullptr, mloop, looptri, data);
bvhtree_from_mesh_setup_data(tree,
BVHTREE_FROM_LOOPTRI,
vert_positions,
nullptr,
nullptr,
mloop,
{looptri, looptri_num},
data);
}
return tree;
@ -1208,11 +1212,9 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
{
BVHCache **bvh_cache_p = (BVHCache **)&mesh->runtime->bvh_cache;
const MLoopTri *looptri = nullptr;
int looptri_len = 0;
Span<MLoopTri> looptris;
if (ELEM(bvh_cache_type, BVHTREE_FROM_LOOPTRI, BVHTREE_FROM_LOOPTRI_NO_HIDDEN)) {
looptri = BKE_mesh_runtime_looptri_ensure(mesh);
looptri_len = BKE_mesh_runtime_looptri_len(mesh);
looptris = mesh->looptris();
}
const float(*positions)[3] = reinterpret_cast<const float(*)[3]>(mesh->vert_positions().data());
const Span<MEdge> edges = mesh->edges();
@ -1225,7 +1227,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
edges.data(),
(const MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE),
loops.data(),
looptri,
looptris,
data);
bool lock_started = false;
@ -1278,20 +1280,13 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
mask = looptri_no_hidden_map_get(
mesh->polys(),
attributes.lookup_or_default(".hide_poly", ATTR_DOMAIN_FACE, false),
looptri_len,
looptris.size(),
&mask_bits_act_len);
ATTR_FALLTHROUGH;
}
case BVHTREE_FROM_LOOPTRI:
data->tree = bvhtree_from_mesh_looptri_create_tree(0.0f,
tree_type,
6,
positions,
loops.data(),
looptri,
looptri_len,
mask,
mask_bits_act_len);
data->tree = bvhtree_from_mesh_looptri_create_tree(
0.0f, tree_type, 6, positions, loops.data(), looptris, mask, mask_bits_act_len);
break;
case BVHTREE_FROM_EM_VERTS:
case BVHTREE_FROM_EM_EDGES:

View File

@ -836,9 +836,8 @@ static bool cloth_from_object(
static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, Mesh *mesh)
{
const blender::Span<MLoop> loops = mesh->loops();
const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(mesh);
const blender::Span<MLoopTri> looptris = mesh->looptris();
const uint mvert_num = mesh->totvert;
const uint looptri_num = BKE_mesh_runtime_looptri_len(mesh);
/* Allocate our vertices. */
clmd->clothObject->mvert_num = mvert_num;
@ -853,14 +852,14 @@ static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, Mesh *mes
/* save face information */
if (clmd->hairdata == nullptr) {
clmd->clothObject->primitive_num = looptri_num;
clmd->clothObject->primitive_num = looptris.size();
}
else {
clmd->clothObject->primitive_num = mesh->totedge;
}
clmd->clothObject->tri = static_cast<MVertTri *>(
MEM_malloc_arrayN(looptri_num, sizeof(MVertTri), __func__));
MEM_malloc_arrayN(looptris.size(), sizeof(MVertTri), __func__));
if (clmd->clothObject->tri == nullptr) {
cloth_free_modifier(clmd);
BKE_modifier_set_error(
@ -869,7 +868,7 @@ static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, Mesh *mes
return;
}
BKE_mesh_runtime_verttri_from_looptri(
clmd->clothObject->tri, loops.data(), looptri, looptri_num);
clmd->clothObject->tri, loops.data(), looptris.data(), looptris.size());
clmd->clothObject->edges = mesh->edges().data();

View File

@ -50,6 +50,11 @@
static CLG_LogRef LOG = {"bke.collection"};
/**
* Extra asserts that #Collection.gobject_hash is valid which are too slow even for debug mode.
*/
// #define USE_DEBUG_EXTRA_GOBJECT_ASSERT
/* -------------------------------------------------------------------- */
/** \name Prototypes
* \{ */
@ -61,6 +66,11 @@ static bool collection_child_add(Collection *parent,
static bool collection_child_remove(Collection *parent, Collection *collection);
static bool collection_object_add(
Main *bmain, Collection *collection, Object *ob, int flag, const bool add_us);
static void collection_object_remove_no_gobject_hash(Main *bmain,
Collection *collection,
CollectionObject *cob,
const bool free_us);
static bool collection_object_remove(Main *bmain,
Collection *collection,
Object *ob,
@ -72,6 +82,18 @@ static CollectionParent *collection_find_parent(Collection *child, Collection *c
static bool collection_find_child_recursive(const Collection *parent,
const Collection *collection);
static void collection_gobject_hash_ensure(Collection *collection);
static void collection_gobject_hash_remove_object(Collection *collection, const Object *ob);
static void collection_gobject_hash_update_object(Collection *collection,
Object *ob_old,
CollectionObject *cob);
/** Does nothing unless #USE_DEBUG_EXTRA_GOBJECT_ASSERT is defined. */
static void collection_gobject_hash_assert_internal_consistency(Collection *collection);
#define BLI_ASSERT_COLLECION_GOBJECT_HASH_IS_VALID(collection) \
collection_gobject_hash_assert_internal_consistency(collection)
/** \} */
/* -------------------------------------------------------------------- */
@ -119,6 +141,7 @@ static void collection_copy_data(Main *bmain, ID *id_dst, const ID *id_src, cons
BLI_listbase_clear(&collection_dst->gobject);
BLI_listbase_clear(&collection_dst->children);
BLI_listbase_clear(&collection_dst->runtime.parents);
collection_dst->runtime.gobject_hash = NULL;
LISTBASE_FOREACH (CollectionChild *, child, &collection_src->children) {
collection_child_add(collection_dst, child->collection, flag, false);
@ -136,6 +159,11 @@ static void collection_free_data(ID *id)
BKE_previewimg_free(&collection->preview);
BLI_freelistN(&collection->gobject);
if (collection->runtime.gobject_hash) {
BLI_ghash_free(collection->runtime.gobject_hash, NULL, NULL);
collection->runtime.gobject_hash = NULL;
}
BLI_freelistN(&collection->children);
BLI_freelistN(&collection->runtime.parents);
@ -150,7 +178,13 @@ static void collection_foreach_id(ID *id, LibraryForeachIDData *data)
data, collection->runtime.owner_id, IDWALK_CB_LOOPBACK | IDWALK_CB_NEVER_SELF);
LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
Object *cob_ob_old = cob->ob;
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, cob->ob, IDWALK_CB_USER);
if (collection->runtime.gobject_hash) {
collection_gobject_hash_update_object(collection, cob_ob_old, cob);
}
}
LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
BKE_LIB_FOREACHID_PROCESS_IDSUPER(
@ -288,6 +322,7 @@ static void collection_blend_read_data(BlendDataReader *reader, ID *id)
static void lib_link_collection_data(BlendLibReader *reader, Library *lib, Collection *collection)
{
BLI_assert(collection->runtime.gobject_hash == NULL);
LISTBASE_FOREACH_MUTABLE (CollectionObject *, cob, &collection->gobject) {
BLO_read_id_address(reader, lib, &cob->ob);
@ -354,6 +389,7 @@ void BKE_collection_compat_blend_read_expand(struct BlendExpander *expander,
void BKE_collection_blend_read_expand(BlendExpander *expander, Collection *collection)
{
BLI_assert(collection->runtime.gobject_hash == NULL);
LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
BLO_expand(expander, cob->ob);
}
@ -518,11 +554,20 @@ bool BKE_collection_delete(Main *bmain, Collection *collection, bool hierarchy)
return false;
}
/* This is being deleted, no need to handle each item.
* NOTE: While it might seem an advantage to use the hash instead of the list-lookup
* it is in fact slower because the items are removed in-order,
* so the list-lookup succeeds on the first test. */
if (collection->runtime.gobject_hash) {
BLI_ghash_free(collection->runtime.gobject_hash, NULL, NULL);
collection->runtime.gobject_hash = NULL;
}
if (hierarchy) {
/* Remove child objects. */
CollectionObject *cob = collection->gobject.first;
while (cob != NULL) {
collection_object_remove(bmain, collection, cob->ob, true);
collection_object_remove_no_gobject_hash(bmain, collection, cob, true);
cob = collection->gobject.first;
}
@ -551,7 +596,7 @@ bool BKE_collection_delete(Main *bmain, Collection *collection, bool hierarchy)
}
/* Remove child object. */
collection_object_remove(bmain, collection, cob->ob, true);
collection_object_remove_no_gobject_hash(bmain, collection, cob, true);
cob = collection->gobject.first;
}
}
@ -938,8 +983,9 @@ bool BKE_collection_has_object(Collection *collection, const Object *ob)
if (ELEM(NULL, collection, ob)) {
return false;
}
return BLI_findptr(&collection->gobject, ob, offsetof(CollectionObject, ob));
BLI_ASSERT_COLLECION_GOBJECT_HASH_IS_VALID(collection);
collection_gobject_hash_ensure(collection);
return BLI_ghash_lookup(collection->runtime.gobject_hash, ob);
}
bool BKE_collection_has_object_recursive(Collection *collection, Object *ob)
@ -1070,13 +1116,15 @@ static bool collection_object_add(
}
}
CollectionObject *cob = BLI_findptr(&collection->gobject, ob, offsetof(CollectionObject, ob));
if (cob) {
collection_gobject_hash_ensure(collection);
CollectionObject **cob_p;
if (BLI_ghash_ensure_p(collection->runtime.gobject_hash, ob, (void ***)&cob_p)) {
return false;
}
cob = MEM_callocN(sizeof(CollectionObject), __func__);
CollectionObject *cob = MEM_callocN(sizeof(CollectionObject), __func__);
cob->ob = ob;
*cob_p = cob;
BLI_addtail(&collection->gobject, cob);
BKE_collection_object_cache_free(collection);
@ -1095,16 +1143,16 @@ static bool collection_object_add(
return true;
}
static bool collection_object_remove(Main *bmain,
Collection *collection,
Object *ob,
const bool free_us)
/**
* A version of #collection_object_remove that does not handle `collection->runtime.gobject_hash`,
* Either the caller must have removed the object from the hash or the hash may be NULL.
*/
static void collection_object_remove_no_gobject_hash(Main *bmain,
Collection *collection,
CollectionObject *cob,
const bool free_us)
{
CollectionObject *cob = BLI_findptr(&collection->gobject, ob, offsetof(CollectionObject, ob));
if (cob == NULL) {
return false;
}
Object *ob = cob->ob;
BLI_freelinkN(&collection->gobject, cob);
BKE_collection_object_cache_free(collection);
@ -1117,7 +1165,19 @@ static bool collection_object_remove(Main *bmain,
collection_tag_update_parent_recursive(
bmain, collection, ID_RECALC_COPY_ON_WRITE | ID_RECALC_GEOMETRY);
}
static bool collection_object_remove(Main *bmain,
Collection *collection,
Object *ob,
const bool free_us)
{
collection_gobject_hash_ensure(collection);
CollectionObject *cob = BLI_ghash_popkey(collection->runtime.gobject_hash, ob, NULL);
if (cob == NULL) {
return false;
}
collection_object_remove_no_gobject_hash(bmain, collection, cob, free_us);
return true;
}
@ -1219,8 +1279,9 @@ bool BKE_collection_object_replace(Main *bmain,
Object *ob_old,
Object *ob_new)
{
CollectionObject *cob = BLI_findptr(
&collection->gobject, ob_old, offsetof(CollectionObject, ob));
collection_gobject_hash_ensure(collection);
CollectionObject *cob;
cob = BLI_ghash_popkey(collection->runtime.gobject_hash, ob_old, NULL);
if (cob == NULL) {
return false;
}
@ -1229,6 +1290,8 @@ bool BKE_collection_object_replace(Main *bmain,
cob->ob = ob_new;
id_us_plus(&cob->ob->id);
BLI_ghash_insert(collection->runtime.gobject_hash, cob->ob, cob);
if (BKE_collection_is_in_scene(collection)) {
BKE_main_collection_sync(bmain);
}
@ -1313,9 +1376,14 @@ void BKE_collections_object_remove_nulls(Main *bmain)
static void collection_object_remove_duplicates(Collection *collection)
{
bool changed = false;
BLI_ASSERT_COLLECION_GOBJECT_HASH_IS_VALID(collection);
const bool use_hash_exists = (collection->runtime.gobject_hash != NULL);
LISTBASE_FOREACH_MUTABLE (CollectionObject *, cob, &collection->gobject) {
if (cob->ob->runtime.collection_management) {
if (use_hash_exists) {
collection_gobject_hash_remove_object(collection, cob->ob);
}
BLI_freelinkN(&collection->gobject, cob);
changed = true;
continue;
@ -1578,6 +1646,79 @@ static CollectionParent *collection_find_parent(Collection *child, Collection *c
return BLI_findptr(&child->runtime.parents, collection, offsetof(CollectionParent, collection));
}
static void collection_gobject_hash_ensure(Collection *collection)
{
if (collection->runtime.gobject_hash) {
BLI_ASSERT_COLLECION_GOBJECT_HASH_IS_VALID(collection);
return;
}
GHash *gobject_hash = BLI_ghash_ptr_new_ex(__func__, BLI_listbase_count(&collection->gobject));
LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
BLI_ghash_insert(gobject_hash, cob->ob, cob);
}
collection->runtime.gobject_hash = gobject_hash;
BLI_ASSERT_COLLECION_GOBJECT_HASH_IS_VALID(collection);
}
static void collection_gobject_hash_remove_object(Collection *collection, const Object *ob)
{
const bool found = BLI_ghash_remove(collection->runtime.gobject_hash, ob, NULL, NULL);
BLI_assert(found);
UNUSED_VARS_NDEBUG(found);
}
/**
* Update the collections object hash, removing `ob_old`, inserting `cob->ob` as the new key.
*
* \param ob_old: The existing key to `cob` in the hash, not removed when NULL.
* \param cob: The `cob->ob` is to be used as the new key,
* when NULL it's not added back into the hash.
*/
static void collection_gobject_hash_update_object(Collection *collection,
Object *ob_old,
CollectionObject *cob)
{
if (ob_old == cob->ob) {
return;
}
BLI_ASSERT_COLLECION_GOBJECT_HASH_IS_VALID(collection);
if (ob_old) {
collection_gobject_hash_remove_object(collection, ob_old);
}
/* The object may be set to NULL if the ID is being cleared from #collection_foreach_id,
* generally `cob->ob` is not expected to be NULL. */
if (cob->ob) {
BLI_ghash_insert(collection->runtime.gobject_hash, cob->ob, cob);
}
}
/**
* Should only be called by: #BLI_ASSERT_COLLECION_GOBJECT_HASH_IS_VALID macro,
* this is an expensive operation intended only to be used for debugging.
*/
static void collection_gobject_hash_assert_internal_consistency(Collection *collection)
{
#ifdef USE_DEBUG_EXTRA_GOBJECT_ASSERT
if (collection->runtime.gobject_hash == NULL) {
return;
}
GHash *gobject_hash = collection->runtime.gobject_hash;
int gobject_count = 0;
LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
CollectionObject *cob_test = BLI_ghash_lookup(gobject_hash, cob->ob);
BLI_assert(cob == cob_test);
gobject_count += 1;
}
const int gobject_hash_count = BLI_ghash_len(gobject_hash);
BLI_assert(gobject_count == gobject_hash_count);
#else
UNUSED_VARS(collection);
#endif /* USE_DEBUG_EXTRA_GOBJECT_ASSERT */
}
static bool collection_child_add(Collection *parent,
Collection *collection,
const int flag,

View File

@ -41,7 +41,7 @@
# include "eltopo-capi.h"
#endif
typedef struct ColDetectData {
struct ColDetectData {
ClothModifierData *clmd;
CollisionModifierData *collmd;
BVHTreeOverlap *overlap;
@ -49,14 +49,14 @@ typedef struct ColDetectData {
bool culling;
bool use_normal;
bool collided;
} ColDetectData;
};
typedef struct SelfColDetectData {
struct SelfColDetectData {
ClothModifierData *clmd;
BVHTreeOverlap *overlap;
CollPair *collisions;
bool collided;
} SelfColDetectData;
};
/***********************************
* Collision modifier code start
@ -93,7 +93,7 @@ void collision_move_object(CollisionModifierData *collmd,
}
BVHTree *bvhtree_build_from_mvert(const float (*positions)[3],
const struct MVertTri *tri,
const MVertTri *tri,
int tri_num,
float epsilon)
{
@ -126,11 +126,11 @@ void bvhtree_update_from_mvert(BVHTree *bvhtree,
bool moving)
{
if ((bvhtree == NULL) || (positions == NULL)) {
if ((bvhtree == nullptr) || (positions == nullptr)) {
return;
}
if (positions_moving == NULL) {
if (positions_moving == nullptr) {
moving = false;
}
@ -155,7 +155,7 @@ void bvhtree_update_from_mvert(BVHTree *bvhtree,
ret = BLI_bvhtree_update_node(bvhtree, i, &co[0][0], &co_moving[0][0], 3);
}
else {
ret = BLI_bvhtree_update_node(bvhtree, i, &co[0][0], NULL, 3);
ret = BLI_bvhtree_update_node(bvhtree, i, &co[0][0], nullptr, 3);
}
/* check if tree is already full */
@ -254,7 +254,7 @@ static float compute_collision_point_tri_tri(const float a1[3],
/* Point projections. */
for (int i = 0; i < 3; i++) {
if (isect_ray_tri_v3(a[i], normal, b[0], b[1], b[2], &tmp, NULL)) {
if (isect_ray_tri_v3(a[i], normal, b[0], b[1], b[2], &tmp, nullptr)) {
if (tmp > maxdist) {
maxdist = tmp;
copy_v3_v3(r_a, a[i]);
@ -267,7 +267,7 @@ static float compute_collision_point_tri_tri(const float a1[3],
negate_v3(normal);
for (int i = 0; i < 3; i++) {
if (isect_ray_tri_v3(b[i], normal, a[0], a[1], a[2], &tmp, NULL)) {
if (isect_ray_tri_v3(b[i], normal, a[0], a[1], a[2], &tmp, nullptr)) {
if (tmp > maxdist) {
maxdist = tmp;
madd_v3_v3v3fl(r_a, b[i], normal, tmp);
@ -418,7 +418,7 @@ static float compute_collision_point_edge_tri(const float a1[3],
normal_tri_v3(normal, b[0], b[1], b[2]);
/* Find intersection. */
if (isect_line_segment_tri_v3(a[0], a[1], b[0], b[1], b[2], &tmp, NULL)) {
if (isect_line_segment_tri_v3(a[0], a[1], b[0], b[1], b[2], &tmp, nullptr)) {
interp_v3_v3v3(isect_a, a[0], a[1], tmp);
isect = true;
}
@ -457,7 +457,7 @@ static float compute_collision_point_edge_tri(const float a1[3],
/* Point projections. */
for (int i = 0; i < 2; i++) {
if (isect_ray_tri_v3(a[i], normal, b[0], b[1], b[2], &tmp, NULL)) {
if (isect_ray_tri_v3(a[i], normal, b[0], b[1], b[2], &tmp, nullptr)) {
if (tmp > maxdist) {
maxdist = tmp;
copy_v3_v3(r_a, a[i]);
@ -592,13 +592,13 @@ static void collision_compute_barycentric(const float pv[3],
return;
}
w1[0] = (float)((e * c - b * f) / d);
w1[0] = float((e * c - b * f) / d);
if (w1[0] < 0) {
w1[0] = 0;
}
w2[0] = (float)((f - b * (double)w1[0]) / c);
w2[0] = float((f - b * (double)w1[0]) / c);
if (w2[0] < 0) {
w2[0] = 0;
@ -630,7 +630,7 @@ DO_INLINE void collision_interpolateOnTriangle(float to[3],
static void cloth_collision_impulse_vert(const float clamp_sq,
const float impulse[3],
struct ClothVertex *vert)
ClothVertex *vert)
{
float impulse_len_sq = len_squared_v3(impulse);
@ -667,7 +667,7 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
const float epsilon2 = BLI_bvhtree_get_epsilon(collmd->bvhtree);
const float min_distance = (clmd->coll_parms->epsilon + epsilon2) * (8.0f / 9.0f);
const bool is_hair = (clmd->hairdata != NULL);
const bool is_hair = (clmd->hairdata != nullptr);
for (int i = 0; i < collision_count; i++, collpair++) {
float i1[3], i2[3], i3[3];
float v1[3], v2[3], relativeVelocity[3];
@ -952,7 +952,7 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd,
# pragma GCC diagnostic pop
#endif
static bool cloth_bvh_collision_is_active(const ClothModifierData *UNUSED(clmd),
static bool cloth_bvh_collision_is_active(const ClothModifierData * /*clmd*/,
const Cloth *cloth,
const MVertTri *tri_a)
{
@ -971,7 +971,7 @@ static bool cloth_bvh_collision_is_active(const ClothModifierData *UNUSED(clmd),
static void cloth_collision(void *__restrict userdata,
const int index,
const TaskParallelTLS *__restrict UNUSED(tls))
const TaskParallelTLS *__restrict /*tls*/)
{
ColDetectData *data = (ColDetectData *)userdata;
@ -1087,7 +1087,7 @@ static bool cloth_bvh_selfcollision_is_active(const ClothModifierData *clmd,
static void cloth_selfcollision(void *__restrict userdata,
const int index,
const TaskParallelTLS *__restrict UNUSED(tls))
const TaskParallelTLS *__restrict /*tls*/)
{
SelfColDetectData *data = (SelfColDetectData *)userdata;
@ -1168,7 +1168,7 @@ static void cloth_selfcollision(void *__restrict userdata,
static void hair_collision(void *__restrict userdata,
const int index,
const TaskParallelTLS *__restrict UNUSED(tls))
const TaskParallelTLS *__restrict /*tls*/)
{
ColDetectData *data = (ColDetectData *)userdata;
@ -1238,13 +1238,16 @@ static void hair_collision(void *__restrict userdata,
}
}
static void add_collision_object(ListBase *relations, Object *ob, int level, uint modifier_type)
static void add_collision_object(ListBase *relations,
Object *ob,
int level,
const ModifierType modifier_type)
{
/* only get objects with collision modifier */
ModifierData *cmd = BKE_modifiers_findby_type(ob, modifier_type);
if (cmd) {
CollisionRelation *relation = MEM_callocN(sizeof(CollisionRelation), "CollisionRelation");
CollisionRelation *relation = MEM_cnew<CollisionRelation>(__func__);
relation->ob = ob;
BLI_addtail(relations, relation);
}
@ -1273,11 +1276,11 @@ ListBase *BKE_collision_relations_create(Depsgraph *depsgraph,
const bool for_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
const int base_flag = (for_render) ? BASE_ENABLED_RENDER : BASE_ENABLED_VIEWPORT;
ListBase *relations = MEM_callocN(sizeof(ListBase), "CollisionRelation list");
ListBase *relations = MEM_cnew<ListBase>(__func__);
for (; base; base = base->next) {
if (base->flag & base_flag) {
add_collision_object(relations, base->object, 0, modifier_type);
add_collision_object(relations, base->object, 0, ModifierType(modifier_type));
}
}
@ -1302,12 +1305,12 @@ Object **BKE_collision_objects_create(Depsgraph *depsgraph,
if (!relations) {
*numcollobj = 0;
return NULL;
return nullptr;
}
int maxnum = BLI_listbase_count(relations);
int num = 0;
Object **objects = MEM_callocN(sizeof(Object *) * maxnum, __func__);
Object **objects = MEM_cnew_array<Object *>(maxnum, __func__);
LISTBASE_FOREACH (CollisionRelation *, relation, relations) {
/* Get evaluated object. */
@ -1325,7 +1328,7 @@ Object **BKE_collision_objects_create(Depsgraph *depsgraph,
if (num == 0) {
MEM_freeN(objects);
objects = NULL;
objects = nullptr;
}
*numcollobj = num;
@ -1343,10 +1346,10 @@ ListBase *BKE_collider_cache_create(Depsgraph *depsgraph, Object *self, Collecti
{
ListBase *relations = DEG_get_collision_relations(
depsgraph, collection, eModifierType_Collision);
ListBase *cache = NULL;
ListBase *cache = nullptr;
if (!relations) {
return NULL;
return nullptr;
}
LISTBASE_FOREACH (CollisionRelation *, relation, relations) {
@ -1360,11 +1363,11 @@ ListBase *BKE_collider_cache_create(Depsgraph *depsgraph, Object *self, Collecti
CollisionModifierData *cmd = (CollisionModifierData *)BKE_modifiers_findby_type(
ob, eModifierType_Collision);
if (cmd && cmd->bvhtree) {
if (cache == NULL) {
cache = MEM_callocN(sizeof(ListBase), "ColliderCache array");
if (cache == nullptr) {
cache = MEM_cnew<ListBase>(__func__);
}
ColliderCache *col = MEM_callocN(sizeof(ColliderCache), "ColliderCache");
ColliderCache *col = MEM_cnew<ColliderCache>(__func__);
col->ob = ob;
col->collmd = cmd;
/* make sure collider is properly set up */
@ -1381,7 +1384,7 @@ void BKE_collider_cache_free(ListBase **colliders)
if (*colliders) {
BLI_freelistN(*colliders);
MEM_freeN(*colliders);
*colliders = NULL;
*colliders = nullptr;
}
}
@ -1393,18 +1396,17 @@ static bool cloth_bvh_objcollisions_nearcheck(ClothModifierData *clmd,
bool culling,
bool use_normal)
{
const bool is_hair = (clmd->hairdata != NULL);
const bool is_hair = (clmd->hairdata != nullptr);
*collisions = (CollPair *)MEM_mallocN(sizeof(CollPair) * numresult, "collision array");
ColDetectData data = {
.clmd = clmd,
.collmd = collmd,
.overlap = overlap,
.collisions = *collisions,
.culling = culling,
.use_normal = use_normal,
.collided = false,
};
ColDetectData data{};
data.clmd = clmd;
data.collmd = collmd;
data.overlap = overlap;
data.collisions = *collisions;
data.culling = culling;
data.use_normal = use_normal;
data.collided = false;
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
@ -1420,12 +1422,11 @@ static bool cloth_bvh_selfcollisions_nearcheck(ClothModifierData *clmd,
int numresult,
BVHTreeOverlap *overlap)
{
SelfColDetectData data = {
.clmd = clmd,
.overlap = overlap,
.collisions = collisions,
.collided = false,
};
SelfColDetectData data{};
data.clmd = clmd;
data.overlap = overlap;
data.collisions = collisions;
data.collided = false;
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
@ -1444,7 +1445,7 @@ static int cloth_bvh_objcollisions_resolve(ClothModifierData *clmd,
{
Cloth *cloth = clmd->clothObject;
int i = 0, j = 0, mvert_num = 0;
ClothVertex *verts = NULL;
ClothVertex *verts = nullptr;
int ret = 0;
int result = 0;
@ -1495,7 +1496,7 @@ static int cloth_bvh_selfcollisions_resolve(ClothModifierData *clmd,
{
Cloth *cloth = clmd->clothObject;
int i = 0, j = 0, mvert_num = 0;
ClothVertex *verts = NULL;
ClothVertex *verts = nullptr;
int ret = 0;
int result = 0;
@ -1529,25 +1530,22 @@ static int cloth_bvh_selfcollisions_resolve(ClothModifierData *clmd,
return ret;
}
static bool cloth_bvh_obj_overlap_cb(void *userdata,
int index_a,
int UNUSED(index_b),
int UNUSED(thread))
static bool cloth_bvh_obj_overlap_cb(void *userdata, int index_a, int /*index_b*/, int /*thread*/)
{
ClothModifierData *clmd = (ClothModifierData *)userdata;
struct Cloth *clothObject = clmd->clothObject;
Cloth *clothObject = clmd->clothObject;
const MVertTri *tri_a = &clothObject->tri[index_a];
return cloth_bvh_collision_is_active(clmd, clothObject, tri_a);
}
static bool cloth_bvh_self_overlap_cb(void *userdata, int index_a, int index_b, int UNUSED(thread))
static bool cloth_bvh_self_overlap_cb(void *userdata, int index_a, int index_b, int /*thread*/)
{
/* This shouldn't happen, but just in case. Note that equal combinations
* (eg. (0,1) & (1,0)) would be filtered out by BLI_bvhtree_overlap_self. */
if (index_a != index_b) {
ClothModifierData *clmd = (ClothModifierData *)userdata;
struct Cloth *clothObject = clmd->clothObject;
Cloth *clothObject = clmd->clothObject;
const MVertTri *tri_a, *tri_b;
tri_a = &clothObject->tri[index_a];
tri_b = &clothObject->tri[index_b];
@ -1566,17 +1564,17 @@ int cloth_bvh_collision(
BVHTree *cloth_bvh = cloth->bvhtree;
uint i = 0, mvert_num = 0;
int rounds = 0;
ClothVertex *verts = NULL;
ClothVertex *verts = nullptr;
int ret = 0, ret2 = 0;
Object **collobjs = NULL;
Object **collobjs = nullptr;
uint numcollobj = 0;
uint *coll_counts_obj = NULL;
BVHTreeOverlap **overlap_obj = NULL;
uint *coll_counts_obj = nullptr;
BVHTreeOverlap **overlap_obj = nullptr;
uint coll_count_self = 0;
BVHTreeOverlap *overlap_self = NULL;
BVHTreeOverlap *overlap_self = nullptr;
bool bvh_updated = false;
if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || cloth_bvh == NULL) {
if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || cloth_bvh == nullptr) {
return 0;
}
@ -1588,17 +1586,17 @@ int cloth_bvh_collision(
bvh_updated = true;
/* Enable self collision if this is a hair sim */
const bool is_hair = (clmd->hairdata != NULL);
const bool is_hair = (clmd->hairdata != nullptr);
collobjs = BKE_collision_objects_create(depsgraph,
is_hair ? NULL : ob,
is_hair ? nullptr : ob,
clmd->coll_parms->group,
&numcollobj,
eModifierType_Collision);
if (collobjs) {
coll_counts_obj = MEM_callocN(sizeof(uint) * numcollobj, "CollCounts");
overlap_obj = MEM_callocN(sizeof(*overlap_obj) * numcollobj, "BVHOverlap");
coll_counts_obj = MEM_cnew_array<uint>(numcollobj, "CollCounts");
overlap_obj = MEM_cnew_array<BVHTreeOverlap *>(numcollobj, "BVHOverlap");
for (i = 0; i < numcollobj; i++) {
Object *collob = collobjs[i];
@ -1615,7 +1613,7 @@ int cloth_bvh_collision(
overlap_obj[i] = BLI_bvhtree_overlap(cloth_bvh,
collmd->bvhtree,
&coll_counts_obj[i],
is_hair ? NULL : cloth_bvh_obj_overlap_cb,
is_hair ? nullptr : cloth_bvh_obj_overlap_cb,
clmd);
}
}
@ -1638,7 +1636,7 @@ int cloth_bvh_collision(
CollPair **collisions;
bool collided = false;
collisions = MEM_callocN(sizeof(CollPair *) * numcollobj, "CollPair");
collisions = MEM_cnew_array<CollPair *>(numcollobj, "CollPair");
for (i = 0; i < numcollobj; i++) {
Object *collob = collobjs[i];
@ -1677,7 +1675,7 @@ int cloth_bvh_collision(
/* Self collisions. */
if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF) {
CollPair *collisions = NULL;
CollPair *collisions = nullptr;
verts = cloth->verts;
mvert_num = cloth->mvert_num;

View File

@ -1005,26 +1005,21 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map,
return true;
}
if (r_map && cddata_type == CD_FAKE_SEAM) {
const size_t elem_size = sizeof(*((MEdge *)nullptr));
const size_t data_size = sizeof(((MEdge *)nullptr)->flag);
const size_t data_offset = offsetof(MEdge, flag);
const uint64_t data_flag = ME_SEAM;
data_transfer_layersmapping_add_item(r_map,
cddata_type,
mix_mode,
mix_factor,
mix_weights,
BKE_mesh_edges(me_src),
BKE_mesh_edges_for_write(me_dst),
me_src->totedge,
me_dst->totedge,
elem_size,
data_size,
data_offset,
data_flag,
nullptr,
interp_data);
if (!CustomData_get_layer_named(&me_dst->edata, CD_PROP_BOOL, ".uv_seam")) {
CustomData_add_layer_named(
&me_dst->edata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, me_dst->totedge, ".uv_seam");
}
data_transfer_layersmapping_add_item_cd(
r_map,
CD_PROP_BOOL,
mix_mode,
mix_factor,
mix_weights,
CustomData_get_layer_named(&me_src->edata, CD_PROP_BOOL, ".uv_seam"),
CustomData_get_layer_named_for_write(
&me_dst->edata, CD_PROP_BOOL, ".uv_seam", me_dst->totedge),
interp,
interp_data);
return true;
}
if (r_map && cddata_type == CD_FAKE_SHARP) {

View File

@ -1481,7 +1481,7 @@ struct DynamicPaintSetInitColorData {
blender::Span<MLoop> loops;
const float (*mloopuv)[2];
const MLoopTri *mlooptri;
blender::Span<MLoopTri> looptris;
const MLoopCol *mloopcol;
ImagePool *pool;
@ -1498,7 +1498,7 @@ static void dynamic_paint_set_init_color_tex_to_vcol_cb(void *__restrict userdat
PaintPoint *pPoint = (PaintPoint *)sData->type_data;
const blender::Span<MLoop> loops = data->loops;
const MLoopTri *mlooptri = data->mlooptri;
const blender::Span<MLoopTri> looptris = data->looptris;
const float(*mloopuv)[2] = data->mloopuv;
ImagePool *pool = data->pool;
Tex *tex = data->surface->init_texture;
@ -1509,11 +1509,11 @@ static void dynamic_paint_set_init_color_tex_to_vcol_cb(void *__restrict userdat
for (int j = 3; j--;) {
TexResult texres = {0};
const uint vert = loops[mlooptri[i].tri[j]].v;
const uint vert = loops[looptris[i].tri[j]].v;
/* remap to [-1.0, 1.0] */
uv[0] = mloopuv[mlooptri[i].tri[j]][0] * 2.0f - 1.0f;
uv[1] = mloopuv[mlooptri[i].tri[j]][1] * 2.0f - 1.0f;
uv[0] = mloopuv[looptris[i].tri[j]][0] * 2.0f - 1.0f;
uv[1] = mloopuv[looptris[i].tri[j]][1] * 2.0f - 1.0f;
multitex_ext_safe(tex, uv, &texres, pool, scene_color_manage, false);
@ -1533,7 +1533,7 @@ static void dynamic_paint_set_init_color_tex_to_imseq_cb(void *__restrict userda
const PaintSurfaceData *sData = data->surface->data;
PaintPoint *pPoint = (PaintPoint *)sData->type_data;
const MLoopTri *mlooptri = data->mlooptri;
const blender::Span<MLoopTri> looptris = data->looptris;
const float(*mloopuv)[2] = data->mloopuv;
Tex *tex = data->surface->init_texture;
ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data;
@ -1548,7 +1548,7 @@ static void dynamic_paint_set_init_color_tex_to_imseq_cb(void *__restrict userda
/* collect all uvs */
for (int j = 3; j--;) {
copy_v2_v2(&uv[j * 3], mloopuv[mlooptri[f_data->uv_p[i].tri_index].tri[j]]);
copy_v2_v2(&uv[j * 3], mloopuv[looptris[f_data->uv_p[i].tri_index].tri[j]]);
}
/* interpolate final uv pos */
@ -1572,7 +1572,7 @@ static void dynamic_paint_set_init_color_vcol_to_imseq_cb(
const PaintSurfaceData *sData = data->surface->data;
PaintPoint *pPoint = (PaintPoint *)sData->type_data;
const MLoopTri *mlooptri = data->mlooptri;
const blender::Span<MLoopTri> looptris = data->looptris;
const MLoopCol *mloopcol = data->mloopcol;
ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data;
const int samples = (data->surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
@ -1583,7 +1583,7 @@ static void dynamic_paint_set_init_color_vcol_to_imseq_cb(
/* collect color values */
for (int j = 3; j--;) {
rgba_uchar_to_float(colors[j], (const uchar *)&mloopcol[mlooptri[tri_idx].tri[j]].r);
rgba_uchar_to_float(colors[j], (const uchar *)&mloopcol[looptris[tri_idx].tri[j]].r);
}
/* interpolate final color */
@ -1619,8 +1619,7 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface
Tex *tex = surface->init_texture;
const blender::Span<MLoop> loops = mesh->loops();
const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
const int tottri = BKE_mesh_runtime_looptri_len(mesh);
const blender::Span<MLoopTri> looptris = mesh->looptris();
char uvname[MAX_CUSTOMDATA_LAYER_NAME];
@ -1645,22 +1644,22 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface
DynamicPaintSetInitColorData data{};
data.surface = surface;
data.loops = loops;
data.mlooptri = mlooptri;
data.looptris = looptris;
data.mloopuv = mloopuv;
data.pool = pool;
data.scene_color_manage = scene_color_manage;
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
settings.use_threading = (tottri > 1000);
settings.use_threading = (looptris.size() > 1000);
BLI_task_parallel_range(
0, tottri, &data, dynamic_paint_set_init_color_tex_to_vcol_cb, &settings);
0, looptris.size(), &data, dynamic_paint_set_init_color_tex_to_vcol_cb, &settings);
BKE_image_pool_free(pool);
}
else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
DynamicPaintSetInitColorData data{};
data.surface = surface;
data.mlooptri = mlooptri;
data.looptris = looptris;
data.mloopuv = mloopuv;
data.scene_color_manage = scene_color_manage;
@ -1688,7 +1687,7 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface
}
}
else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
const blender::Span<MLoopTri> looptris = mesh->looptris();
const MLoopCol *col = static_cast<const MLoopCol *>(
CustomData_get_layer_named(&mesh->ldata, CD_PROP_BYTE_COLOR, surface->init_layername));
if (!col) {
@ -1697,7 +1696,7 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface
DynamicPaintSetInitColorData data{};
data.surface = surface;
data.mlooptri = mlooptri;
data.looptris = looptris;
data.mloopcol = col;
TaskParallelSettings settings;
@ -2192,10 +2191,9 @@ struct DynamicPaintCreateUVSurfaceData {
PaintUVPoint *tempPoints;
Vec3f *tempWeights;
const MLoopTri *mlooptri;
blender::Span<MLoopTri> looptris;
const float (*mloopuv)[2];
blender::Span<MLoop> loops;
int tottri;
const Bounds2D *faceBB;
uint32_t *active_points;
@ -2212,10 +2210,9 @@ static void dynamic_paint_create_uv_surface_direct_cb(void *__restrict userdata,
PaintUVPoint *tempPoints = data->tempPoints;
Vec3f *tempWeights = data->tempWeights;
const MLoopTri *mlooptri = data->mlooptri;
const blender::Span<MLoopTri> looptris = data->looptris;
const float(*mloopuv)[2] = data->mloopuv;
const blender::Span<MLoop> loops = data->loops;
const int tottri = data->tottri;
const Bounds2D *faceBB = data->faceBB;
@ -2259,16 +2256,16 @@ static void dynamic_paint_create_uv_surface_direct_cb(void *__restrict userdata,
/* Loop through every face in the mesh */
/* XXX TODO: This is *horrible* with big meshes, should use a 2D BVHTree over UV tris here!
*/
for (int i = 0; i < tottri; i++) {
for (const int i : looptris.index_range()) {
/* Check uv bb */
if ((faceBB[i].min[0] > point[sample][0]) || (faceBB[i].min[1] > point[sample][1]) ||
(faceBB[i].max[0] < point[sample][0]) || (faceBB[i].max[1] < point[sample][1])) {
continue;
}
const float *uv1 = mloopuv[mlooptri[i].tri[0]];
const float *uv2 = mloopuv[mlooptri[i].tri[1]];
const float *uv3 = mloopuv[mlooptri[i].tri[2]];
const float *uv1 = mloopuv[looptris[i].tri[0]];
const float *uv2 = mloopuv[looptris[i].tri[1]];
const float *uv3 = mloopuv[looptris[i].tri[2]];
/* If point is inside the face */
if (isect_point_tri_v2(point[sample], uv1, uv2, uv3) != 0) {
@ -2286,9 +2283,9 @@ static void dynamic_paint_create_uv_surface_direct_cb(void *__restrict userdata,
tPoint->tri_index = i;
/* save vertex indexes */
tPoint->v1 = loops[mlooptri[i].tri[0]].v;
tPoint->v2 = loops[mlooptri[i].tri[1]].v;
tPoint->v3 = loops[mlooptri[i].tri[2]].v;
tPoint->v1 = loops[looptris[i].tri[0]].v;
tPoint->v2 = loops[looptris[i].tri[1]].v;
tPoint->v3 = loops[looptris[i].tri[2]].v;
sample = 5; /* make sure we exit sample loop as well */
break;
@ -2309,7 +2306,7 @@ static void dynamic_paint_create_uv_surface_neighbor_cb(void *__restrict userdat
PaintUVPoint *tempPoints = data->tempPoints;
Vec3f *tempWeights = data->tempWeights;
const MLoopTri *mlooptri = data->mlooptri;
const blender::Span<MLoopTri> looptris = data->looptris;
const float(*mloopuv)[2] = data->mloopuv;
const blender::Span<MLoop> loops = data->loops;
@ -2351,9 +2348,9 @@ static void dynamic_paint_create_uv_surface_neighbor_cb(void *__restrict userdat
if (tempPoints[ind].neighbor_pixel == -1 && tempPoints[ind].tri_index != -1) {
float uv[2];
const int i = tempPoints[ind].tri_index;
const float *uv1 = mloopuv[mlooptri[i].tri[0]];
const float *uv2 = mloopuv[mlooptri[i].tri[1]];
const float *uv3 = mloopuv[mlooptri[i].tri[2]];
const float *uv1 = mloopuv[looptris[i].tri[0]];
const float *uv2 = mloopuv[looptris[i].tri[1]];
const float *uv3 = mloopuv[looptris[i].tri[2]];
/* tri index */
/* There is a low possibility of actually having a neighbor point which tri is
@ -2376,9 +2373,9 @@ static void dynamic_paint_create_uv_surface_neighbor_cb(void *__restrict userdat
}
/* save vertex indexes */
tPoint->v1 = loops[mlooptri[i].tri[0]].v;
tPoint->v2 = loops[mlooptri[i].tri[1]].v;
tPoint->v3 = loops[mlooptri[i].tri[2]].v;
tPoint->v1 = loops[looptris[i].tri[0]].v;
tPoint->v2 = loops[looptris[i].tri[1]].v;
tPoint->v3 = loops[looptris[i].tri[2]].v;
break;
}
@ -2396,7 +2393,7 @@ static void dynamic_paint_create_uv_surface_neighbor_cb(void *__restrict userdat
#undef JITTER_SAMPLES
static float dist_squared_to_looptri_uv_edges(const MLoopTri *mlooptri,
static float dist_squared_to_looptri_uv_edges(const blender::Span<MLoopTri> looptris,
const float (*mloopuv)[2],
int tri_index,
const float point[2])
@ -2408,8 +2405,8 @@ static float dist_squared_to_looptri_uv_edges(const MLoopTri *mlooptri,
for (int i = 0; i < 3; i++) {
const float dist_squared = dist_squared_to_line_segment_v2(
point,
mloopuv[mlooptri[tri_index].tri[(i + 0)]],
mloopuv[mlooptri[tri_index].tri[(i + 1) % 3]]);
mloopuv[looptris[tri_index].tri[(i + 0)]],
mloopuv[looptris[tri_index].tri[(i + 1) % 3]]);
if (dist_squared < min_distance) {
min_distance = dist_squared;
@ -2520,10 +2517,10 @@ static void dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceDa
int depth)
{
const blender::Span<MLoop> loops = data->loops;
const MLoopTri *mlooptri = data->mlooptri;
const blender::Span<MLoopTri> looptris = data->looptris;
const float(*mloopuv)[2] = data->mloopuv;
const uint *loop_idx = mlooptri[tri_index].tri;
const uint *loop_idx = looptris[tri_index].tri;
/* Enumerate all edges of the triangle, rotating the vertex list accordingly. */
for (int edge_idx = 0; edge_idx < 3; edge_idx++) {
@ -2577,7 +2574,7 @@ static void dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceDa
continue;
}
const uint *other_loop_idx = mlooptri[lt_index].tri;
const uint *other_loop_idx = looptris[lt_index].tri;
/* Check edges for match, looping in the same order as the outer loop. */
for (int j = 0; j < 3; j++) {
@ -2680,7 +2677,7 @@ static void dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceDa
const float final_pt[2] = {((final_index % w) + 0.5f) / w, ((final_index / w) + 0.5f) / h};
const float threshold = square_f(0.7f) / (w * h);
if (dist_squared_to_looptri_uv_edges(mlooptri, mloopuv, final_tri_index, final_pt) >
if (dist_squared_to_looptri_uv_edges(looptris, mloopuv, final_tri_index, final_pt) >
threshold) {
continue;
}
@ -2818,7 +2815,6 @@ int dynamicPaint_createUVSurface(Scene *scene,
PaintUVPoint *tempPoints = nullptr;
Vec3f *tempWeights = nullptr;
const MLoopTri *mlooptri = nullptr;
const float(*mloopuv)[2] = nullptr;
Bounds2D *faceBB = nullptr;
@ -2835,8 +2831,7 @@ int dynamicPaint_createUVSurface(Scene *scene,
}
const blender::Span<MLoop> loops = mesh->loops();
mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
const int tottri = BKE_mesh_runtime_looptri_len(mesh);
const blender::Span<MLoopTri> looptris = mesh->looptris();
/* get uv map */
if (CustomData_has_layer(&mesh->ldata, CD_PROP_FLOAT2)) {
@ -2859,7 +2854,8 @@ int dynamicPaint_createUVSurface(Scene *scene,
/*
* Start generating the surface
*/
CLOG_INFO(&LOG, 1, "Preparing UV surface of %ix%i pixels and %i tris.", w, h, tottri);
CLOG_INFO(
&LOG, 1, "Preparing UV surface of %ix%i pixels and %i tris.", w, h, int(looptris.size()));
/* Init data struct */
if (surface->data) {
@ -2893,7 +2889,8 @@ int dynamicPaint_createUVSurface(Scene *scene,
* the pixel-inside-a-face search.
*/
if (!error) {
faceBB = static_cast<Bounds2D *>(MEM_mallocN(tottri * sizeof(*faceBB), "MPCanvasFaceBB"));
faceBB = static_cast<Bounds2D *>(
MEM_malloc_arrayN(looptris.size(), sizeof(*faceBB), "MPCanvasFaceBB"));
if (!faceBB) {
error = true;
}
@ -2903,12 +2900,12 @@ int dynamicPaint_createUVSurface(Scene *scene,
*do_update = true;
if (!error) {
for (int i = 0; i < tottri; i++) {
copy_v2_v2(faceBB[i].min, mloopuv[mlooptri[i].tri[0]]);
copy_v2_v2(faceBB[i].max, mloopuv[mlooptri[i].tri[0]]);
for (const int i : looptris.index_range()) {
copy_v2_v2(faceBB[i].min, mloopuv[looptris[i].tri[0]]);
copy_v2_v2(faceBB[i].max, mloopuv[looptris[i].tri[0]]);
for (int j = 1; j < 3; j++) {
minmax_v2v2_v2(faceBB[i].min, faceBB[i].max, mloopuv[mlooptri[i].tri[j]]);
minmax_v2v2_v2(faceBB[i].min, faceBB[i].max, mloopuv[looptris[i].tri[j]]);
}
}
@ -2920,16 +2917,15 @@ int dynamicPaint_createUVSurface(Scene *scene,
data.surface = surface;
data.tempPoints = tempPoints;
data.tempWeights = tempWeights;
data.mlooptri = mlooptri;
data.looptris = looptris;
data.mloopuv = mloopuv;
data.loops = loops;
data.tottri = tottri;
data.faceBB = faceBB;
{
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
settings.use_threading = (h > 64 || tottri > 1000);
settings.use_threading = (h > 64 || looptris.size() > 1000);
BLI_task_parallel_range(0, h, &data, dynamic_paint_create_uv_surface_direct_cb, &settings);
}
@ -2979,8 +2975,8 @@ int dynamicPaint_createUVSurface(Scene *scene,
BKE_mesh_vert_looptri_map_create(&vert_to_looptri_map,
&vert_to_looptri_map_mem,
mesh->totvert,
mlooptri,
tottri,
looptris.data(),
looptris.size(),
loops.data(),
mesh->totloop);
@ -3439,15 +3435,15 @@ static void mesh_tris_spherecast_dp(void *userdata,
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->vert_positions;
const MLoopTri *mlooptri = data->looptri;
const MLoopTri *looptris = data->looptri;
const MLoop *loops = data->loop;
const float *t0, *t1, *t2;
float dist;
t0 = positions[loops[mlooptri[index].tri[0]].v];
t1 = positions[loops[mlooptri[index].tri[1]].v];
t2 = positions[loops[mlooptri[index].tri[2]].v];
t0 = positions[loops[looptris[index].tri[0]].v];
t1 = positions[loops[looptris[index].tri[1]].v];
t2 = positions[loops[looptris[index].tri[2]].v];
dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
@ -3471,14 +3467,14 @@ static void mesh_tris_nearest_point_dp(void *userdata,
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float(*positions)[3] = data->vert_positions;
const MLoopTri *mlooptri = data->looptri;
const MLoopTri *looptris = data->looptri;
const MLoop *loops = data->loop;
float nearest_tmp[3], dist_sq;
const float *t0, *t1, *t2;
t0 = positions[loops[mlooptri[index].tri[0]].v];
t1 = positions[loops[mlooptri[index].tri[1]].v];
t2 = positions[loops[mlooptri[index].tri[2]].v];
t0 = positions[loops[looptris[index].tri[0]].v];
t1 = positions[loops[looptris[index].tri[1]].v];
t2 = positions[loops[looptris[index].tri[2]].v];
closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2);
dist_sq = len_squared_v3v3(co, nearest_tmp);
@ -3912,7 +3908,7 @@ struct DynamicPaintPaintData {
Mesh *mesh;
const float (*positions)[3];
blender::Span<MLoop> loops;
const MLoopTri *mlooptri;
blender::Span<MLoopTri> looptris;
float brush_radius;
const float *avg_brushNor;
const Vec3f *brushVelocity;
@ -3946,7 +3942,7 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(void *__restrict userdata,
const float(*positions)[3] = data->positions;
const blender::Span<MLoop> loops = data->loops;
const MLoopTri *mlooptri = data->mlooptri;
const blender::Span<MLoopTri> looptris = data->looptris;
const float brush_radius = data->brush_radius;
const float *avg_brushNor = data->avg_brushNor;
const Vec3f *brushVelocity = data->brushVelocity;
@ -4019,9 +4015,9 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(void *__restrict userdata,
/* For optimization sake, hit point normal isn't calculated in ray cast loop */
const int vtri[3] = {
int(loops[mlooptri[hit.index].tri[0]].v),
int(loops[mlooptri[hit.index].tri[1]].v),
int(loops[mlooptri[hit.index].tri[2]].v),
int(loops[looptris[hit.index].tri[0]].v),
int(loops[looptris[hit.index].tri[1]].v),
int(loops[looptris[hit.index].tri[2]].v),
};
float dot;
@ -4169,9 +4165,9 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(void *__restrict userdata,
float brushPointVelocity[3];
float velocity[3];
const int v1 = loops[mlooptri[hitTri].tri[0]].v;
const int v2 = loops[mlooptri[hitTri].tri[1]].v;
const int v3 = loops[mlooptri[hitTri].tri[2]].v;
const int v1 = loops[looptris[hitTri].tri[0]].v;
const int v2 = loops[looptris[hitTri].tri[1]].v;
const int v3 = loops[looptris[hitTri].tri[2]].v;
/* calculate barycentric weights for hit point */
interp_weights_tri_v3(weights, positions[v1], positions[v2], positions[v3], hitCoord);
@ -4270,7 +4266,6 @@ static bool dynamicPaint_paintMesh(Depsgraph *depsgraph,
PaintBakeData *bData = sData->bData;
Mesh *mesh = nullptr;
Vec3f *brushVelocity = nullptr;
const MLoopTri *mlooptri = nullptr;
if (brush->flags & MOD_DPAINT_USES_VELOCITY) {
dynamicPaint_brushMeshCalculateVelocity(
@ -4294,7 +4289,7 @@ static bool dynamicPaint_paintMesh(Depsgraph *depsgraph,
mesh = BKE_mesh_copy_for_eval(brush_mesh, false);
float(*positions)[3] = BKE_mesh_vert_positions_for_write(mesh);
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(mesh);
mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
const blender::Span<MLoopTri> looptris = mesh->looptris();
const blender::Span<MLoop> loops = mesh->loops();
numOfVerts = mesh->totvert;
@ -4350,7 +4345,7 @@ static bool dynamicPaint_paintMesh(Depsgraph *depsgraph,
data.mesh = mesh;
data.positions = positions;
data.loops = loops;
data.mlooptri = mlooptri;
data.looptris = looptris;
data.brush_radius = brush_radius;
data.avg_brushNor = avg_brushNor;
data.brushVelocity = brushVelocity;

View File

@ -939,7 +939,7 @@ struct ObstaclesFromDMData {
const float (*vert_positions)[3];
const MLoop *mloop;
const MLoopTri *mlooptri;
blender::Span<MLoopTri> looptris;
BVHTreeFromMesh *tree;
FluidObjectBB *bb;
@ -974,7 +974,7 @@ static void obstacles_from_mesh_task_cb(void *__restrict userdata,
update_velocities(data->fes,
data->vert_positions,
data->mloop,
data->mlooptri,
data->looptris.data(),
bb->velocity,
index,
data->tree,
@ -997,7 +997,6 @@ static void obstacles_from_mesh(Object *coll_ob,
float dt)
{
if (fes->mesh) {
const MLoopTri *looptri;
BVHTreeFromMesh tree_data = {nullptr};
int numverts, i;
@ -1010,7 +1009,7 @@ static void obstacles_from_mesh(Object *coll_ob,
int min[3], max[3], res[3];
const MLoop *mloop = BKE_mesh_loops(me);
looptri = BKE_mesh_runtime_looptri_ensure(me);
const blender::Span<MLoopTri> looptris = me->looptris();
numverts = me->totvert;
/* TODO(sebbas): Make initialization of vertex velocities optional? */
@ -1074,7 +1073,7 @@ static void obstacles_from_mesh(Object *coll_ob,
data.fes = fes;
data.vert_positions = positions;
data.mloop = mloop;
data.mlooptri = looptri;
data.looptris = looptris;
data.tree = &tree_data;
data.bb = bb;
data.has_velocity = has_velocity;
@ -1983,7 +1982,7 @@ struct EmitFromDMData {
const float (*vert_positions)[3];
const float (*vert_normals)[3];
const MLoop *mloop;
const MLoopTri *mlooptri;
blender::Span<MLoopTri> looptris;
const float (*mloopuv)[2];
const MDeformVert *dvert;
int defgrp_index;
@ -2017,7 +2016,7 @@ static void emit_from_mesh_task_cb(void *__restrict userdata,
data->vert_positions,
data->vert_normals,
data->mloop,
data->mlooptri,
data->looptris.data(),
data->mloopuv,
bb->influence,
bb->velocity,
@ -2067,7 +2066,7 @@ static void emit_from_mesh(
float(*positions)[3] = BKE_mesh_vert_positions_for_write(me);
const MLoop *mloop = BKE_mesh_loops(me);
const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(me);
const blender::Span<MLoopTri> looptris = me->looptris();
const int numverts = me->totvert;
const MDeformVert *dvert = BKE_mesh_deform_verts(me);
const float(*mloopuv)[2] = static_cast<const float(*)[2]>(
@ -2144,7 +2143,7 @@ static void emit_from_mesh(
data.vert_positions = positions;
data.vert_normals = vert_normals;
data.mloop = mloop;
data.mlooptri = mlooptri;
data.looptris = looptris;
data.mloopuv = mloopuv;
data.dvert = dvert;
data.defgrp_index = defgrp_index;

View File

@ -493,7 +493,13 @@ bool BKE_gpencil_stroke_sample(bGPdata *gpd,
copy_v3_v3(&pt2->x, last_coord);
new_pt[i].pressure = pt[0].pressure;
new_pt[i].strength = pt[0].strength;
memcpy(new_pt[i].vert_color, pt[0].vert_color, sizeof(float[4]));
copy_v3_v3(&pt2->x, last_coord);
new_pt[i].pressure = pt[0].pressure;
new_pt[i].strength = pt[0].strength;
new_pt[i].uv_fac = pt[0].uv_fac;
new_pt[i].uv_rot = pt[0].uv_rot;
copy_v2_v2(new_pt[i].uv_fill, pt[0].uv_fill);
copy_v4_v4(new_pt[i].vert_color, pt[0].vert_color);
if (select) {
new_pt[i].flag |= GP_SPOINT_SELECT;
}
@ -2266,7 +2272,7 @@ void BKE_gpencil_stroke_subdivide(bGPdata *gpd, bGPDstroke *gps, int level, int
pt_final->uv_fac = interpf(pt->uv_fac, next->uv_fac, 0.5f);
interp_v4_v4v4(pt_final->uv_fill, pt->uv_fill, next->uv_fill, 0.5f);
CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
pt_final->time = interpf(pt->time, next->time, 0.5f);
pt_final->time = 0;
pt_final->runtime.pt_orig = nullptr;
pt_final->flag = 0;
interp_v4_v4v4(pt_final->vert_color, pt->vert_color, next->vert_color, 0.5f);
@ -2490,6 +2496,7 @@ static void gpencil_generate_edgeloops(Object *ob,
const bool use_seams,
const bool use_vgroups)
{
using namespace blender;
Mesh *me = (Mesh *)ob->data;
if (me->totedge == 0) {
return;
@ -2498,6 +2505,9 @@ static void gpencil_generate_edgeloops(Object *ob,
const Span<MEdge> edges = me->edges();
const Span<MDeformVert> dverts = me->deform_verts();
const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(me);
const bke::AttributeAccessor attributes = me->attributes();
const VArray<bool> uv_seams = attributes.lookup_or_default<bool>(
".uv_seam", ATTR_DOMAIN_EDGE, false);
/* Arrays for all edge vertices (forward and backward) that form a edge loop.
* This is reused for each edge-loop to create gpencil stroke. */
@ -2523,7 +2533,7 @@ static void gpencil_generate_edgeloops(Object *ob,
sub_v3_v3v3(gped->vec, vert_positions[ed->v1], vert_positions[ed->v2]);
/* If use seams, mark as done if not a seam. */
if ((use_seams) && ((ed->flag & ME_SEAM) == 0)) {
if ((use_seams) && !uv_seams[i]) {
gped->flag = 1;
}
}

View File

@ -85,11 +85,11 @@ static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc)
view_layer->active_collection = nullptr;
}
LISTBASE_FOREACH (LayerCollection *, nlc, &lc->layer_collections) {
LISTBASE_FOREACH_MUTABLE (LayerCollection *, nlc, &lc->layer_collections) {
layer_collection_free(view_layer, nlc);
MEM_freeN(nlc);
}
BLI_freelistN(&lc->layer_collections);
BLI_listbase_clear(&lc->layer_collections);
}
static Base *object_base_new(Object *ob)
@ -254,10 +254,11 @@ void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user)
BLI_ghash_free(view_layer->object_bases_hash, nullptr, nullptr);
}
LISTBASE_FOREACH (LayerCollection *, lc, &view_layer->layer_collections) {
LISTBASE_FOREACH_MUTABLE (LayerCollection *, lc, &view_layer->layer_collections) {
layer_collection_free(view_layer, lc);
MEM_freeN(lc);
}
BLI_freelistN(&view_layer->layer_collections);
BLI_listbase_clear(&view_layer->layer_collections);
LISTBASE_FOREACH (ViewLayerEngineData *, sled, &view_layer->drawdata) {
if (sled->storage) {

View File

@ -40,6 +40,13 @@ Main *BKE_main_new()
void BKE_main_free(Main *mainvar)
{
/* In case this is called on a 'split-by-libraries' list of mains.
*
* Should not happen in typical usages, but can occur e.g. if a file reading is aborted. */
if (mainvar->next) {
BKE_main_free(mainvar->next);
}
/* also call when reading a file, erase all, etc */
ListBase *lbarray[INDEX_ID_MAX];
int a;

View File

@ -272,6 +272,7 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
BKE_mesh_legacy_bevel_weight_from_layers(mesh);
BKE_mesh_legacy_edge_crease_from_layers(mesh);
BKE_mesh_legacy_sharp_edges_to_flags(mesh);
BKE_mesh_legacy_uv_seam_to_flags(mesh);
BKE_mesh_legacy_attribute_strings_to_flags(mesh);
mesh->active_color_attribute = nullptr;
mesh->default_color_attribute = nullptr;

View File

@ -104,9 +104,9 @@ class MeshesToIMeshInfo {
void input_mvert_for_orig_index(int orig_index,
const Mesh **r_orig_mesh,
int *r_index_in_orig_mesh) const;
const MEdge *input_medge_for_orig_index(int orig_index,
const Mesh **r_orig_mesh,
int *r_index_in_orig_mesh) const;
void input_medge_for_orig_index(int orig_index,
const Mesh **r_orig_mesh,
int *r_index_in_orig_mesh) const;
};
/* Given an index `imesh_v` in the `IMesh`, return the index of the
@ -199,24 +199,21 @@ void MeshesToIMeshInfo::input_mvert_for_orig_index(int orig_index,
}
/* Similarly for edges. */
const MEdge *MeshesToIMeshInfo::input_medge_for_orig_index(int orig_index,
const Mesh **r_orig_mesh,
int *r_index_in_orig_mesh) const
void MeshesToIMeshInfo::input_medge_for_orig_index(int orig_index,
const Mesh **r_orig_mesh,
int *r_index_in_orig_mesh) const
{
int orig_mesh_index = input_mesh_for_imesh_edge(orig_index);
BLI_assert(0 <= orig_mesh_index && orig_mesh_index < meshes.size());
const Mesh *me = meshes[orig_mesh_index];
const Span<MEdge> edges = me->edges();
int index_in_mesh = orig_index - mesh_edge_offset[orig_mesh_index];
BLI_assert(0 <= index_in_mesh && index_in_mesh < me->totedge);
const MEdge *medge = &edges[index_in_mesh];
if (r_orig_mesh) {
*r_orig_mesh = me;
}
if (r_index_in_orig_mesh) {
*r_index_in_orig_mesh = index_in_mesh;
}
return medge;
}
/**
@ -434,13 +431,10 @@ static void copy_poly_attributes(Mesh *dest_mesh,
/* Similar to copy_vert_attributes but for edge attributes. */
static void copy_edge_attributes(Mesh *dest_mesh,
MEdge *medge,
const MEdge *orig_medge,
const Mesh *orig_me,
int medge_index,
int index_in_orig_me)
{
medge->flag = orig_medge->flag;
CustomData *target_cd = &dest_mesh->edata;
const CustomData *source_cd = &orig_me->edata;
for (int source_layer_i = 0; source_layer_i < source_cd->totlayer; ++source_layer_i) {
@ -777,7 +771,6 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
/* Now that the MEdges are populated, we can copy over the required attributes and custom layers.
*/
MutableSpan<MEdge> edges = result->edges_for_write();
for (int fi : im->face_index_range()) {
const Face *f = im->face(fi);
const MPoly *mp = &dst_polys[fi];
@ -785,11 +778,9 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
if (f->edge_orig[j] != NO_INDEX) {
const Mesh *orig_me;
int index_in_orig_me;
const MEdge *orig_medge = mim.input_medge_for_orig_index(
f->edge_orig[j], &orig_me, &index_in_orig_me);
mim.input_medge_for_orig_index(f->edge_orig[j], &orig_me, &index_in_orig_me);
int e_index = dst_loops[mp->loopstart + j].e;
MEdge *medge = &edges[e_index];
copy_edge_attributes(result, medge, orig_medge, orig_me, e_index, index_in_orig_me);
copy_edge_attributes(result, orig_me, e_index, index_in_orig_me);
}
}
}

View File

@ -120,8 +120,6 @@ static void make_edges_mdata_extend(Mesh &mesh)
BLI_edgehashIterator_step(ehi), ++medge, e_index++) {
BLI_edgehashIterator_getKey(ehi, &medge->v1, &medge->v2);
BLI_edgehashIterator_setValue(ehi, POINTER_FROM_UINT(e_index));
medge->flag = 0;
}
BLI_edgehashIterator_free(ehi);

View File

@ -476,7 +476,7 @@ static void convert_mfaces_to_mpolys(ID *id,
/* unrelated but avoid having the FGON flag enabled,
* so we can reuse it later for something else */
me->flag &= ~ME_FGON;
me->flag_legacy &= ~ME_FGON;
}
polyindex = (int *)CustomData_get_layer(fdata, CD_ORIGINDEX);
@ -1379,13 +1379,13 @@ void BKE_mesh_legacy_sharp_edges_to_flags(Mesh *mesh)
CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge"))) {
threading::parallel_for(edges.index_range(), 4096, [&](const IndexRange range) {
for (const int i : range) {
SET_FLAG_FROM_TEST(edges[i].flag, sharp_edges[i], ME_SHARP);
SET_FLAG_FROM_TEST(edges[i].flag_legacy, sharp_edges[i], ME_SHARP);
}
});
}
else {
for (const int i : edges.index_range()) {
edges[i].flag &= ~ME_SHARP;
edges[i].flag_legacy &= ~ME_SHARP;
}
}
}
@ -1399,13 +1399,14 @@ void BKE_mesh_legacy_sharp_edges_from_flags(Mesh *mesh)
if (attributes.contains("sharp_edge")) {
return;
}
if (std::any_of(
edges.begin(), edges.end(), [](const MEdge &edge) { return edge.flag & ME_SHARP; })) {
if (std::any_of(edges.begin(), edges.end(), [](const MEdge &edge) {
return edge.flag_legacy & ME_SHARP;
})) {
SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_only_span<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE);
threading::parallel_for(edges.index_range(), 4096, [&](const IndexRange range) {
for (const int i : range) {
sharp_edges.span[i] = edges[i].flag & ME_SHARP;
sharp_edges.span[i] = edges[i].flag_legacy & ME_SHARP;
}
});
sharp_edges.finish();
@ -1414,6 +1415,54 @@ void BKE_mesh_legacy_sharp_edges_from_flags(Mesh *mesh)
/** \} */
/* -------------------------------------------------------------------- */
/** \name UV Seam Conversion
* \{ */
void BKE_mesh_legacy_uv_seam_to_flags(Mesh *mesh)
{
using namespace blender;
MutableSpan<MEdge> edges = mesh->edges_for_write();
if (const bool *uv_seams = static_cast<const bool *>(
CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, ".uv_seam"))) {
threading::parallel_for(edges.index_range(), 4096, [&](const IndexRange range) {
for (const int i : range) {
SET_FLAG_FROM_TEST(edges[i].flag_legacy, uv_seams[i], ME_SEAM);
}
});
}
else {
for (const int i : edges.index_range()) {
edges[i].flag_legacy &= ~ME_SEAM;
}
}
}
void BKE_mesh_legacy_uv_seam_from_flags(Mesh *mesh)
{
using namespace blender;
using namespace blender::bke;
const Span<MEdge> edges = mesh->edges();
MutableAttributeAccessor attributes = mesh->attributes_for_write();
if (attributes.contains(".uv_seam")) {
return;
}
if (std::any_of(edges.begin(), edges.end(), [](const MEdge &edge) {
return edge.flag_legacy & ME_SEAM;
})) {
SpanAttributeWriter<bool> uv_seams = attributes.lookup_or_add_for_write_only_span<bool>(
".uv_seam", ATTR_DOMAIN_EDGE);
threading::parallel_for(edges.index_range(), 4096, [&](const IndexRange range) {
for (const int i : range) {
uv_seams.span[i] = edges[i].flag_legacy & ME_SEAM;
}
});
uv_seams.finish();
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Hide Attribute and Legacy Flag Conversion
* \{ */
@ -1438,7 +1487,7 @@ void BKE_mesh_legacy_convert_hide_layers_to_flags(Mesh *mesh)
".hide_edge", ATTR_DOMAIN_EDGE, false);
threading::parallel_for(edges.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {
SET_FLAG_FROM_TEST(edges[i].flag, hide_edge[i], ME_HIDE);
SET_FLAG_FROM_TEST(edges[i].flag_legacy, hide_edge[i], ME_HIDE);
}
});
@ -1476,13 +1525,14 @@ void BKE_mesh_legacy_convert_flags_to_hide_layers(Mesh *mesh)
}
const Span<MEdge> edges = mesh->edges();
if (std::any_of(
edges.begin(), edges.end(), [](const MEdge &edge) { return edge.flag & ME_HIDE; })) {
if (std::any_of(edges.begin(), edges.end(), [](const MEdge &edge) {
return edge.flag_legacy & ME_HIDE;
})) {
SpanAttributeWriter<bool> hide_edge = attributes.lookup_or_add_for_write_only_span<bool>(
".hide_edge", ATTR_DOMAIN_EDGE);
threading::parallel_for(edges.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {
hide_edge.span[i] = edges[i].flag & ME_HIDE;
hide_edge.span[i] = edges[i].flag_legacy & ME_HIDE;
}
});
hide_edge.finish();
@ -1755,7 +1805,7 @@ void BKE_mesh_legacy_convert_selection_layers_to_flags(Mesh *mesh)
".select_edge", ATTR_DOMAIN_EDGE, false);
threading::parallel_for(edges.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {
SET_FLAG_FROM_TEST(edges[i].flag, select_edge[i], SELECT);
SET_FLAG_FROM_TEST(edges[i].flag_legacy, select_edge[i], SELECT);
}
});
@ -1794,13 +1844,14 @@ void BKE_mesh_legacy_convert_flags_to_selection_layers(Mesh *mesh)
}
const Span<MEdge> edges = mesh->edges();
if (std::any_of(
edges.begin(), edges.end(), [](const MEdge &edge) { return edge.flag & SELECT; })) {
if (std::any_of(edges.begin(), edges.end(), [](const MEdge &edge) {
return edge.flag_legacy & SELECT;
})) {
SpanAttributeWriter<bool> select_edge = attributes.lookup_or_add_for_write_only_span<bool>(
".select_edge", ATTR_DOMAIN_EDGE);
threading::parallel_for(edges.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {
select_edge.span[i] = edges[i].flag & SELECT;
select_edge.span[i] = edges[i].flag_legacy & SELECT;
}
});
select_edge.finish();
@ -1836,12 +1887,12 @@ void BKE_mesh_legacy_convert_loose_edges_to_flag(Mesh *mesh)
threading::parallel_for(edges.index_range(), 4096, [&](const IndexRange range) {
if (loose_edges.count == 0) {
for (const int64_t i : range) {
edges[i].flag &= ~ME_LOOSEEDGE;
edges[i].flag_legacy &= ~ME_LOOSEEDGE;
}
}
else {
for (const int64_t i : range) {
SET_FLAG_FROM_TEST(edges[i].flag, loose_edges.is_loose_bits[i], ME_LOOSEEDGE);
SET_FLAG_FROM_TEST(edges[i].flag_legacy, loose_edges.is_loose_bits[i], ME_LOOSEEDGE);
}
}
});

View File

@ -999,8 +999,8 @@ void BKE_mesh_loop_islands_add(MeshIslandStore *island_store,
sizeof(*innrcut->indices) * size_t(num_innercut_items));
}
static bool mesh_calc_islands_loop_poly_uv(const MEdge *edges,
const int totedge,
static bool mesh_calc_islands_loop_poly_uv(const int totedge,
const bool *uv_seams,
const MPoly *polys,
const int totpoly,
const MLoop *loops,
@ -1085,7 +1085,7 @@ static bool mesh_calc_islands_loop_poly_uv(const MEdge *edges,
}
/* Edge is UV boundary if tagged as seam. */
return (edges[edge_index].flag & ME_SEAM) != 0;
return uv_seams && uv_seams[edge_index];
};
poly_edge_loop_islands_calc(totedge,
@ -1185,21 +1185,23 @@ bool BKE_mesh_calc_islands_loop_poly_edgeseam(const float (*vert_positions)[3],
const int totvert,
const MEdge *edges,
const int totedge,
const bool *uv_seams,
const MPoly *polys,
const int totpoly,
const MLoop *loops,
const int totloop,
MeshIslandStore *r_island_store)
{
UNUSED_VARS(vert_positions, totvert);
UNUSED_VARS(vert_positions, totvert, edges);
return mesh_calc_islands_loop_poly_uv(
edges, totedge, polys, totpoly, loops, totloop, nullptr, r_island_store);
totedge, uv_seams, polys, totpoly, loops, totloop, nullptr, r_island_store);
}
bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3],
const int totvert,
MEdge *edges,
const int totedge,
const bool *uv_seams,
MPoly *polys,
const int totpoly,
MLoop *loops,
@ -1207,10 +1209,10 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3],
const float (*luvs)[2],
MeshIslandStore *r_island_store)
{
UNUSED_VARS(vert_positions, totvert);
UNUSED_VARS(vert_positions, totvert, edges);
BLI_assert(luvs != nullptr);
return mesh_calc_islands_loop_poly_uv(
edges, totedge, polys, totpoly, loops, totloop, luvs, r_island_store);
totedge, uv_seams, polys, totpoly, loops, totloop, luvs, r_island_store);
}
/** \} */

View File

@ -126,13 +126,8 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
(axis == 1 && mmd->flag & MOD_MIR_BISECT_AXIS_Y) ||
(axis == 2 && mmd->flag & MOD_MIR_BISECT_AXIS_Z));
Mesh *result;
MEdge *me;
MLoop *ml;
MPoly *mp;
float mtx[4][4];
float plane_co[3], plane_no[3];
int i;
int a, totshape;
int *vtmap_a = nullptr, *vtmap_b = nullptr;
@ -189,43 +184,41 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
mesh = mesh_bisect;
}
const int maxVerts = mesh->totvert;
const int maxEdges = mesh->totedge;
const int maxLoops = mesh->totloop;
const int maxPolys = mesh->totpoly;
const int src_verts_num = mesh->totvert;
const int src_edges_num = mesh->totedge;
const blender::Span<MPoly> src_polys = mesh->polys();
const int src_loops_num = mesh->totloop;
result = BKE_mesh_new_nomain_from_template(
mesh, maxVerts * 2, maxEdges * 2, maxLoops * 2, maxPolys * 2);
Mesh *result = BKE_mesh_new_nomain_from_template(
mesh, src_verts_num * 2, src_edges_num * 2, src_loops_num * 2, src_polys.size() * 2);
/* Copy custom-data to original geometry. */
CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, maxVerts);
CustomData_copy_data(&mesh->edata, &result->edata, 0, 0, maxEdges);
CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, maxLoops);
CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, maxPolys);
CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, src_verts_num);
CustomData_copy_data(&mesh->edata, &result->edata, 0, 0, src_edges_num);
CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, src_polys.size());
CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, src_loops_num);
/* Copy custom-data to new geometry,
* copy from itself because this data may have been created in the checks above. */
CustomData_copy_data(&result->vdata, &result->vdata, 0, maxVerts, maxVerts);
CustomData_copy_data(&result->edata, &result->edata, 0, maxEdges, maxEdges);
/* loops are copied later */
CustomData_copy_data(&result->pdata, &result->pdata, 0, maxPolys, maxPolys);
/* Copy custom data to mirrored geometry. Loops are copied later. */
CustomData_copy_data(&mesh->vdata, &result->vdata, 0, src_verts_num, src_verts_num);
CustomData_copy_data(&mesh->edata, &result->edata, 0, src_edges_num, src_edges_num);
CustomData_copy_data(&mesh->pdata, &result->pdata, 0, src_polys.size(), src_polys.size());
if (do_vtargetmap) {
/* second half is filled with -1 */
*r_vert_merge_map = static_cast<int *>(
MEM_malloc_arrayN(maxVerts, sizeof(int[2]), "MOD_mirror tarmap"));
MEM_malloc_arrayN(src_verts_num, sizeof(int[2]), "MOD_mirror tarmap"));
vtmap_a = *r_vert_merge_map;
vtmap_b = *r_vert_merge_map + maxVerts;
vtmap_b = *r_vert_merge_map + src_verts_num;
*r_vert_merge_map_len = 0;
}
/* mirror vertex coordinates */
float(*positions)[3] = BKE_mesh_vert_positions_for_write(result);
for (i = 0; i < maxVerts; i++) {
for (int i = 0; i < src_verts_num; i++) {
const int vert_index_prev = i;
const int vert_index = maxVerts + i;
const int vert_index = src_verts_num + i;
mul_m4_v3(mtx, positions[vert_index]);
if (do_vtargetmap) {
@ -262,7 +255,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
else {
if (UNLIKELY(len_squared_v3v3(positions[vert_index_prev], positions[vert_index]) <
tolerance_sq)) {
*vtmap_a = maxVerts + i;
*vtmap_a = src_verts_num + i;
(*r_vert_merge_map_len)++;
/* average location */
@ -287,53 +280,52 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
for (a = 0; a < totshape; a++) {
float(*cos)[3] = static_cast<float(*)[3]>(
CustomData_get_layer_n_for_write(&result->vdata, CD_SHAPEKEY, a, result->totvert));
for (i = maxVerts; i < result->totvert; i++) {
for (int i = src_verts_num; i < result->totvert; i++) {
mul_m4_v3(mtx, cos[i]);
}
}
blender::MutableSpan<MEdge> result_edges = result->edges_for_write();
blender::MutableSpan<MPoly> result_polys = result->polys_for_write();
blender::MutableSpan<MLoop> result_loops = result->loops_for_write();
/* adjust mirrored edge vertex indices */
me = result->edges_for_write().data() + maxEdges;
for (i = 0; i < maxEdges; i++, me++) {
me->v1 += maxVerts;
me->v2 += maxVerts;
for (const int i : result_edges.index_range().drop_front(src_edges_num)) {
result_edges[i].v1 += src_verts_num;
result_edges[i].v2 += src_verts_num;
}
/* adjust mirrored poly loopstart indices, and reverse loop order (normals) */
mp = result->polys_for_write().data() + maxPolys;
ml = BKE_mesh_loops_for_write(result);
for (i = 0; i < maxPolys; i++, mp++) {
MLoop *ml2;
int j, e;
for (const int i : result_polys.index_range().drop_front(src_polys.size())) {
result_polys[i].loopstart += src_loops_num;
}
/* reverse loop order (normals) */
for (const int i : src_polys.index_range()) {
const blender::IndexRange src_poly(src_polys[i].loopstart, src_polys[i].totloop);
const int mirror_i = src_polys.size() + i;
const blender::IndexRange mirror_poly(result_polys[mirror_i].loopstart,
result_polys[mirror_i].totloop);
/* reverse the loop, but we keep the first vertex in the face the same,
* to ensure that quads are split the same way as on the other side */
CustomData_copy_data(
&result->ldata, &result->ldata, mp->loopstart, mp->loopstart + maxLoops, 1);
CustomData_copy_data(&mesh->ldata, &result->ldata, src_poly.start(), mirror_poly.start(), 1);
for (j = 1; j < mp->totloop; j++) {
CustomData_copy_data(&result->ldata,
&result->ldata,
mp->loopstart + j,
mp->loopstart + maxLoops + mp->totloop - j,
1);
for (int j = 1; j < mirror_poly.size(); j++) {
CustomData_copy_data(&mesh->ldata, &result->ldata, src_poly[j], mirror_poly.last(j - 1), 1);
}
ml2 = ml + mp->loopstart + maxLoops;
e = ml2[0].e;
for (j = 0; j < mp->totloop - 1; j++) {
ml2[j].e = ml2[j + 1].e;
blender::MutableSpan<MLoop> mirror_loops = result_loops.slice(mirror_poly);
const int e = mirror_loops.first().e;
for (int j = 0; j < mirror_poly.size() - 1; j++) {
mirror_loops[j].e = mirror_loops[j + 1].e;
}
ml2[mp->totloop - 1].e = e;
mp->loopstart += maxLoops;
mirror_loops.last().e = e;
}
/* adjust mirrored loop vertex and edge indices */
ml = BKE_mesh_loops_for_write(result) + maxLoops;
for (i = 0; i < maxLoops; i++, ml++) {
ml->v += maxVerts;
ml->e += maxEdges;
for (const int i : result_loops.index_range().drop_front(src_loops_num)) {
result_loops[i].v += src_verts_num;
result_loops[i].e += src_edges_num;
}
/* handle uvs,
@ -350,7 +342,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
for (a = 0; a < totuv; a++) {
float(*dmloopuv)[2] = static_cast<float(*)[2]>(
CustomData_get_layer_n_for_write(&result->ldata, CD_PROP_FLOAT2, a, result->totloop));
int j = maxLoops;
int j = src_loops_num;
dmloopuv += j; /* second set of loops only */
for (; j-- > 0; dmloopuv++) {
if (do_mirr_u) {
@ -379,14 +371,12 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
/* handle custom split normals */
if (ob->type == OB_MESH && (((Mesh *)ob->data)->flag & ME_AUTOSMOOTH) &&
CustomData_has_layer(&result->ldata, CD_CUSTOMLOOPNORMAL)) {
const int totloop = result->totloop;
const int totpoly = result->totpoly;
CustomData_has_layer(&result->ldata, CD_CUSTOMLOOPNORMAL) && result->totpoly > 0) {
float(*loop_normals)[3] = static_cast<float(*)[3]>(
MEM_calloc_arrayN(size_t(totloop), sizeof(*loop_normals), __func__));
MEM_calloc_arrayN(size_t(result->totloop), sizeof(*loop_normals), __func__));
CustomData *ldata = &result->ldata;
short(*clnors)[2] = static_cast<short(*)[2]>(
CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, totloop));
CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, result->totloop));
MLoopNorSpaceArray lnors_spacearr = {nullptr};
/* The transform matrix of a normal must be
@ -398,35 +388,34 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
/* calculate custom normals into loop_normals, then mirror first half into second half */
const bool *sharp_edges = static_cast<const bool *>(
CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge"));
CustomData_get_layer_named(&result->edata, CD_PROP_BOOL, "sharp_edge"));
BKE_mesh_normals_loop_split(BKE_mesh_vert_positions(result),
BKE_mesh_vert_normals_ensure(result),
result->totvert,
result->edges().data(),
result->totedge,
result->loops().data(),
result_edges.data(),
result_edges.size(),
result_loops.data(),
loop_normals,
totloop,
result->polys().data(),
result_loops.size(),
result_polys.data(),
BKE_mesh_poly_normals_ensure(result),
totpoly,
result_polys.size(),
true,
mesh->smoothresh,
result->smoothresh,
sharp_edges,
nullptr,
&lnors_spacearr,
clnors);
/* mirroring has to account for loops being reversed in polys in second half */
blender::MutableSpan<MPoly> result_polys = result->polys_for_write();
for (i = 0; i < maxPolys; i++) {
const int mirror_i = maxPolys + i;
int j;
for (const int i : src_polys.index_range()) {
const blender::IndexRange src_poly(src_polys[i].loopstart, src_polys[i].totloop);
const int mirror_i = src_polys.size() + i;
for (j = mp->loopstart; j < mp->loopstart + mp->totloop; j++) {
for (const int j : src_poly) {
int mirrorj = result_polys[mirror_i].loopstart;
if (j > mp->loopstart) {
mirrorj += result_polys[mirror_i].totloop - (j - mp->loopstart);
if (j > src_poly.start()) {
mirrorj += result_polys[mirror_i].totloop - (j - src_poly.start());
}
copy_v3_v3(loop_normals[mirrorj], loop_normals[j]);
mul_m4_v3(mtx_nor, loop_normals[mirrorj]);
@ -442,15 +431,15 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
/* handle vgroup stuff */
if (BKE_object_supports_vertex_groups(ob)) {
if ((mmd->flag & MOD_MIR_VGROUP) && CustomData_has_layer(&result->vdata, CD_MDEFORMVERT)) {
MDeformVert *dvert = BKE_mesh_deform_verts_for_write(result) + maxVerts;
MDeformVert *dvert = BKE_mesh_deform_verts_for_write(result) + src_verts_num;
int flip_map_len = 0;
int *flip_map = BKE_object_defgroup_flip_map(ob, false, &flip_map_len);
if (flip_map) {
for (i = 0; i < maxVerts; dvert++, i++) {
for (int i = 0; i < src_verts_num; dvert++, i++) {
/* merged vertices get both groups, others get flipped */
if (use_correct_order_on_merge && do_vtargetmap &&
((*r_vert_merge_map)[i + maxVerts] != -1)) {
BKE_defvert_flip_merged(dvert - maxVerts, flip_map, flip_map_len);
((*r_vert_merge_map)[i + src_verts_num] != -1)) {
BKE_defvert_flip_merged(dvert - src_verts_num, flip_map, flip_map_len);
}
else if (!use_correct_order_on_merge && do_vtargetmap &&
((*r_vert_merge_map)[i] != -1)) {

View File

@ -1252,8 +1252,6 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
const float full_weight = 1.0f;
const float max_dist_sq = max_dist * max_dist;
int i;
BLI_assert(mode & MREMAP_MODE_LOOP);
BLI_assert((islands_precision_src >= 0.0f) && (islands_precision_src <= 1.0f));
@ -1262,7 +1260,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
if (mode == MREMAP_MODE_TOPOLOGY) {
/* In topology mapping, we assume meshes are identical, islands included! */
BLI_assert(numloops_dst == me_src->totloop);
for (i = 0; i < numloops_dst; i++) {
for (int i = 0; i < numloops_dst; i++) {
mesh_remap_item_define(r_map, i, FLT_MAX, 0, 1, &i, &full_weight);
}
}
@ -1311,8 +1309,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
const blender::Span<MEdge> edges_src = me_src->edges();
const blender::Span<MPoly> polys_src = me_src->polys();
const blender::Span<MLoop> loops_src = me_src->loops();
const MLoopTri *looptri_src = nullptr;
int num_looptri_src = 0;
blender::Span<MLoopTri> looptris_src;
size_t buff_size_interp = MREMAP_DEFAULT_BUFSIZE;
float(*vcos_interp)[3] = nullptr;
@ -1447,10 +1444,13 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
/* First, generate the islands, if possible. */
if (gen_islands_src) {
const bool *uv_seams = static_cast<const bool *>(
CustomData_get_layer_named(&me_src->edata, CD_PROP_BOOL, ".uv_seam"));
use_islands = gen_islands_src(positions_src,
num_verts_src,
edges_src.data(),
int(edges_src.size()),
uv_seams,
polys_src.data(),
int(polys_src.size()),
loops_src.data(),
@ -1506,7 +1506,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
MeshElemMap *isld = island_store.islands[tindex];
int num_verts_active = 0;
verts_active.fill(false);
for (i = 0; i < isld->count; i++) {
for (int i = 0; i < isld->count; i++) {
const MPoly &poly = polys_src[isld->indices[i]];
for (lidx_src = poly.loopstart; lidx_src < poly.loopstart + poly.totloop; lidx_src++) {
const uint vidx_src = loops_src[lidx_src].v;
@ -1533,16 +1533,14 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
}
else { /* We use polygons. */
if (use_islands) {
/* bvhtree here uses looptri faces... */
looptri_src = BKE_mesh_runtime_looptri_ensure(me_src);
num_looptri_src = BKE_mesh_runtime_looptri_len(me_src);
blender::BitVector<> looptri_active(num_looptri_src);
looptris_src = me_src->looptris();
blender::BitVector<> looptri_active(looptris_src.size());
for (tindex = 0; tindex < num_trees; tindex++) {
int num_looptri_active = 0;
looptri_active.fill(false);
for (i = 0; i < num_looptri_src; i++) {
const MPoly &poly = polys_src[looptri_src[i].poly];
for (const int64_t i : looptris_src.index_range()) {
const MPoly &poly = polys_src[looptris_src[i].poly];
if (island_store.items_to_islands[poly.loopstart] == tindex) {
looptri_active[i].set();
num_looptri_active++;
@ -1551,8 +1549,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
bvhtree_from_mesh_looptri_ex(&treedata[tindex],
positions_src,
loops_src.data(),
looptri_src,
num_looptri_src,
looptris_src.data(),
int(looptris_src.size()),
looptri_active,
num_looptri_active,
0.0,
@ -1636,7 +1634,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
vert_to_refelem_map_src = vert_to_poly_map_src;
}
for (i = vert_to_refelem_map_src[nearest.index].count; i--;) {
for (int i = vert_to_refelem_map_src[nearest.index].count; i--;) {
const int index_src = vert_to_refelem_map_src[nearest.index].indices[i];
BLI_assert(index_src != -1);
const float dot = dot_v3v3(nors_src[index_src], *nor_dst);
@ -1881,7 +1879,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
*/
int last_valid_pidx_isld_src = -1;
/* Note we go backward here, from dest to src poly. */
for (i = as_solution.steps - 1; i--;) {
for (int i = as_solution.steps - 1; i--;) {
BLI_AStarGNLink *as_link = as_solution.prev_links[pidx_isld_src];
const int eidx = POINTER_AS_INT(as_link->custom_data);
pidx_isld_src = as_solution.prev_nodes[pidx_isld_src];
@ -1973,7 +1971,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
*/
int last_valid_pidx_isld_src = -1;
/* Note we go backward here, from dest to src poly. */
for (i = as_solution.steps - 1; i--;) {
for (int i = as_solution.steps - 1; i--;) {
BLI_AStarGNLink *as_link = as_solution.prev_links[pidx_isld_src];
int eidx = POINTER_AS_INT(as_link->custom_data);
@ -2008,14 +2006,14 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
&poly_to_looptri_map_src_buff,
polys_src.data(),
int(polys_src.size()),
looptri_src,
num_looptri_src);
looptris_src.data(),
int(looptris_src.size()));
}
for (j = poly_to_looptri_map_src[pidx_src].count; j--;) {
float h[3];
const MLoopTri *lt =
&looptri_src[poly_to_looptri_map_src[pidx_src].indices[j]];
&looptris_src[poly_to_looptri_map_src[pidx_src].indices[j]];
float dist_sq;
closest_on_tri_to_point_v3(h,

View File

@ -65,15 +65,14 @@ static Mesh *remesh_quadriflow(const Mesh *input_mesh,
{
const Span<float3> input_positions = input_mesh->vert_positions();
const Span<MLoop> input_loops = input_mesh->loops();
const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(input_mesh);
const Span<MLoopTri> looptris = input_mesh->looptris();
/* Gather the required data for export to the internal quadriflow mesh format. */
MVertTri *verttri = (MVertTri *)MEM_callocN(
sizeof(*verttri) * BKE_mesh_runtime_looptri_len(input_mesh), "remesh_looptri");
Array<MVertTri> verttri(looptris.size());
BKE_mesh_runtime_verttri_from_looptri(
verttri, input_loops.data(), looptri, BKE_mesh_runtime_looptri_len(input_mesh));
verttri.data(), input_loops.data(), looptris.data(), looptris.size());
const int totfaces = BKE_mesh_runtime_looptri_len(input_mesh);
const int totfaces = looptris.size();
const int totverts = input_mesh->totvert;
Array<int> faces(totfaces * 3);
@ -105,8 +104,6 @@ static Mesh *remesh_quadriflow(const Mesh *input_mesh,
/* Run the remesher */
QFLOW_quadriflow_remesh(&qrd, update_cb, update_cb_data);
MEM_freeN(verttri);
if (qrd.out_faces == nullptr) {
/* The remeshing was canceled */
return nullptr;
@ -335,7 +332,7 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source)
const VArraySpan<int> src(src_face_sets);
MutableSpan<int> dst = dst_face_sets.span;
const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(source);
const blender::Span<MLoopTri> looptris = source->looptris();
BVHTreeFromMesh bvhtree = {nullptr};
BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_LOOPTRI, 2);
@ -353,7 +350,7 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source)
BLI_bvhtree_find_nearest(
bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
if (nearest.index != -1) {
dst[i] = src[looptri[nearest.index].poly];
dst[i] = src[looptris[nearest.index].poly];
}
else {
dst[i] = 1;

View File

@ -574,14 +574,15 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
int tangent_names_len)
{
/* TODO(@ideasman42): store in Mesh.runtime to avoid recalculation. */
const blender::Span<MLoopTri> looptris = me_eval->looptris();
short tangent_mask = 0;
BKE_mesh_calc_loop_tangent_ex(
BKE_mesh_vert_positions(me_eval),
me_eval->polys().data(),
uint(me_eval->totpoly),
me_eval->loops().data(),
BKE_mesh_runtime_looptri_ensure(me_eval),
uint(BKE_mesh_runtime_looptri_len(me_eval)),
looptris.data(),
uint(looptris.size()),
&me_eval->ldata,
calc_active_tangent,
tangent_names,

View File

@ -329,7 +329,7 @@ static void movieclip_blend_read_data(BlendDataReader *reader, ID *id)
BLI_listbase_clear(&clip->runtime.gputextures);
/* Needed for proper versioning, will be NULL for all newer files anyway. */
BLO_read_data_address(reader, &clip->tracking.stabilization.rot_track);
BLO_read_data_address(reader, &clip->tracking.stabilization.rot_track_legacy);
clip->tracking.dopesheet.ok = 0;
BLI_listbase_clear(&clip->tracking.dopesheet.channels);

View File

@ -231,15 +231,14 @@ static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh)
data->edge_is_boundary = edge_is_boundary;
/* Build the boundary looptri bitmask. */
const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
int totlooptri = BKE_mesh_runtime_looptri_len(mesh);
const blender::Span<MLoopTri> looptris = mesh->looptris();
BLI_bitmap *looptri_has_boundary = BLI_BITMAP_NEW(totlooptri,
BLI_bitmap *looptri_has_boundary = BLI_BITMAP_NEW(looptris.size(),
"ShrinkwrapBoundaryData::looptri_is_boundary");
for (int i = 0; i < totlooptri; i++) {
for (const int64_t i : looptris.index_range()) {
int real_edges[3];
BKE_mesh_looptri_get_real_edges(edges.data(), loops.data(), &mlooptri[i], real_edges);
BKE_mesh_looptri_get_real_edges(edges.data(), loops.data(), &looptris[i], real_edges);
for (int j = 0; j < 3; j++) {
if (real_edges[j] >= 0 && edge_mode[real_edges[j]]) {

View File

@ -911,11 +911,10 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, float (*r_positions)[3])
}
/* utility function */
BLI_INLINE void ccgDM_to_MEdge(MEdge *med, const int v1, const int v2, const short flag)
BLI_INLINE void ccgDM_to_MEdge(MEdge *med, const int v1, const int v2)
{
med->v1 = v1;
med->v2 = v2;
med->flag = flag;
}
static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
@ -927,7 +926,6 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
int gridSize = ccgSubSurf_getGridSize(ss);
int edgeSize = ccgSubSurf_getEdgeSize(ss);
uint i = 0;
short *edgeFlags = ccgdm->edgeFlags;
totface = ccgSubSurf_getNumFaces(ss);
for (index = 0; index < totface; index++) {
@ -938,20 +936,17 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
for (x = 0; x < gridSize - 1; x++) {
ccgDM_to_MEdge(&medge[i++],
getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize),
getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize),
0);
getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize));
}
for (x = 1; x < gridSize - 1; x++) {
for (y = 0; y < gridSize - 1; y++) {
ccgDM_to_MEdge(&medge[i++],
getFaceIndex(ss, f, S, x, y, edgeSize, gridSize),
getFaceIndex(ss, f, S, x, y + 1, edgeSize, gridSize),
0);
getFaceIndex(ss, f, S, x, y + 1, edgeSize, gridSize));
ccgDM_to_MEdge(&medge[i++],
getFaceIndex(ss, f, S, y, x, edgeSize, gridSize),
getFaceIndex(ss, f, S, y + 1, x, edgeSize, gridSize),
0);
getFaceIndex(ss, f, S, y + 1, x, edgeSize, gridSize));
}
}
}
@ -960,21 +955,9 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
totedge = ccgSubSurf_getNumEdges(ss);
for (index = 0; index < totedge; index++) {
CCGEdge *e = ccgdm->edgeMap[index].edge;
short ed_flag = 0;
int x;
int edgeIdx = POINTER_AS_INT(ccgSubSurf_getEdgeEdgeHandle(e));
if (edgeFlags) {
if (edgeIdx != -1) {
ed_flag |= (edgeFlags[index] & ME_SEAM);
}
}
for (x = 0; x < edgeSize - 1; x++) {
ccgDM_to_MEdge(&medge[i++],
getEdgeIndex(ss, e, x, edgeSize),
getEdgeIndex(ss, e, x + 1, edgeSize),
ed_flag);
for (int x = 0; x < edgeSize - 1; x++) {
ccgDM_to_MEdge(
&medge[i++], getEdgeIndex(ss, e, x, edgeSize), getEdgeIndex(ss, e, x + 1, edgeSize));
}
}
}
@ -1170,7 +1153,6 @@ static void ccgDM_release(DerivedMesh *dm)
if (ccgdm->pmap_mem) {
MEM_freeN(ccgdm->pmap_mem);
}
MEM_freeN(ccgdm->edgeFlags);
MEM_freeN(ccgdm->faceFlags);
MEM_freeN(ccgdm->vertMap);
MEM_freeN(ccgdm->edgeMap);
@ -1539,7 +1521,6 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
int index;
int i;
int vertNum = 0, edgeNum = 0, faceNum = 0;
short *edgeFlags = ccgdm->edgeFlags;
DMFlagMat *faceFlags = ccgdm->faceFlags;
int *polyidx = nullptr;
blender::Vector<int, 16> loopidx;
@ -1551,7 +1532,6 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
int gridSideEdges;
int gridInternalEdges;
WeightTable wtable = {nullptr};
MEdge *medge = nullptr;
bool has_edge_cd;
edgeSize = ccgSubSurf_getEdgeSize(ss);
@ -1562,8 +1542,6 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
gridSideEdges = gridSize - 1;
gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
medge = dm->getEdgeArray(dm);
const MPoly *mpoly = static_cast<const MPoly *>(CustomData_get_layer(&dm->polyData, CD_MPOLY));
const int *material_indices = static_cast<const int *>(
CustomData_get_layer_named(&dm->polyData, CD_MPOLY, "material_index"));
@ -1742,10 +1720,6 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
ccgdm->edgeMap[index].startVert = vertNum;
ccgdm->edgeMap[index].startEdge = edgeNum;
if (edgeIdx >= 0 && edgeFlags) {
edgeFlags[edgeIdx] = medge[edgeIdx].flag;
}
/* set the edge base vert */
*((int *)ccgSubSurf_getEdgeUserData(ss, e)) = vertNum;
@ -1827,6 +1801,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
CCGDerivedMesh *ccgdm = MEM_cnew<CCGDerivedMesh>(__func__);
BLI_assert(totedge == ccgSubSurf_getNumEdges(ss));
UNUSED_VARS_NDEBUG(totedge);
BLI_assert(totface == ccgSubSurf_getNumFaces(ss));
DM_from_template(&ccgdm->dm,
dm,
@ -1849,7 +1824,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
ccgdm->useSubsurfUv = useSubsurfUv;
/* CDDM hack. */
ccgdm->edgeFlags = static_cast<short *>(MEM_callocN(sizeof(short) * totedge, "edgeFlags"));
ccgdm->faceFlags = static_cast<DMFlagMat *>(
MEM_callocN(sizeof(DMFlagMat) * totface, "faceFlags"));

View File

@ -136,6 +136,8 @@ void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1);
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1);
/**
* Removes \a vlink from \a listbase. Assumes it is linked into there!
*
* \warning Does _not_ clear the `prev`/`next` pointers of the removed `vlink`.
*/
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1);
/**

View File

@ -178,6 +178,8 @@ set(SRC
BLI_assert.h
BLI_astar.h
BLI_atomic_disjoint_set.hh
BLI_bit_ref.hh
BLI_bit_span.hh
BLI_bit_vector.hh
BLI_bitmap.h
BLI_bitmap_draw_2d.h

View File

@ -288,6 +288,26 @@ struct LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh);
*/
void BLO_blendhandle_close(BlendHandle *bh);
/** Mark the given Main (and the 'root' local one in case of lib-split Mains) as invalid, and
* generate an error report containing given `message`. */
void BLO_read_invalidate_message(BlendHandle *bh, struct Main *bmain, const char *message);
/**
* BLI_assert-like macro to check a condition, and if `false`, fail the whole .blend reading
* process by marking the Main data-base as invalid, and returning provided `_ret_value`.
*
* NOTE: About usages:
* - #BLI_assert should be used when the error is considered as a bug, but there is some code to
* recover from it and produce a valid Main data-base.
* - #BLO_read_assert_message should be used when the error is not considered as recoverable.
*/
#define BLO_read_assert_message(_check_expr, _ret_value, _bh, _bmain, _message) \
if (_check_expr) { \
BLO_read_invalidate_message((_bh), (_bmain), (_message)); \
return _ret_value; \
} \
(void)0
/** \} */
#define BLO_GROUP_MAX 32

View File

@ -385,6 +385,13 @@ void BLO_blendhandle_close(BlendHandle *bh)
blo_filedata_free(fd);
}
void BLO_read_invalidate_message(BlendHandle *bh, Main *bmain, const char *message)
{
FileData *fd = reinterpret_cast<FileData *>(bh);
blo_readfile_invalidate(fd, bmain, message);
}
/**********/
BlendFileData *BLO_read_from_file(const char *filepath,

View File

@ -320,6 +320,10 @@ static void add_main_to_main(Main *mainvar, Main *from)
ListBase *lbarray[INDEX_ID_MAX], *fromarray[INDEX_ID_MAX];
int a;
if (from->is_read_invalid) {
mainvar->is_read_invalid = true;
}
set_listbasepointers(mainvar, lbarray);
a = set_listbasepointers(from, fromarray);
while (a--) {
@ -342,6 +346,7 @@ void blo_join_main(ListBase *mainlist)
while ((tojoin = mainl->next)) {
add_main_to_main(mainl, tojoin);
BLI_remlink(mainlist, tojoin);
tojoin->next = tojoin->prev = nullptr;
BKE_main_free(tojoin);
}
}
@ -548,6 +553,21 @@ static Main *blo_find_main(FileData *fd, const char *filepath, const char *relab
return m;
}
void blo_readfile_invalidate(FileData *fd, Main *bmain, const char *message)
{
/* Tag given bmain, and 'root 'local' main one (in case given one is a library one) as invalid.
*/
bmain->is_read_invalid = true;
for (; bmain->prev != nullptr; bmain = bmain->prev)
;
bmain->is_read_invalid = true;
BLO_reportf_wrap(fd->reports,
RPT_ERROR,
"A critical error happened (the blend file is likely corrupted): %s",
message);
}
/** \} */
/* -------------------------------------------------------------------- */
@ -3564,15 +3584,33 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
main->build_hash);
}
blo_do_versions_pre250(fd, lib, main);
blo_do_versions_250(fd, lib, main);
blo_do_versions_260(fd, lib, main);
blo_do_versions_270(fd, lib, main);
blo_do_versions_280(fd, lib, main);
blo_do_versions_290(fd, lib, main);
blo_do_versions_300(fd, lib, main);
blo_do_versions_400(fd, lib, main);
blo_do_versions_cycles(fd, lib, main);
if (!main->is_read_invalid) {
blo_do_versions_pre250(fd, lib, main);
}
if (!main->is_read_invalid) {
blo_do_versions_250(fd, lib, main);
}
if (!main->is_read_invalid) {
blo_do_versions_260(fd, lib, main);
}
if (!main->is_read_invalid) {
blo_do_versions_270(fd, lib, main);
}
if (!main->is_read_invalid) {
blo_do_versions_280(fd, lib, main);
}
if (!main->is_read_invalid) {
blo_do_versions_290(fd, lib, main);
}
if (!main->is_read_invalid) {
blo_do_versions_300(fd, lib, main);
}
if (!main->is_read_invalid) {
blo_do_versions_400(fd, lib, main);
}
if (!main->is_read_invalid) {
blo_do_versions_cycles(fd, lib, main);
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */
@ -3582,7 +3620,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
main->is_locked_for_linking = false;
}
static void do_versions_after_linking(Main *main, ReportList *reports)
static void do_versions_after_linking(FileData *fd, Main *main)
{
CLOG_INFO(&LOG,
2,
@ -3595,13 +3633,27 @@ static void do_versions_after_linking(Main *main, ReportList *reports)
/* Don't allow versioning to create new data-blocks. */
main->is_locked_for_linking = true;
do_versions_after_linking_250(main);
do_versions_after_linking_260(main);
do_versions_after_linking_270(main);
do_versions_after_linking_280(main, reports);
do_versions_after_linking_290(main, reports);
do_versions_after_linking_300(main, reports);
do_versions_after_linking_cycles(main);
if (!main->is_read_invalid) {
do_versions_after_linking_250(main);
}
if (!main->is_read_invalid) {
do_versions_after_linking_260(main);
}
if (!main->is_read_invalid) {
do_versions_after_linking_270(main);
}
if (!main->is_read_invalid) {
do_versions_after_linking_280(fd, main);
}
if (!main->is_read_invalid) {
do_versions_after_linking_290(fd, main);
}
if (!main->is_read_invalid) {
do_versions_after_linking_300(fd, main);
}
if (!main->is_read_invalid) {
do_versions_after_linking_cycles(main);
}
main->is_locked_for_linking = false;
}
@ -3810,6 +3862,9 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
static void blo_read_file_checks(Main *bmain)
{
#ifndef NDEBUG
BLI_assert(bmain->next == nullptr);
BLI_assert(!bmain->is_read_invalid);
LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) {
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
/* This pointer is deprecated and should always be nullptr. */
@ -3914,6 +3969,10 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
bhead = read_libblock(fd, bfd->main, bhead, LIB_TAG_LOCAL, false, nullptr);
}
}
if (bfd->main->is_read_invalid) {
return bfd;
}
}
/* do before read_libraries, but skip undo case */
@ -3927,6 +3986,10 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
}
}
if (bfd->main->is_read_invalid) {
return bfd;
}
if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) {
fd->reports->duration.libraries = PIL_check_seconds_timer();
read_libraries(fd, &mainlist);
@ -3953,7 +4016,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
blo_split_main(&mainlist, bfd->main);
LISTBASE_FOREACH (Main *, mainvar, &mainlist) {
BLI_assert(mainvar->versionfile != 0);
do_versions_after_linking(mainvar, fd->reports->reports);
do_versions_after_linking(fd, mainvar);
}
blo_join_main(&mainlist);
@ -3963,6 +4026,10 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
BKE_main_id_refcount_recompute(bfd->main, false);
}
if (bfd->main->is_read_invalid) {
return bfd;
}
/* After all data has been read and versioned, uses LIB_TAG_NEW. Theoretically this should
* not be calculated in the undo case, but it is currently needed even on undo to recalculate
* a cache. */
@ -4174,6 +4241,10 @@ static void expand_doit_library(void *fdhandle, Main *mainvar, void *old)
{
FileData *fd = static_cast<FileData *>(fdhandle);
if (mainvar->is_read_invalid) {
return;
}
BHead *bhead = find_bhead(fd, old);
if (bhead == nullptr) {
return;
@ -4432,7 +4503,16 @@ ID *BLO_library_link_named_part(Main *mainl,
const LibraryLink_Params *params)
{
FileData *fd = (FileData *)(*bh);
return link_named_part(mainl, fd, idcode, name, params->flag);
ID *ret_id = nullptr;
if (!mainl->is_read_invalid) {
ret_id = link_named_part(mainl, fd, idcode, name, params->flag);
}
if (mainl->is_read_invalid) {
return nullptr;
}
return ret_id;
}
/* common routine to append/link something from a library */
@ -4562,6 +4642,10 @@ static void library_link_end(Main *mainl, FileData **fd, const int flag)
mainvar = static_cast<Main *>((*fd)->mainlist->first);
mainl = nullptr; /* blo_join_main free's mainl, can't use anymore */
if (mainvar->is_read_invalid) {
return;
}
lib_link_all(*fd, mainvar);
after_liblink_merged_bmain_process(mainvar);
@ -4582,15 +4666,24 @@ static void library_link_end(Main *mainl, FileData **fd, const int flag)
* or they will go again through do_versions - bad, very bad! */
split_main_newid(mainvar, main_newid);
do_versions_after_linking(main_newid, (*fd)->reports->reports);
do_versions_after_linking(*fd, main_newid);
add_main_to_main(mainvar, main_newid);
if (mainvar->is_read_invalid) {
break;
}
}
blo_join_main((*fd)->mainlist);
mainvar = static_cast<Main *>((*fd)->mainlist->first);
MEM_freeN((*fd)->mainlist);
if (mainvar->is_read_invalid) {
BKE_main_free(main_newid);
return;
}
/* This does not take into account old, deprecated data, so we also have to do it after
* `do_versions_after_linking()`. */
BKE_main_id_refcount_recompute(mainvar, false);
@ -4631,9 +4724,12 @@ static void library_link_end(Main *mainl, FileData **fd, const int flag)
void BLO_library_link_end(Main *mainl, BlendHandle **bh, const LibraryLink_Params *params)
{
FileData *fd = (FileData *)(*bh);
library_link_end(mainl, &fd, params->flag);
*bh = (BlendHandle *)fd;
FileData *fd = reinterpret_cast<FileData *>(*bh);
if (!mainl->is_read_invalid) {
library_link_end(mainl, &fd, params->flag);
*bh = reinterpret_cast<BlendHandle *>(fd);
}
}
void *BLO_library_read_struct(FileData *fd, BHead *bh, const char *blockname)

View File

@ -219,9 +219,9 @@ void blo_do_versions_cycles(struct FileData *fd, struct Library *lib, struct Mai
void do_versions_after_linking_250(struct Main *bmain);
void do_versions_after_linking_260(struct Main *bmain);
void do_versions_after_linking_270(struct Main *bmain);
void do_versions_after_linking_280(struct Main *bmain, struct ReportList *reports);
void do_versions_after_linking_290(struct Main *bmain, struct ReportList *reports);
void do_versions_after_linking_300(struct Main *bmain, struct ReportList *reports);
void do_versions_after_linking_280(struct FileData *fd, struct Main *bmain);
void do_versions_after_linking_290(struct FileData *fd, struct Main *bmain);
void do_versions_after_linking_300(struct FileData *fd, struct Main *bmain);
void do_versions_after_linking_cycles(struct Main *bmain);
/**
@ -232,6 +232,10 @@ void do_versions_after_linking_cycles(struct Main *bmain);
*/
void *blo_read_get_new_globaldata_address(struct FileData *fd, const void *adr);
/* Mark the Main data as invalid (.blend file reading should be aborted ASAP, and the already read
* data should be discarded). Also add an error report to `fd` including given `message`. */
void blo_readfile_invalidate(struct FileData *fd, struct Main *bmain, const char *message);
#ifdef __cplusplus
}
#endif

View File

@ -456,22 +456,22 @@ static void do_versions_affine_tracker_track(MovieTrackingTrack *track)
if (is_zero_v2(marker->pattern_corners[0]) && is_zero_v2(marker->pattern_corners[1]) &&
is_zero_v2(marker->pattern_corners[2]) && is_zero_v2(marker->pattern_corners[3])) {
marker->pattern_corners[0][0] = track->pat_min[0];
marker->pattern_corners[0][1] = track->pat_min[1];
marker->pattern_corners[0][0] = track->pat_min_legacy[0];
marker->pattern_corners[0][1] = track->pat_min_legacy[1];
marker->pattern_corners[1][0] = track->pat_max[0];
marker->pattern_corners[1][1] = track->pat_min[1];
marker->pattern_corners[1][0] = track->pat_max_legacy[0];
marker->pattern_corners[1][1] = track->pat_min_legacy[1];
marker->pattern_corners[2][0] = track->pat_max[0];
marker->pattern_corners[2][1] = track->pat_max[1];
marker->pattern_corners[2][0] = track->pat_max_legacy[0];
marker->pattern_corners[2][1] = track->pat_max_legacy[1];
marker->pattern_corners[3][0] = track->pat_min[0];
marker->pattern_corners[3][1] = track->pat_max[1];
marker->pattern_corners[3][0] = track->pat_min_legacy[0];
marker->pattern_corners[3][1] = track->pat_max_legacy[1];
}
if (is_zero_v2(marker->search_min) && is_zero_v2(marker->search_max)) {
copy_v2_v2(marker->search_min, track->search_min);
copy_v2_v2(marker->search_max, track->search_max);
copy_v2_v2(marker->search_min, track->search_min_legacy);
copy_v2_v2(marker->search_max, track->search_max_legacy);
}
}
}
@ -1625,8 +1625,8 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain)
for (tracking_object = tracking->objects.first; tracking_object;
tracking_object = tracking_object->next) {
if (tracking_object->keyframe1 == 0 && tracking_object->keyframe2 == 0) {
tracking_object->keyframe1 = tracking->settings.keyframe1;
tracking_object->keyframe2 = tracking->settings.keyframe2;
tracking_object->keyframe1 = tracking->settings.keyframe1_legacy;
tracking_object->keyframe2 = tracking->settings.keyframe2_legacy;
}
}
}

View File

@ -149,13 +149,13 @@ static bGPDpalettecolor *BKE_gpencil_palettecolor_addnew(bGPDpalette *palette, c
*/
static void migrate_single_rot_stabilization_track_settings(MovieTrackingStabilization *stab)
{
if (stab->rot_track) {
if (!(stab->rot_track->flag & TRACK_USE_2D_STAB_ROT)) {
if (stab->rot_track_legacy) {
if (!(stab->rot_track_legacy->flag & TRACK_USE_2D_STAB_ROT)) {
stab->tot_rot_track++;
stab->rot_track->flag |= TRACK_USE_2D_STAB_ROT;
stab->rot_track_legacy->flag |= TRACK_USE_2D_STAB_ROT;
}
}
stab->rot_track = NULL; /* this field is now ignored */
stab->rot_track_legacy = NULL; /* this field is now ignored */
}
static void do_version_constraints_radians_degrees_270_1(ListBase *lb)
@ -1406,7 +1406,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain)
fd->filesdna, "MovieTrackingStabilization", "int", "tot_rot_track")) {
MovieClip *clip;
for (clip = bmain->movieclips.first; clip != NULL; clip = clip->id.next) {
if (clip->tracking.stabilization.rot_track) {
if (clip->tracking.stabilization.rot_track_legacy) {
migrate_single_rot_stabilization_track_settings(&clip->tracking.stabilization);
}
if (clip->tracking.stabilization.scale == 0.0f) {
@ -1420,8 +1420,6 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain)
clip->tracking.stabilization.anchor_frame = 1;
/* by default show the track lists expanded, to improve "discoverability" */
clip->tracking.stabilization.flag |= TRACKING_SHOW_STAB_TRACKS;
/* deprecated, not used anymore */
clip->tracking.stabilization.ok = false;
}
}
}

View File

@ -1171,7 +1171,7 @@ static void do_version_fcurve_hide_viewport_fix(struct ID *UNUSED(id),
fcu->rna_path = BLI_strdupn("hide_viewport", 13);
}
void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports))
void do_versions_after_linking_280(FileData *fd, Main *bmain)
{
bool use_collection_compat_28 = true;
@ -1241,6 +1241,12 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports))
if (!MAIN_VERSION_ATLEAST(bmain, 280, 0)) {
for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
BLO_read_assert_message(screen->scene == NULL,
,
(BlendHandle *)fd,
bmain,
"No Screen data-block should ever have a NULL `scene` pointer");
/* same render-layer as do_version_workspaces_after_lib_link will activate,
* so same layer as BKE_view_layer_default_view would return */
ViewLayer *layer = screen->scene->view_layers.first;

View File

@ -410,7 +410,7 @@ static void version_node_socket_duplicate(bNodeTree *ntree,
}
}
void do_versions_after_linking_290(Main *bmain, ReportList * /*reports*/)
void do_versions_after_linking_290(FileData * /*fd*/, Main *bmain)
{
if (!MAIN_VERSION_ATLEAST(bmain, 290, 1)) {
/* Patch old grease pencil modifiers material filter. */

View File

@ -939,7 +939,7 @@ static void version_geometry_nodes_primitive_uv_maps(bNodeTree &ntree)
}
}
void do_versions_after_linking_300(Main *bmain, ReportList * /*reports*/)
void do_versions_after_linking_300(FileData * /*fd*/, Main *bmain)
{
if (MAIN_VERSION_ATLEAST(bmain, 300, 0) && !MAIN_VERSION_ATLEAST(bmain, 300, 1)) {
/* Set zero user text objects to have a fake user. */

View File

@ -35,6 +35,7 @@ static void version_mesh_legacy_to_struct_of_array_format(Mesh &mesh)
BKE_mesh_legacy_sharp_edges_from_flags(&mesh);
BKE_mesh_legacy_face_set_to_generic(&mesh);
BKE_mesh_legacy_edge_crease_to_layers(&mesh);
BKE_mesh_legacy_uv_seam_from_flags(&mesh);
BKE_mesh_legacy_convert_verts_to_positions(&mesh);
BKE_mesh_legacy_attribute_flags_to_strings(&mesh);
}

View File

@ -113,21 +113,11 @@ using blender::Span;
using blender::StringRef;
using blender::Vector;
static char bm_edge_flag_from_mflag(const short mflag)
{
return ((mflag & ME_SEAM) ? BM_ELEM_SEAM : 0) | BM_ELEM_DRAW;
}
static char bm_face_flag_from_mflag(const char mflag)
{
return ((mflag & ME_SMOOTH) ? BM_ELEM_SMOOTH : 0);
}
static short bm_edge_flag_to_mflag(const BMEdge *e)
{
const char hflag = e->head.hflag;
return (hflag & BM_ELEM_SEAM) ? ME_SEAM : 0;
}
static char bm_face_flag_to_mflag(const BMFace *f)
{
const char hflag = f->head.hflag;
@ -142,6 +132,7 @@ bool BM_attribute_stored_in_bmesh_builtin(const StringRef name)
".hide_vert",
".hide_edge",
".hide_poly",
".uv_seam",
".select_vert",
".select_edge",
".select_poly",
@ -437,6 +428,8 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
&me->pdata, CD_PROP_INT32, "material_index");
const bool *sharp_edges = (const bool *)CustomData_get_layer_named(
&me->edata, CD_PROP_BOOL, "sharp_edge");
const bool *uv_seams = (const bool *)CustomData_get_layer_named(
&me->edata, CD_PROP_BOOL, ".uv_seam");
const Span<float3> positions = me->vert_positions();
Array<BMVert *> vtable(me->totvert);
@ -482,8 +475,10 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
bm, vtable[medge[i].v1], vtable[medge[i].v2], nullptr, BM_CREATE_SKIP_CD);
BM_elem_index_set(e, i); /* set_ok */
/* Transfer flags. */
e->head.hflag = bm_edge_flag_from_mflag(medge[i].flag);
e->head.hflag = 0;
if (uv_seams && uv_seams[i]) {
BM_elem_flag_enable(e, BM_ELEM_SEAM);
}
if (hide_edge && hide_edge[i]) {
BM_elem_flag_enable(e, BM_ELEM_HIDDEN);
}
@ -1258,6 +1253,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
bool need_hide_poly = false;
bool need_material_index = false;
bool need_sharp_edge = false;
bool need_uv_seam = false;
i = 0;
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
@ -1285,7 +1281,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
medge[i].v1 = BM_elem_index_get(e->v1);
medge[i].v2 = BM_elem_index_get(e->v2);
medge[i].flag = bm_edge_flag_to_mflag(e);
if (BM_elem_flag_test(e, BM_ELEM_SEAM)) {
need_uv_seam = true;
}
if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
need_hide_edge = true;
}
@ -1359,6 +1357,13 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
return !BM_elem_flag_test(BM_edge_at_index(bm, i), BM_ELEM_SMOOTH);
});
}
if (need_uv_seam) {
BM_mesh_elem_table_ensure(bm, BM_EDGE);
write_fn_to_attribute<bool>(
me->attributes_for_write(), ".uv_seam", ATTR_DOMAIN_EDGE, [&](const int i) {
return BM_elem_flag_test(BM_edge_at_index(bm, i), BM_ELEM_SEAM);
});
}
/* Patch hook indices and vertex parents. */
if (params->calc_object_remap && (ototvert > 0)) {
@ -1496,7 +1501,8 @@ static void bm_edge_table_build(BMesh &bm,
MutableSpan<const BMEdge *> table,
bool &need_select_edge,
bool &need_hide_edge,
bool &need_sharp_edge)
bool &need_sharp_edge,
bool &need_uv_seams)
{
char hflag = 0;
BMIter iter;
@ -1510,6 +1516,7 @@ static void bm_edge_table_build(BMesh &bm,
need_select_edge = (hflag & BM_ELEM_SELECT) != 0;
need_hide_edge = (hflag & BM_ELEM_HIDDEN) != 0;
need_sharp_edge = (hflag & BM_ELEM_SMOOTH) != 0;
need_uv_seams = (hflag & BM_ELEM_SEAM) != 0;
}
static void bm_face_loop_table_build(BMesh &bm,
@ -1574,7 +1581,8 @@ static void bm_to_mesh_edges(const BMesh &bm,
Mesh &mesh,
MutableSpan<bool> select_edge,
MutableSpan<bool> hide_edge,
MutableSpan<bool> sharp_edge)
MutableSpan<bool> sharp_edge,
MutableSpan<bool> uv_seams)
{
const Vector<BMeshToMeshLayerInfo> info = bm_to_mesh_copy_info_calc(bm.edata, mesh.edata);
MutableSpan<MEdge> dst_edges = mesh.edges_for_write();
@ -1584,7 +1592,6 @@ static void bm_to_mesh_edges(const BMesh &bm,
MEdge &dst_edge = dst_edges[edge_i];
dst_edge.v1 = BM_elem_index_get(src_edge.v1);
dst_edge.v2 = BM_elem_index_get(src_edge.v2);
dst_edge.flag = bm_edge_flag_to_mflag(&src_edge);
bmesh_block_copy_to_mesh_attributes(info, edge_i, src_edge.head.data);
}
if (!select_edge.is_empty()) {
@ -1602,6 +1609,11 @@ static void bm_to_mesh_edges(const BMesh &bm,
sharp_edge[edge_i] = !BM_elem_flag_test(bm_edges[edge_i], BM_ELEM_SMOOTH);
}
}
if (!uv_seams.is_empty()) {
for (const int edge_i : range) {
uv_seams[edge_i] = BM_elem_flag_test(bm_edges[edge_i], BM_ELEM_SEAM);
}
}
});
}
@ -1709,6 +1721,7 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
bool need_hide_poly = false;
bool need_material_index = false;
bool need_sharp_edge = false;
bool need_uv_seams = false;
Array<const BMVert *> vert_table;
Array<const BMEdge *> edge_table;
Array<const BMFace *> face_table;
@ -1721,7 +1734,8 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
},
[&]() {
edge_table.reinitialize(bm->totedge);
bm_edge_table_build(*bm, edge_table, need_select_edge, need_hide_edge, need_sharp_edge);
bm_edge_table_build(
*bm, edge_table, need_select_edge, need_hide_edge, need_sharp_edge, need_uv_seams);
},
[&]() {
face_table.reinitialize(bm->totface);
@ -1739,6 +1753,7 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
bke::SpanAttributeWriter<bool> select_edge;
bke::SpanAttributeWriter<bool> hide_edge;
bke::SpanAttributeWriter<bool> sharp_edge;
bke::SpanAttributeWriter<bool> uv_seams;
bke::SpanAttributeWriter<bool> select_poly;
bke::SpanAttributeWriter<bool> hide_poly;
bke::SpanAttributeWriter<int> material_index;
@ -1754,6 +1769,9 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
if (need_sharp_edge) {
sharp_edge = attrs.lookup_or_add_for_write_only_span<bool>("sharp_edge", ATTR_DOMAIN_EDGE);
}
if (need_uv_seams) {
uv_seams = attrs.lookup_or_add_for_write_only_span<bool>(".uv_seam", ATTR_DOMAIN_EDGE);
}
if (need_hide_edge) {
hide_edge = attrs.lookup_or_add_for_write_only_span<bool>(".hide_edge", ATTR_DOMAIN_EDGE);
}
@ -1773,7 +1791,13 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
me->totvert > 1024,
[&]() { bm_to_mesh_verts(*bm, vert_table, *me, select_vert.span, hide_vert.span); },
[&]() {
bm_to_mesh_edges(*bm, edge_table, *me, select_edge.span, hide_edge.span, sharp_edge.span);
bm_to_mesh_edges(*bm,
edge_table,
*me,
select_edge.span,
hide_edge.span,
sharp_edge.span,
uv_seams.span);
},
[&]() {
bm_to_mesh_faces(
@ -1786,6 +1810,7 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
select_edge.finish();
hide_edge.finish();
sharp_edge.finish();
uv_seams.finish();
select_poly.finish();
hide_poly.finish();
material_index.finish();

View File

@ -40,8 +40,7 @@ GPU_SHADER_CREATE_INFO(workbench_next_mesh)
.vertex_in(2, Type::VEC4, "ac")
.vertex_in(3, Type::VEC2, "au")
.vertex_source("workbench_prepass_vert.glsl")
.additional_info("draw_modelmat_new")
.additional_info("draw_resource_handle_new");
.additional_info("draw_modelmat_new_with_custom_id", "draw_resource_handle_new");
GPU_SHADER_CREATE_INFO(workbench_next_curves)
/* TODO Adding workbench_next_mesh to avoid shader compilation errors */

View File

@ -16,8 +16,12 @@ void main()
normal_interp = normalize(normal_object_to_view(nor));
object_id = int(uint(resource_id) & 0xFFFFu) + 1;
#ifdef WORKBENCH_NEXT
workbench_material_data_get(
int(drw_CustomID), ac.rgb, color_interp, alpha_interp, _roughness, metallic);
#else
workbench_material_data_get(
resource_handle, ac.rgb, color_interp, alpha_interp, _roughness, metallic);
object_id = int(uint(resource_handle) & 0xFFFFu) + 1;
#endif
}

View File

@ -68,6 +68,7 @@ class Instance {
resolution,
GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT |
GPU_TEXTURE_USAGE_MIP_SWIZZLE_VIEW);
resources.material_buf.clear();
opaque_ps.sync(scene_state, resources);
transparent_ps.sync(scene_state, resources);
@ -202,12 +203,8 @@ class Instance {
if (batches[i] == nullptr) {
continue;
}
/* TODO(fclem): This create a cull-able instance for each sub-object. This is done
* for simplicity to reduce complexity. But this increase the overhead per object.
* Instead, we should use an indirection buffer to the material buffer. */
ResourceHandle _handle = i == 0 ? handle : manager.resource_handle(ob_ref);
Material &mat = resources.material_buf.get_or_resize(_handle.resource_index());
Material mat;
if (::Material *_mat = BKE_object_material_get_eval(ob_ref.object, i + 1)) {
mat = Material(*_mat);
@ -225,7 +222,7 @@ class Instance {
get_material_image(ob_ref.object, i + 1, image, iuser, sampler_state);
}
draw_mesh(ob_ref, mat, batches[i], _handle, image, sampler_state, iuser);
draw_mesh(ob_ref, mat, batches[i], handle, image, sampler_state, iuser);
}
}
}
@ -247,7 +244,7 @@ class Instance {
}
if (batch) {
Material &mat = resources.material_buf.get_or_resize(handle.resource_index());
Material mat;
if (object_state.color_type == V3D_SHADING_OBJECT_COLOR) {
mat = Material(*ob_ref.object);
@ -291,9 +288,11 @@ class Instance {
ImageUser *iuser = nullptr)
{
const bool in_front = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0;
resources.material_buf.append(material);
int material_index = resources.material_buf.size() - 1;
auto draw = [&](MeshPass &pass) {
pass.draw(ob_ref, batch, handle, image, sampler_state, iuser);
pass.draw(ob_ref, batch, handle, material_index, image, sampler_state, iuser);
};
if (scene_state.xray_mode || material.is_transparent()) {

View File

@ -18,6 +18,7 @@ bool MeshPass::is_empty() const
void MeshPass::init_pass(SceneResources &resources, DRWState state, int clip_planes)
{
use_custom_ids = true;
is_empty_ = true;
PassMain::init();
state_set(state, clip_planes);
@ -57,6 +58,7 @@ void MeshPass::init_subpasses(ePipelineType pipeline,
void MeshPass::draw(ObjectRef &ref,
GPUBatch *batch,
ResourceHandle handle,
uint material_index,
::Image *image /* = nullptr */,
eGPUSamplerState sampler_state /* = GPU_SAMPLER_DEFAULT */,
ImageUser *iuser /* = nullptr */)
@ -95,11 +97,11 @@ void MeshPass::draw(ObjectRef &ref,
};
texture_subpass_map_.lookup_or_add_cb(TextureSubPassKey(texture, geometry_type), add_cb)
->draw(batch, handle);
->draw(batch, handle, material_index);
return;
}
}
passes_[int(geometry_type)][int(eShaderType::MATERIAL)]->draw(batch, handle);
passes_[int(geometry_type)][int(eShaderType::MATERIAL)]->draw(batch, handle, material_index);
}
/** \} */

View File

@ -184,6 +184,7 @@ class MeshPass : public PassMain {
void draw(ObjectRef &ref,
GPUBatch *batch,
ResourceHandle handle,
uint material_index,
::Image *image = nullptr,
eGPUSamplerState sampler_state = eGPUSamplerState::GPU_SAMPLER_DEFAULT,
ImageUser *iuser = nullptr);

View File

@ -387,7 +387,7 @@ BLI_INLINE void extract_task_range_run_iter(const MeshRenderData *mr,
int stop;
switch (iter_type) {
case MR_ITER_LOOPTRI:
range_data.elems = is_mesh ? mr->mlooptri : (void *)mr->edit_bmesh->looptris;
range_data.elems = is_mesh ? mr->looptris.data() : (void *)mr->edit_bmesh->looptris;
func = is_mesh ? extract_range_iter_looptri_mesh : extract_range_iter_looptri_bm;
stop = mr->tri_len;
break;

View File

@ -339,7 +339,7 @@ void mesh_render_data_update_looptris(MeshRenderData *mr,
if (mr->extract_type != MR_EXTRACT_BMESH) {
/* Mesh */
if ((iter_type & MR_ITER_LOOPTRI) || (data_flag & MR_DATA_LOOPTRI)) {
mr->mlooptri = BKE_mesh_runtime_looptri_ensure(mr->me);
mr->looptris = mr->me->looptris();
}
}
else {

View File

@ -600,14 +600,13 @@ void DrawCommandBuf::bind(RecordingState &state,
}
void DrawMultiBuf::bind(RecordingState &state,
Vector<Header, 0> &headers,
Vector<Undetermined, 0> &commands,
Vector<Header, 0> & /*headers*/,
Vector<Undetermined, 0> & /*commands*/,
VisibilityBuf &visibility_buf,
int visibility_word_per_draw,
int view_len)
int view_len,
bool use_custom_ids)
{
UNUSED_VARS(headers, commands);
GPU_debug_group_begin("DrawMultiBuf.bind");
resource_id_count_ = 0u;
@ -636,7 +635,7 @@ void DrawMultiBuf::bind(RecordingState &state,
group_buf_.push_update();
prototype_buf_.push_update();
/* Allocate enough for the expansion pass. */
resource_id_buf_.get_or_resize(resource_id_count_);
resource_id_buf_.get_or_resize(resource_id_count_ * (use_custom_ids ? 2 : 1));
/* Two command per group. */
command_buf_.get_or_resize(group_count_ * 2);
@ -646,6 +645,7 @@ void DrawMultiBuf::bind(RecordingState &state,
GPU_shader_uniform_1i(shader, "prototype_len", prototype_count_);
GPU_shader_uniform_1i(shader, "visibility_word_per_draw", visibility_word_per_draw);
GPU_shader_uniform_1i(shader, "view_shift", log2_ceil_u(view_len));
GPU_shader_uniform_1b(shader, "use_custom_ids", use_custom_ids);
GPU_storagebuf_bind(group_buf_, GPU_shader_get_ssbo_binding(shader, "group_buf"));
GPU_storagebuf_bind(visibility_buf, GPU_shader_get_ssbo_binding(shader, "visibility_buf"));
GPU_storagebuf_bind(prototype_buf_, GPU_shader_get_ssbo_binding(shader, "prototype_buf"));

View File

@ -433,7 +433,8 @@ class DrawCommandBuf {
uint instance_len,
uint vertex_len,
uint vertex_first,
ResourceHandle handle)
ResourceHandle handle,
uint /*custom_id*/)
{
vertex_first = vertex_first != -1 ? vertex_first : 0;
instance_len = instance_len != -1 ? instance_len : 1;
@ -533,7 +534,8 @@ class DrawMultiBuf {
uint instance_len,
uint vertex_len,
uint vertex_first,
ResourceHandle handle)
ResourceHandle handle,
uint custom_id)
{
/* Custom draw-calls cannot be batched and will produce one group per draw. */
const bool custom_group = ((vertex_first != 0 && vertex_first != -1) || vertex_len != -1);
@ -555,6 +557,7 @@ class DrawMultiBuf {
DrawPrototype &draw = prototype_buf_.get_or_resize(prototype_count_++);
draw.resource_handle = handle.raw;
draw.custom_id = custom_id;
draw.instance_len = instance_len;
draw.group_id = group_id;
@ -594,7 +597,8 @@ class DrawMultiBuf {
Vector<Undetermined, 0> &commands,
VisibilityBuf &visibility_buf,
int visibility_word_per_draw,
int view_len);
int view_len,
bool use_custom_ids);
};
/** \} */

View File

@ -72,9 +72,10 @@ struct DrawPrototype {
uint group_id;
/* Resource handle associated with this call. Also reference visibility. */
uint resource_handle;
/* Custom extra value to be used by the engines. */
uint custom_id;
/* Number of instances. */
uint instance_len;
uint _pad0;
};
BLI_STATIC_ASSERT_ALIGN(DrawPrototype, 16)

View File

@ -186,7 +186,8 @@ void Manager::submit(PassMain &pass, View &view)
pass.commands_,
view.get_visibility_buffer(),
view.visibility_word_per_draw(),
view.view_len_);
view.view_len_,
pass.use_custom_ids);
resource_bind();

View File

@ -135,6 +135,8 @@ class PassBase {
public:
const char *debug_name;
bool use_custom_ids;
PassBase(const char *name,
DrawCommandBufType &draw_command_buf,
SubPassVector<PassBase<DrawCommandBufType>> &sub_passes,
@ -142,7 +144,8 @@ class PassBase {
: draw_commands_buf_(draw_command_buf),
sub_passes_(sub_passes),
shader_(shader),
debug_name(name){};
debug_name(name),
use_custom_ids(false){};
/**
* Reset the pass command pool.
@ -224,13 +227,14 @@ class PassBase {
uint instance_len = -1,
uint vertex_len = -1,
uint vertex_first = -1,
ResourceHandle handle = {0});
ResourceHandle handle = {0},
uint custom_id = 0);
/**
* Shorter version for the common case.
* \note Implemented in derived class. Not a virtual function to avoid indirection.
*/
void draw(GPUBatch *batch, ResourceHandle handle);
void draw(GPUBatch *batch, ResourceHandle handle, uint custom_id = 0);
/**
* Record a procedural draw call. Geometry is **NOT** source from a GPUBatch.
@ -240,7 +244,8 @@ class PassBase {
uint instance_len,
uint vertex_len,
uint vertex_first = -1,
ResourceHandle handle = {0});
ResourceHandle handle = {0},
uint custom_id = 0);
/**
* Indirect variants.
@ -654,20 +659,25 @@ template<class T> std::string PassBase<T>::serialize(std::string line_prefix) co
* \{ */
template<class T>
inline void PassBase<T>::draw(
GPUBatch *batch, uint instance_len, uint vertex_len, uint vertex_first, ResourceHandle handle)
inline void PassBase<T>::draw(GPUBatch *batch,
uint instance_len,
uint vertex_len,
uint vertex_first,
ResourceHandle handle,
uint custom_id)
{
if (instance_len == 0 || vertex_len == 0) {
return;
}
BLI_assert(shader_);
draw_commands_buf_.append_draw(
headers_, commands_, batch, instance_len, vertex_len, vertex_first, handle);
headers_, commands_, batch, instance_len, vertex_len, vertex_first, handle, custom_id);
}
template<class T> inline void PassBase<T>::draw(GPUBatch *batch, ResourceHandle handle)
template<class T>
inline void PassBase<T>::draw(GPUBatch *batch, ResourceHandle handle, uint custom_id)
{
this->draw(batch, -1, -1, -1, handle);
this->draw(batch, -1, -1, -1, handle, custom_id);
}
template<class T>
@ -675,9 +685,11 @@ inline void PassBase<T>::draw_procedural(GPUPrimType primitive,
uint instance_len,
uint vertex_len,
uint vertex_first,
ResourceHandle handle)
ResourceHandle handle,
uint custom_id)
{
this->draw(procedural_batch_get(primitive), instance_len, vertex_len, vertex_first, handle);
this->draw(
procedural_batch_get(primitive), instance_len, vertex_len, vertex_first, handle, custom_id);
}
/** \} */

View File

@ -83,7 +83,7 @@ struct MeshRenderData {
BMFace *efa_act;
BMFace *efa_act_uv;
/* The triangulation of #Mesh polygons, owned by the mesh. */
const MLoopTri *mlooptri;
blender::Span<MLoopTri> looptris;
const int *material_indices;
const float (*vert_normals)[3];
const float (*poly_normals)[3];

View File

@ -74,7 +74,7 @@ static void extract_tris_iter_poly_mesh(const MeshRenderData *mr,
int tri_len = mp->totloop - 2;
for (int offs = 0; offs < tri_len; offs++) {
const MLoopTri *mlt = &mr->mlooptri[tri_first_index_real + offs];
const MLoopTri *mlt = &mr->looptris[tri_first_index_real + offs];
int tri_index = tri_first_index + offs;
GPU_indexbuf_set_tri_verts(elb, tri_index, mlt->tri[0], mlt->tri[1], mlt->tri[2]);
}

View File

@ -214,12 +214,12 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness)
BVHTreeFromMesh treeData = {nullptr};
BVHTree *tree = BKE_bvhtree_from_mesh_get(&treeData, mr->me, BVHTREE_FROM_LOOPTRI, 4);
const MLoopTri *mlooptri = mr->mlooptri;
for (int i = 0; i < mr->tri_len; i++, mlooptri++) {
const int index = mlooptri->poly;
const float *cos[3] = {mr->vert_positions[mr->mloop[mlooptri->tri[0]].v],
mr->vert_positions[mr->mloop[mlooptri->tri[1]].v],
mr->vert_positions[mr->mloop[mlooptri->tri[2]].v]};
const Span<MLoopTri> looptris = mr->looptris;
for (const int i : looptris.index_range()) {
const int index = looptris[i].poly;
const float *cos[3] = {mr->vert_positions[mr->mloop[looptris[i].tri[0]].v],
mr->vert_positions[mr->mloop[looptris[i].tri[1]].v],
mr->vert_positions[mr->mloop[looptris[i].tri[2]].v]};
float ray_co[3];
float ray_no[3];
@ -261,7 +261,7 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness)
struct BVHTree_OverlapData {
const float3 *positions;
const MLoop *loops;
const MLoopTri *mlooptri;
Span<MLoopTri> looptris;
float epsilon;
};
@ -269,8 +269,8 @@ static bool bvh_overlap_cb(void *userdata, int index_a, int index_b, int /*threa
{
struct BVHTree_OverlapData *data = static_cast<struct BVHTree_OverlapData *>(userdata);
const MLoopTri *tri_a = &data->mlooptri[index_a];
const MLoopTri *tri_b = &data->mlooptri[index_b];
const MLoopTri *tri_a = &data->looptris[index_a];
const MLoopTri *tri_b = &data->looptris[index_b];
if (UNLIKELY(tri_a->poly == tri_b->poly)) {
return false;
@ -344,15 +344,15 @@ static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect)
struct BVHTree_OverlapData data = {nullptr};
data.positions = mr->vert_positions;
data.loops = mr->mloop;
data.mlooptri = mr->mlooptri;
data.looptris = mr->looptris;
data.epsilon = BLI_bvhtree_get_epsilon(tree);
BVHTreeOverlap *overlap = BLI_bvhtree_overlap_self(tree, &overlap_len, bvh_overlap_cb, &data);
if (overlap) {
for (int i = 0; i < overlap_len; i++) {
const MPoly *f_hit_pair[2] = {
&mr->mpoly[mr->mlooptri[overlap[i].indexA].poly],
&mr->mpoly[mr->mlooptri[overlap[i].indexB].poly],
&mr->mpoly[mr->looptris[overlap[i].indexA].poly],
&mr->mpoly[mr->looptris[overlap[i].indexB].poly],
};
for (int j = 0; j < 2; j++) {
const MPoly *f_hit = f_hit_pair[j];

View File

@ -118,7 +118,7 @@ static void extract_tan_init_common(const MeshRenderData *mr,
mr->mpoly,
mr->poly_len,
mr->mloop,
mr->mlooptri,
mr->looptris.data(),
mr->tri_len,
cd_ldata,
calc_active_tangent,

View File

@ -108,7 +108,14 @@ void main()
uint view_index = i * 32u;
while (word != 0u) {
if ((word & 1u) != 0u) {
resource_id_buf[dst_index++] = view_index | (resource_index << view_shift);
if (use_custom_ids) {
resource_id_buf[dst_index * 2] = view_index | (resource_index << view_shift);
resource_id_buf[dst_index * 2 + 1] = proto.custom_id;
}
else {
resource_id_buf[dst_index] = view_index | (resource_index << view_shift);
}
dst_index++;
}
view_index++;
word >>= 1u;
@ -117,7 +124,13 @@ void main()
}
else {
for (uint i = dst_index; i < dst_index + visible_instance_len; i++) {
resource_id_buf[i] = resource_index;
if (use_custom_ids) {
resource_id_buf[i * 2] = resource_index;
resource_id_buf[i * 2 + 1] = proto.custom_id;
}
else {
resource_id_buf[i] = resource_index;
}
}
}
}

View File

@ -189,6 +189,7 @@ GPU_SHADER_CREATE_INFO(draw_command_generate)
.push_constant(Type::INT, "prototype_len")
.push_constant(Type::INT, "visibility_word_per_draw")
.push_constant(Type::INT, "view_shift")
.push_constant(Type::BOOL, "use_custom_ids")
.compute_source("draw_command_generate_comp.glsl");
/** \} */
@ -200,9 +201,18 @@ GPU_SHADER_CREATE_INFO(draw_command_generate)
GPU_SHADER_CREATE_INFO(draw_resource_id_new)
.define("UNIFORM_RESOURCE_ID_NEW")
/* TODO (Miguel Pozo): This is an int for compatibility.
* It should become uint once the "Next" ports are complete. */
.storage_buf(DRW_RESOURCE_ID_SLOT, Qualifier::READ, "int", "resource_id_buf[]")
.define("drw_ResourceID", "resource_id_buf[gpu_BaseInstance + gl_InstanceID]");
GPU_SHADER_CREATE_INFO(draw_resource_with_custom_id_new)
.define("UNIFORM_RESOURCE_ID_NEW")
.define("WITH_CUSTOM_IDS")
.storage_buf(DRW_RESOURCE_ID_SLOT, Qualifier::READ, "int2", "resource_id_buf[]")
.define("drw_ResourceID", "resource_id_buf[gpu_BaseInstance + gl_InstanceID].x")
.define("drw_CustomID", "resource_id_buf[gpu_BaseInstance + gl_InstanceID].y");
/**
* Workaround the lack of gl_BaseInstance by binding the resource_id_buf as vertex buf.
*/
@ -210,6 +220,13 @@ GPU_SHADER_CREATE_INFO(draw_resource_id_fallback)
.define("UNIFORM_RESOURCE_ID_NEW")
.vertex_in(15, Type::INT, "drw_ResourceID");
GPU_SHADER_CREATE_INFO(draw_resource_with_custom_id_fallback)
.define("UNIFORM_RESOURCE_ID_NEW")
.define("WITH_CUSTOM_IDS")
.vertex_in(15, Type::IVEC2, "vertex_in_drw_ResourceID")
.define("drw_ResourceID", "vertex_in_drw_ResourceID.x")
.define("drw_CustomID", "vertex_in_drw_ResourceID.y");
/** TODO mask view id bits. */
GPU_SHADER_CREATE_INFO(draw_resource_handle_new).define("resource_handle", "drw_ResourceID");
@ -219,14 +236,19 @@ GPU_SHADER_CREATE_INFO(draw_resource_handle_new).define("resource_handle", "drw_
/** \name Draw Object Resources
* \{ */
GPU_SHADER_CREATE_INFO(draw_modelmat_new)
GPU_SHADER_CREATE_INFO(draw_modelmat_new_common)
.typedef_source("draw_shader_shared.h")
.storage_buf(DRW_OBJ_MAT_SLOT, Qualifier::READ, "ObjectMatrices", "drw_matrix_buf[]")
.define("drw_ModelMatrixInverse", "drw_matrix_buf[resource_id].model_inverse")
.define("drw_ModelMatrix", "drw_matrix_buf[resource_id].model")
/* TODO For compatibility with old shaders. To be removed. */
.define("ModelMatrixInverse", "drw_ModelMatrixInverse")
.define("ModelMatrix", "drw_ModelMatrix")
.additional_info("draw_resource_id_new");
.define("ModelMatrix", "drw_ModelMatrix");
GPU_SHADER_CREATE_INFO(draw_modelmat_new)
.additional_info("draw_modelmat_new_common", "draw_resource_id_new");
GPU_SHADER_CREATE_INFO(draw_modelmat_new_with_custom_id)
.additional_info("draw_modelmat_new_common", "draw_resource_with_custom_id_new");
/** \} */

View File

@ -928,7 +928,7 @@ typedef struct MeshDeformBind {
struct {
blender::Span<MPoly> polys;
blender::Span<MLoop> loops;
const MLoopTri *looptri;
blender::Span<MLoopTri> looptris;
const float (*poly_nors)[3];
} cagemesh_cache;
} MeshDeformBind;
@ -959,13 +959,12 @@ static void harmonic_ray_callback(void *userdata,
MeshRayCallbackData *data = static_cast<MeshRayCallbackData *>(userdata);
MeshDeformBind *mdb = data->mdb;
const blender::Span<MLoop> loops = mdb->cagemesh_cache.loops;
const MLoopTri *looptri = mdb->cagemesh_cache.looptri, *lt;
const float(*poly_nors)[3] = mdb->cagemesh_cache.poly_nors;
MeshDeformIsect *isec = data->isec;
float no[3], co[3], dist;
float *face[3];
lt = &looptri[index];
const MLoopTri *lt = &mdb->cagemesh_cache.looptris[index];
face[0] = mdb->cagecos[loops[lt->tri[0]].v];
face[1] = mdb->cagecos[loops[lt->tri[1]].v];
@ -1034,7 +1033,7 @@ static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb,
&data,
BVH_RAYCAST_WATERTIGHT) != -1) {
const blender::Span<MLoop> loops = mdb->cagemesh_cache.loops;
const MLoopTri *lt = &mdb->cagemesh_cache.looptri[hit.index];
const MLoopTri *lt = &mdb->cagemesh_cache.looptris[hit.index];
const MPoly *mp = &mdb->cagemesh_cache.polys[lt->poly];
const float(*cagecos)[3] = mdb->cagecos;
const float len = isect_mdef.lambda;
@ -1632,7 +1631,7 @@ static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBin
Mesh *me = mdb->cagemesh;
mdb->cagemesh_cache.polys = me->polys();
mdb->cagemesh_cache.loops = me->loops();
mdb->cagemesh_cache.looptri = BKE_mesh_runtime_looptri_ensure(me);
mdb->cagemesh_cache.looptris = me->looptris();
mdb->cagemesh_cache.poly_nors = BKE_mesh_poly_normals_ensure(me);
}

View File

@ -833,8 +833,8 @@ static void ui_searchbox_region_layout_fn(const struct bContext *C, struct ARegi
region->winrct.ymax = rect_i.ymax;
}
region->winx = region->winrct.xmax - region->winrct.xmin;
region->winy = region->winrct.ymax - region->winrct.ymin;
region->winx = region->winrct.xmax - region->winrct.xmin + 1;
region->winy = region->winrct.ymax - region->winrct.ymin + 1;
data->size_set = true;
}

View File

@ -10,9 +10,9 @@ set(INC
../../bmesh
../../depsgraph
../../draw
../../functions
../../geometry
../../gpu
../../functions
../../imbuf
../../makesdna
../../makesrna
@ -54,7 +54,7 @@ set(SRC
editmesh_undo.cc
editmesh_utils.c
mesh_data.cc
mesh_mirror.c
mesh_mirror.cc
mesh_ops.c
meshtools.cc

View File

@ -224,10 +224,11 @@ static void build_poly_connections(blender::AtomicDisjointSet &islands,
{
using namespace blender;
const Span<MPoly> polys = mesh.polys();
const Span<MEdge> edges = mesh.edges();
const Span<MLoop> loops = mesh.loops();
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
const bke::AttributeAccessor attributes = mesh.attributes();
const VArray<bool> uv_seams = attributes.lookup_or_default<bool>(
".uv_seam", ATTR_DOMAIN_EDGE, false);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
@ -243,7 +244,7 @@ static void build_poly_connections(blender::AtomicDisjointSet &islands,
for (const int poly_loop_index : poly_loops.index_range()) {
const MLoop &outer_mloop = poly_loops[poly_loop_index];
if (skip_seams && (edges[outer_mloop.e].flag & ME_SEAM) != 0) {
if (skip_seams && uv_seams[outer_mloop.e]) {
continue;
}
@ -252,7 +253,7 @@ static void build_poly_connections(blender::AtomicDisjointSet &islands,
if (&outer_mloop == &inner_mloop) {
continue;
}
if (skip_seams && (edges[inner_mloop.e].flag & ME_SEAM) != 0) {
if (skip_seams && uv_seams[inner_mloop.e]) {
continue;
}
islands.join(inner_mloop.e, outer_mloop.e);
@ -273,10 +274,11 @@ static void paintface_select_linked_faces(Mesh &mesh,
build_poly_connections(islands, mesh);
const Span<MPoly> polys = mesh.polys();
const Span<MEdge> edges = mesh.edges();
const Span<MLoop> loops = mesh.loops();
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
const VArray<bool> uv_seams = attributes.lookup_or_default<bool>(
".uv_seam", ATTR_DOMAIN_EDGE, false);
bke::SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_span<bool>(
".select_poly", ATTR_DOMAIN_FACE);
@ -284,7 +286,7 @@ static void paintface_select_linked_faces(Mesh &mesh,
for (const int i : face_indices) {
const MPoly &poly = polys[i];
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
if ((edges[loop.e].flag & ME_SEAM) != 0) {
if (uv_seams[loop.e]) {
continue;
}
const int root = islands.find_root(loop.e);

View File

@ -27,12 +27,12 @@
#define KD_THRESH 0.00002f
static struct {
void *tree;
} MirrKdStore = {NULL};
KDTree_3d *tree;
} MirrKdStore = {nullptr};
void ED_mesh_mirror_spatial_table_begin(Object *ob, BMEditMesh *em, Mesh *me_eval)
{
Mesh *me = ob->data;
Mesh *me = static_cast<Mesh *>(ob->data);
const bool use_em = (!me_eval && em && me->edit_mesh == em);
const int totvert = use_em ? em->bm->totvert : me_eval ? me_eval->totvert : me->totvert;
@ -69,7 +69,7 @@ int ED_mesh_mirror_spatial_table_lookup(Object *ob,
Mesh *me_eval,
const float co[3])
{
if (MirrKdStore.tree == NULL) {
if (MirrKdStore.tree == nullptr) {
ED_mesh_mirror_spatial_table_begin(ob, em, me_eval);
}
@ -86,12 +86,12 @@ int ED_mesh_mirror_spatial_table_lookup(Object *ob,
return -1;
}
void ED_mesh_mirror_spatial_table_end(Object *UNUSED(ob))
void ED_mesh_mirror_spatial_table_end(Object * /*ob*/)
{
/* TODO: store this in object/object-data (keep unused argument for now). */
if (MirrKdStore.tree) {
BLI_kdtree_3d_free(MirrKdStore.tree);
MirrKdStore.tree = NULL;
MirrKdStore.tree = nullptr;
}
}
@ -101,12 +101,12 @@ void ED_mesh_mirror_spatial_table_end(Object *UNUSED(ob))
/** \name Mesh Topology Mirror API
* \{ */
typedef uint MirrTopoHash_t;
using MirrTopoHash_t = uint;
typedef struct MirrTopoVert_t {
struct MirrTopoVert_t {
MirrTopoHash_t hash;
int v_index;
} MirrTopoVert_t;
};
static int mirrtopo_hash_sort(const void *l1, const void *l2)
{
@ -132,7 +132,7 @@ static int mirrtopo_vert_sort(const void *v1, const void *v2)
bool ED_mesh_mirrtopo_recalc_check(BMEditMesh *em, Mesh *me, MirrTopoStore_t *mesh_topo_store)
{
const bool is_editmode = em != NULL;
const bool is_editmode = em != nullptr;
int totvert;
int totedge;
@ -145,7 +145,7 @@ bool ED_mesh_mirrtopo_recalc_check(BMEditMesh *em, Mesh *me, MirrTopoStore_t *me
totedge = me->totedge;
}
if ((mesh_topo_store->index_lookup == NULL) ||
if ((mesh_topo_store->index_lookup == nullptr) ||
(mesh_topo_store->prev_is_editmode != is_editmode) ||
(totvert != mesh_topo_store->prev_vert_tot) || (totedge != mesh_topo_store->prev_edge_tot)) {
return true;
@ -159,10 +159,10 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em,
const bool skip_em_vert_array_init)
{
if (em) {
BLI_assert(me == NULL);
BLI_assert(me == nullptr);
}
const bool is_editmode = (em != NULL);
const MEdge *medge = NULL, *med;
const bool is_editmode = (em != nullptr);
const MEdge *medge = nullptr, *med;
/* Edit-mode variables. */
BMEdge *eed;
@ -173,13 +173,8 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em,
int tot_unique = -1, tot_unique_prev = -1;
int tot_unique_edges = 0, tot_unique_edges_prev;
MirrTopoHash_t *topo_hash = NULL;
MirrTopoHash_t *topo_hash_prev = NULL;
MirrTopoVert_t *topo_pairs;
MirrTopoHash_t topo_pass = 1;
intptr_t *index_lookup; /* direct access to mesh_topo_store->index_lookup */
/* reallocate if needed */
ED_mesh_mirrtopo_free(mesh_topo_store);
@ -194,7 +189,8 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em,
totvert = me->totvert;
}
topo_hash = MEM_callocN(totvert * sizeof(MirrTopoHash_t), "TopoMirr");
MirrTopoHash_t *topo_hash = static_cast<MirrTopoHash_t *>(
MEM_callocN(totvert * sizeof(MirrTopoHash_t), __func__));
/* Initialize the vert-edge-user counts used to detect unique topology */
if (em) {
@ -216,7 +212,7 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em,
}
}
topo_hash_prev = MEM_dupallocN(topo_hash);
MirrTopoHash_t *topo_hash_prev = static_cast<MirrTopoHash_t *>(MEM_dupallocN(topo_hash));
tot_unique_prev = -1;
tot_unique_edges_prev = -1;
@ -268,10 +264,12 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em,
}
/* Hash/Index pairs are needed for sorting to find index pairs */
topo_pairs = MEM_callocN(sizeof(MirrTopoVert_t) * totvert, "MirrTopoPairs");
MirrTopoVert_t *topo_pairs = static_cast<MirrTopoVert_t *>(
MEM_callocN(sizeof(MirrTopoVert_t) * totvert, "MirrTopoPairs"));
/* since we are looping through verts, initialize these values here too */
index_lookup = MEM_mallocN(totvert * sizeof(*index_lookup), "mesh_topo_lookup");
intptr_t *index_lookup = static_cast<intptr_t *>(
MEM_mallocN(totvert * sizeof(*index_lookup), "mesh_topo_lookup"));
if (em) {
if (skip_em_vert_array_init == false) {
@ -336,7 +334,7 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em,
}
MEM_freeN(topo_pairs);
topo_pairs = NULL;
topo_pairs = nullptr;
MEM_freeN(topo_hash);
MEM_freeN(topo_hash_prev);

View File

@ -419,7 +419,7 @@ struct ProjPaintState {
blender::Span<MLoop> loops_eval;
const bool *select_poly_eval;
const int *material_indices;
const MLoopTri *mlooptri_eval;
blender::Span<MLoopTri> looptris_eval;
const float (*mloopuv_stencil_eval)[2];
@ -551,7 +551,7 @@ static Material *tex_get_material(const ProjPaintState *ps, int poly_i)
static TexPaintSlot *project_paint_face_paint_slot(const ProjPaintState *ps, int tri_index)
{
const int poly_i = ps->mlooptri_eval[tri_index].poly;
const int poly_i = ps->looptris_eval[tri_index].poly;
Material *ma = tex_get_material(ps, poly_i);
return ma ? ma->texpaintslot + ma->paint_active_slot : nullptr;
}
@ -562,7 +562,7 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_i
return ps->stencil_ima;
}
const int poly_i = ps->mlooptri_eval[tri_index].poly;
const int poly_i = ps->looptris_eval[tri_index].poly;
Material *ma = tex_get_material(ps, poly_i);
TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_active_slot : nullptr;
return slot ? slot->ima : ps->canvas_ima;
@ -570,14 +570,14 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_i
static TexPaintSlot *project_paint_face_clone_slot(const ProjPaintState *ps, int tri_index)
{
const int poly_i = ps->mlooptri_eval[tri_index].poly;
const int poly_i = ps->looptris_eval[tri_index].poly;
Material *ma = tex_get_material(ps, poly_i);
return ma ? ma->texpaintslot + ma->paint_clone_slot : nullptr;
}
static Image *project_paint_face_clone_image(const ProjPaintState *ps, int tri_index)
{
const int poly_i = ps->mlooptri_eval[tri_index].poly;
const int poly_i = ps->looptris_eval[tri_index].poly;
Material *ma = tex_get_material(ps, poly_i);
TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_clone_slot : nullptr;
return slot ? slot->ima : ps->clone_ima;
@ -673,7 +673,7 @@ static int project_paint_PickFace(const ProjPaintState *ps, const float pt[2], f
for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
const int tri_index = POINTER_AS_INT(node->link);
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const float *vtri_ss[3] = {
ps->screenCoords[ps->loops_eval[lt->tri[0]].v],
ps->screenCoords[ps->loops_eval[lt->tri[1]].v],
@ -737,7 +737,7 @@ static bool project_paint_PickColor(
return false;
}
lt = &ps->mlooptri_eval[tri_index];
lt = &ps->looptris_eval[tri_index];
PS_LOOPTRI_ASSIGN_UV_3(lt_tri_uv, ps->poly_to_loop_uv, lt);
interp_v2_v2v2v2(uv, UNPACK3(lt_tri_uv), w);
@ -915,7 +915,7 @@ static bool project_bucket_point_occluded(const ProjPaintState *ps,
const int tri_index = POINTER_AS_INT(bucketFace->link);
if (orig_face != tri_index) {
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const float *vtri_ss[3] = {
ps->screenCoords[ps->loops_eval[lt->tri[0]].v],
ps->screenCoords[ps->loops_eval[lt->tri[1]].v],
@ -1121,7 +1121,7 @@ static bool pixel_bounds_array(
static void project_face_winding_init(const ProjPaintState *ps, const int tri_index)
{
/* detect the winding of faces in uv space */
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
float winding = cross_tri_v2(lt_tri_uv[0], lt_tri_uv[1], lt_tri_uv[2]);
@ -1141,7 +1141,7 @@ static bool check_seam(const ProjPaintState *ps,
int *other_face,
int *orig_fidx)
{
const MLoopTri *orig_lt = &ps->mlooptri_eval[orig_face];
const MLoopTri *orig_lt = &ps->looptris_eval[orig_face];
const float *orig_lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, orig_lt)};
/* vert indices from face vert order indices */
const uint i1 = ps->loops_eval[orig_lt->tri[orig_i1_fidx]].v;
@ -1154,7 +1154,7 @@ static bool check_seam(const ProjPaintState *ps,
const int tri_index = POINTER_AS_INT(node->link);
if (tri_index != orig_face) {
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
/* could check if the 2 faces images match here,
* but then there wouldn't be a way to return the opposite face's info */
@ -1303,7 +1303,7 @@ static void uv_image_outset(const ProjPaintState *ps,
int fidx[2];
uint loop_index;
uint vert[2];
const MLoopTri *ltri = &ps->mlooptri_eval[tri_index];
const MLoopTri *ltri = &ps->looptris_eval[tri_index];
float ibuf_inv[2];
@ -1386,7 +1386,7 @@ static void insert_seam_vert_array(const ProjPaintState *ps,
const int ibuf_x,
const int ibuf_y)
{
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
const int fidx[2] = {fidx1, ((fidx1 + 1) % 3)};
float vec[2];
@ -1446,7 +1446,7 @@ static void project_face_seams_init(const ProjPaintState *ps,
int other_face, other_fidx;
/* next fidx in the face (0,1,2,3) -> (1,2,3,0) or (0,1,2) -> (1,2,0) for a tri */
int fidx[2] = {2, 0};
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
LinkNode *node;
/* initialize face winding if needed */
@ -1665,7 +1665,7 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps,
Image *other_tpage = ps->stencil_ima;
if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, nullptr, nullptr))) {
const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt_other = &ps->looptris_eval[tri_index];
const float *lt_other_tri_uv[3] = {ps->mloopuv_stencil_eval[lt_other->tri[0]],
ps->mloopuv_stencil_eval[lt_other->tri[1]],
ps->mloopuv_stencil_eval[lt_other->tri[2]]};
@ -1704,7 +1704,7 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps,
}
if (ps->do_mask_cavity) {
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
float ca1, ca2, ca3, ca_mask;
ca1 = ps->cavities[lt_vtri[0]];
@ -1719,7 +1719,7 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps,
/* calculate mask */
if (ps->do_mask_normal) {
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
const MPoly *mp = &ps->polys_eval[lt->poly];
float no[3], angle_cos;
@ -1959,7 +1959,7 @@ static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps,
Image *other_tpage = project_paint_face_clone_image(ps, tri_index);
if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, nullptr, nullptr))) {
const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt_other = &ps->looptris_eval[tri_index];
const float *lt_other_tri_uv[3] = {
PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv_clone, lt_other)};
@ -2996,7 +2996,7 @@ static void project_paint_face_init(const ProjPaintState *ps,
ps->projImages + image_index,
};
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
@ -3287,7 +3287,7 @@ static void project_paint_face_init(const ProjPaintState *ps,
bucket_clip_edges[1])) {
/* Avoid div by zero. */
if (len_squared_v2v2(vCoSS[fidx1], vCoSS[fidx2]) > FLT_EPSILON) {
uint loop_idx = ps->mlooptri_eval[tri_index].tri[fidx1];
uint loop_idx = ps->looptris_eval[tri_index].tri[fidx1];
LoopSeamData *seam_data = &ps->loopSeamData[loop_idx];
float(*seam_uvs)[2] = seam_data->seam_uvs;
@ -3525,7 +3525,7 @@ static void project_bucket_init(const ProjPaintState *ps,
for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
tri_index = POINTER_AS_INT(node->link);
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
/* Image context switching */
@ -4085,8 +4085,7 @@ static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *p
ps->totpoly_eval = ps->me_eval->totpoly;
ps->totloop_eval = ps->me_eval->totloop;
ps->mlooptri_eval = BKE_mesh_runtime_looptri_ensure(ps->me_eval);
ps->totlooptri_eval = BKE_mesh_runtime_looptri_len(ps->me_eval);
ps->looptris_eval = ps->me_eval->looptris();
ps->poly_to_loop_uv = static_cast<const float(**)[2]>(
MEM_mallocN(ps->totpoly_eval * sizeof(float(*)[2]), "proj_paint_mtfaces"));
@ -4159,7 +4158,7 @@ static bool project_paint_clone_face_skip(ProjPaintState *ps,
}
/* will set multiple times for 4+ sided poly */
ps->poly_to_loop_uv_clone[ps->mlooptri_eval[tri_index].poly] = lc->mloopuv_clone_base;
ps->poly_to_loop_uv_clone[ps->looptris_eval[tri_index].poly] = lc->mloopuv_clone_base;
}
return false;
}
@ -4304,17 +4303,17 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
TexPaintSlot *slot_last = nullptr;
TexPaintSlot *slot = nullptr;
int tile_last = -1, tile;
const MLoopTri *lt;
int image_index = -1, tri_index;
int prev_poly = -1;
const blender::Span<MLoopTri> looptris = ps->looptris_eval;
BLI_assert(ps->image_tot == 0);
for (tri_index = 0, lt = ps->mlooptri_eval; tri_index < ps->totlooptri_eval; tri_index++, lt++) {
for (tri_index = 0; tri_index < ps->totlooptri_eval; tri_index++) {
bool is_face_sel;
bool skip_tri = false;
is_face_sel = project_paint_check_face_sel(ps, face_lookup, lt);
is_face_sel = project_paint_check_face_sel(ps, face_lookup, &looptris[tri_index]);
if (!ps->do_stencil_brush) {
slot = project_paint_face_paint_slot(ps, tri_index);
@ -4353,12 +4352,12 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
tpage = ps->stencil_ima;
}
ps->poly_to_loop_uv[lt->poly] = mloopuv_base;
ps->poly_to_loop_uv[looptris[tri_index].poly] = mloopuv_base;
tile = project_paint_face_paint_tile(tpage, mloopuv_base[lt->tri[0]]);
tile = project_paint_face_paint_tile(tpage, mloopuv_base[looptris[tri_index].tri[0]]);
#ifndef PROJ_DEBUG_NOSEAMBLEED
project_paint_bleed_add_face_user(ps, arena, lt, tri_index);
project_paint_bleed_add_face_user(ps, arena, &looptris[tri_index], tri_index);
#endif
if (skip_tri || project_paint_clone_face_skip(ps, layer_clone, slot, tri_index)) {
@ -4369,7 +4368,7 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
if (is_face_sel && tpage) {
ProjPaintFaceCoSS coSS;
proj_paint_face_coSS_init(ps, lt, &coSS);
proj_paint_face_coSS_init(ps, &looptris[tri_index], &coSS);
if (is_multi_view == false) {
if (project_paint_flt_max_cull(ps, &coSS)) {
@ -4386,12 +4385,12 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
/* Back-face culls individual triangles but mask normal will use polygon. */
if (ps->do_backfacecull) {
if (ps->do_mask_normal) {
if (prev_poly != lt->poly) {
if (prev_poly != looptris[tri_index].poly) {
int iloop;
bool culled = true;
const MPoly *poly = &ps->polys_eval[lt->poly];
const MPoly *poly = &ps->polys_eval[looptris[tri_index].poly];
int poly_loops = poly->totloop;
prev_poly = lt->poly;
prev_poly = looptris[tri_index].poly;
for (iloop = 0; iloop < poly_loops; iloop++) {
if (!(ps->vertFlags[ps->loops_eval[poly->loopstart + iloop].v] & PROJ_VERT_CULL)) {
culled = false;
@ -4404,7 +4403,6 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
* but counter gets incremented when continuing, so decrease by 3 */
int poly_tri = poly_loops - 3;
tri_index += poly_tri;
lt += poly_tri;
continue;
}
}
@ -4451,7 +4449,7 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
if (image_index != -1) {
/* Initialize the faces screen pixels */
/* Add this to a list to initialize later */
project_paint_delayed_face_init(ps, lt, tri_index);
project_paint_delayed_face_init(ps, &looptris[tri_index], tri_index);
}
}
}
@ -5703,7 +5701,7 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
tri_index = project_paint_PickFace(ps, pos, w);
if (tri_index != -1) {
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const MLoopTri *lt = &ps->looptris_eval[tri_index];
const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
float world[3];
UnifiedPaintSettings *ups = &ps->scene->toolsettings->unified_paint_settings;

View File

@ -680,10 +680,11 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
break;
}
case SCULPT_FACE_SETS_FROM_UV_SEAMS: {
const Span<MEdge> edges = mesh->edges();
const VArraySpan<bool> uv_seams = mesh->attributes().lookup_or_default<bool>(
".uv_seam", ATTR_DOMAIN_EDGE, false);
sculpt_face_sets_init_flood_fill(
ob, [&](const int /*from_face*/, const int edge, const int /*to_face*/) -> bool {
return (edges[edge].flag & ME_SEAM) == 0;
return !uv_seams[edge];
});
break;
}

View File

@ -142,8 +142,9 @@ static void graph_init(struct wmWindowManager *wm, ScrArea *area)
/* init dopesheet data if non-existent (i.e. for old files) */
if (sipo->ads == NULL) {
wmWindow *win = WM_window_find_by_area(wm, area);
sipo->ads = MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
sipo->ads->source = (ID *)WM_window_get_active_scene(wm->winactive);
sipo->ads->source = win ? (ID *)WM_window_get_active_scene(win) : NULL;
}
/* force immediate init of any invalid F-Curve colors */

View File

@ -132,7 +132,8 @@ static void nla_init(struct wmWindowManager *wm, ScrArea *area)
/* init dopesheet data if non-existent (i.e. for old files) */
if (snla->ads == NULL) {
snla->ads = MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
snla->ads->source = (wm->winactive) ? (ID *)WM_window_get_active_scene(wm->winactive) : NULL;
wmWindow *win = WM_window_find_by_area(wm, area);
snla->ads->source = win ? (ID *)WM_window_get_active_scene(win) : NULL;
}
ED_area_tag_refresh(area);

View File

@ -2039,9 +2039,11 @@ static NodeLinkDrawConfig nodelink_get_draw_config(const bContext &C,
draw_config.th_col2 = th_col2;
draw_config.th_col3 = th_col3;
const bNodeTree &node_tree = *snode.edittree;
draw_config.dim_factor = selected ? 1.0f :
node_link_dim_factor(
snode.runtime->all_socket_locations, v2d, link);
node_tree.runtime->all_socket_locations, v2d, link);
bTheme *btheme = UI_GetTheme();
draw_config.dash_alpha = btheme->space_node.dash_alpha;
@ -2063,24 +2065,21 @@ static NodeLinkDrawConfig nodelink_get_draw_config(const bContext &C,
if (snode.overlay.flag & SN_OVERLAY_SHOW_OVERLAYS &&
snode.overlay.flag & SN_OVERLAY_SHOW_WIRE_COLORS) {
PointerRNA from_node_ptr, to_node_ptr;
RNA_pointer_create((ID *)snode.edittree, &RNA_Node, link.fromnode, &from_node_ptr);
RNA_pointer_create((ID *)snode.edittree, &RNA_Node, link.tonode, &to_node_ptr);
RNA_pointer_create((ID *)&node_tree, &RNA_Node, link.fromnode, &from_node_ptr);
RNA_pointer_create((ID *)&node_tree, &RNA_Node, link.tonode, &to_node_ptr);
if (link.fromsock) {
node_socket_color_get(
C, *snode.edittree, from_node_ptr, *link.fromsock, draw_config.start_color);
node_socket_color_get(C, node_tree, from_node_ptr, *link.fromsock, draw_config.start_color);
}
else {
node_socket_color_get(
C, *snode.edittree, to_node_ptr, *link.tosock, draw_config.start_color);
node_socket_color_get(C, node_tree, to_node_ptr, *link.tosock, draw_config.start_color);
}
if (link.tosock) {
node_socket_color_get(C, *snode.edittree, to_node_ptr, *link.tosock, draw_config.end_color);
node_socket_color_get(C, node_tree, to_node_ptr, *link.tosock, draw_config.end_color);
}
else {
node_socket_color_get(
C, *snode.edittree, from_node_ptr, *link.fromsock, draw_config.end_color);
node_socket_color_get(C, node_tree, from_node_ptr, *link.fromsock, draw_config.end_color);
}
}
else {
@ -2167,8 +2166,9 @@ void node_draw_link_bezier(const bContext &C,
const int th_col3,
const bool selected)
{
const std::array<float2, 4> points = node_link_bezier_points(snode.runtime->all_socket_locations,
link);
const bNodeTree &node_tree = *snode.edittree;
const std::array<float2, 4> points = node_link_bezier_points(
node_tree.runtime->all_socket_locations, link);
if (!node_link_draw_is_visible(v2d, points)) {
return;
}
@ -2227,15 +2227,18 @@ void node_draw_link(const bContext &C,
static std::array<float2, 4> node_link_bezier_points_dragged(const SpaceNode &snode,
const bNodeLink &link)
{
const bNodeTree &node_tree = *snode.edittree;
const float2 cursor = snode.runtime->cursor * UI_DPI_FAC;
std::array<float2, 4> points;
points[0] = link.fromsock ?
socket_link_connection_location(
snode.runtime->all_socket_locations, *link.fromnode, *link.fromsock, link) :
socket_link_connection_location(node_tree.runtime->all_socket_locations,
*link.fromnode,
*link.fromsock,
link) :
cursor;
points[3] = link.tosock ?
socket_link_connection_location(
snode.runtime->all_socket_locations, *link.tonode, *link.tosock, link) :
node_tree.runtime->all_socket_locations, *link.tonode, *link.tosock, link) :
cursor;
calculate_inner_link_bezier_points(points);
return points;

View File

@ -138,7 +138,7 @@ static int add_reroute_exec(bContext *C, wmOperator *op)
const ARegion &region = *CTX_wm_region(C);
SpaceNode &snode = *CTX_wm_space_node(C);
bNodeTree &ntree = *snode.edittree;
const Span<float2> socket_locations = snode.runtime->all_socket_locations;
const Span<float2> socket_locations = ntree.runtime->all_socket_locations;
Vector<float2> path;
RNA_BEGIN (op->ptr, itemptr, "path") {

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