Overlay-Next: Initial implementation #107045
@ -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):
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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]]
|
||||
|
@ -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])
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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'}
|
||||
|
@ -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="")
|
||||
|
@ -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'}
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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],
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -95,7 +95,6 @@ typedef struct CCGDerivedMesh {
|
||||
struct CCGFace *face;
|
||||
} * faceMap;
|
||||
|
||||
short *edgeFlags;
|
||||
struct DMFlagMat *faceFlags;
|
||||
|
||||
int *reverseFaceMap;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -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)) {
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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]]) {
|
||||
|
@ -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"));
|
||||
|
||||
|
@ -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);
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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. */
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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"));
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -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];
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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];
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
|
||||
/** \} */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -138,7 +138,7 @@ static int add_reroute_exec(bContext *C, wmOperator *op)
|
||||
const ARegion ®ion = *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
Loading…
Reference in New Issue
Block a user