WIP: Brush assets project #106303
|
@ -115,7 +115,8 @@ def git_branch(git_command: str) -> str:
|
|||
|
||||
try:
|
||||
branch = subprocess.check_output([git_command, "rev-parse", "--abbrev-ref", "HEAD"])
|
||||
except subprocess.CalledProcessError as e:
|
||||
except subprocess.CalledProcessError:
|
||||
# No need to print the exception, error text is written to the output already.
|
||||
sys.stderr.write("Failed to get Blender git branch\n")
|
||||
sys.exit(1)
|
||||
|
||||
|
|
|
@ -16,10 +16,11 @@ This ``directory`` and ``files`` properties now will be used by the
|
|||
"""
|
||||
|
||||
import bpy
|
||||
from bpy_extras.io_utils import ImportHelper
|
||||
from mathutils import Vector
|
||||
|
||||
|
||||
class ShaderScriptImport(bpy.types.Operator):
|
||||
class ShaderScriptImport(bpy.types.Operator, ImportHelper):
|
||||
"""Test importer that creates scripts nodes from .txt files"""
|
||||
bl_idname = "shader.script_import"
|
||||
bl_label = "Import a text file as a script node"
|
||||
|
@ -28,8 +29,11 @@ class ShaderScriptImport(bpy.types.Operator):
|
|||
This Operator can import multiple .txt files, we need following directory and files
|
||||
properties that the file handler will use to set files path data
|
||||
"""
|
||||
directory: bpy.props.StringProperty(subtype='FILE_PATH', options={'SKIP_SAVE'})
|
||||
files: bpy.props.CollectionProperty(type=bpy.types.OperatorFileListElement, options={'SKIP_SAVE'})
|
||||
directory: bpy.props.StringProperty(subtype='FILE_PATH', options={'SKIP_SAVE', 'HIDDEN'})
|
||||
files: bpy.props.CollectionProperty(type=bpy.types.OperatorFileListElement, options={'SKIP_SAVE', 'HIDDEN'})
|
||||
|
||||
"""Allow the user to select if the node's label is set or not"""
|
||||
set_label: bpy.props.BoolProperty(name="Set Label", default=False)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
@ -57,23 +61,26 @@ class ShaderScriptImport(bpy.types.Operator):
|
|||
filepath = os.path.join(self.directory, file.name)
|
||||
text_node.filepath = filepath
|
||||
text_node.location = Vector((x, y))
|
||||
|
||||
# Set the node's title to the file name
|
||||
if self.set_label:
|
||||
text_node.label = file.name
|
||||
|
||||
x += 20.0
|
||||
y -= 20.0
|
||||
return {'FINISHED'}
|
||||
|
||||
"""
|
||||
By default the file handler invokes the operator with the directory and files properties set.
|
||||
In this example if this properties are set the operator is executed, if not the
|
||||
file select window is invoked.
|
||||
This depends on setting ``options={'SKIP_SAVE'}`` to the properties options to avoid
|
||||
to reuse filepath data between operator calls.
|
||||
Use ImportHelper's invoke_popup() to handle the invocation so that this operator's properties
|
||||
are shown in a popup. This allows the user to configure additional settings on the operator like
|
||||
the `set_label` property. Consider having a draw() method on the operator in order to layout the
|
||||
properties in the UI appropriately.
|
||||
|
||||
If filepath information is not provided the file select window will be invoked instead.
|
||||
"""
|
||||
|
||||
def invoke(self, context, event):
|
||||
if self.directory:
|
||||
return self.execute(context)
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {'RUNNING_MODAL'}
|
||||
return self.invoke_popup(context)
|
||||
|
||||
|
||||
class SHADER_FH_script_import(bpy.types.FileHandler):
|
||||
|
|
|
@ -219,10 +219,6 @@ endif()
|
|||
|
||||
if(WITH_CYCLES_OSL)
|
||||
add_definitions(-DWITH_OSL)
|
||||
# osl 1.9.x
|
||||
add_definitions(-DOSL_STATIC_BUILD)
|
||||
# pre 1.9
|
||||
add_definitions(-DOSL_STATIC_LIBRARY)
|
||||
include_directories(
|
||||
SYSTEM
|
||||
${OSL_INCLUDE_DIR}
|
||||
|
|
|
@ -142,6 +142,12 @@ if(WITH_OPENIMAGEDENOISE)
|
|||
)
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_OSL)
|
||||
list(APPEND LIB
|
||||
${OSL_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
blender_add_lib(bf_intern_cycles "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
||||
add_dependencies(bf_intern_cycles bf_rna)
|
||||
|
|
|
@ -203,6 +203,13 @@ if(WITH_OPENIMAGEDENOISE)
|
|||
)
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_OSL)
|
||||
list(APPEND LIB
|
||||
${OSL_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
include_directories(${INC})
|
||||
include_directories(SYSTEM ${INC_SYS})
|
||||
|
||||
|
|
|
@ -7,76 +7,82 @@
|
|||
|
||||
#define vector3 point
|
||||
|
||||
float safe_noise(float p)
|
||||
float safe_noise(float co)
|
||||
{
|
||||
float f = noise("noise", p);
|
||||
if (isinf(f)) {
|
||||
return 0.5;
|
||||
}
|
||||
return f;
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. */
|
||||
float p = fmod(co, 100000.0);
|
||||
|
||||
return noise("noise", p);
|
||||
}
|
||||
|
||||
float safe_noise(vector2 p)
|
||||
float safe_noise(vector2 co)
|
||||
{
|
||||
float f = noise("noise", p.x, p.y);
|
||||
if (isinf(f)) {
|
||||
return 0.5;
|
||||
}
|
||||
return f;
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0, however at such scales this
|
||||
* usually shouldn't be noticeable. */
|
||||
vector2 p = fmod(co, 100000.0);
|
||||
|
||||
return noise("noise", p.x, p.y);
|
||||
}
|
||||
|
||||
float safe_noise(vector3 p)
|
||||
float safe_noise(vector3 co)
|
||||
{
|
||||
float f = noise("noise", p);
|
||||
if (isinf(f)) {
|
||||
return 0.5;
|
||||
}
|
||||
return f;
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0, however at such scales this
|
||||
* usually shouldn't be noticeable. */
|
||||
vector3 p = fmod(co, 100000.0);
|
||||
|
||||
return noise("noise", p);
|
||||
}
|
||||
|
||||
float safe_noise(vector4 p)
|
||||
float safe_noise(vector4 co)
|
||||
{
|
||||
float f = noise("noise", vector3(p.x, p.y, p.z), p.w);
|
||||
if (isinf(f)) {
|
||||
return 0.5;
|
||||
}
|
||||
return f;
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0, however at such scales this
|
||||
* usually shouldn't be noticeable. */
|
||||
vector4 p = fmod(co, 100000.0);
|
||||
|
||||
return noise("noise", vector3(p.x, p.y, p.z), p.w);
|
||||
}
|
||||
|
||||
float safe_snoise(float p)
|
||||
float safe_snoise(float co)
|
||||
{
|
||||
float f = noise("snoise", p);
|
||||
if (isinf(f)) {
|
||||
return 0.0;
|
||||
}
|
||||
return f;
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. */
|
||||
float p = fmod(co, 100000.0);
|
||||
|
||||
return noise("snoise", p);
|
||||
}
|
||||
|
||||
float safe_snoise(vector2 p)
|
||||
float safe_snoise(vector2 co)
|
||||
{
|
||||
float f = noise("snoise", p.x, p.y);
|
||||
if (isinf(f)) {
|
||||
return 0.0;
|
||||
}
|
||||
return f;
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0, however at such scales this
|
||||
* usually shouldn't be noticeable. */
|
||||
vector2 p = fmod(co, 100000.0);
|
||||
|
||||
return noise("snoise", p.x, p.y);
|
||||
}
|
||||
|
||||
float safe_snoise(vector3 p)
|
||||
float safe_snoise(vector3 co)
|
||||
{
|
||||
float f = noise("snoise", p);
|
||||
if (isinf(f)) {
|
||||
return 0.0;
|
||||
}
|
||||
return f;
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0, however at such scales this
|
||||
* usually shouldn't be noticeable. */
|
||||
vector3 p = fmod(co, 100000.0);
|
||||
|
||||
return noise("snoise", p);
|
||||
}
|
||||
|
||||
float safe_snoise(vector4 p)
|
||||
float safe_snoise(vector4 co)
|
||||
{
|
||||
float f = noise("snoise", vector3(p.x, p.y, p.z), p.w);
|
||||
if (isinf(f)) {
|
||||
return 0.0;
|
||||
}
|
||||
return f;
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0, however at such scales this
|
||||
* usually shouldn't be noticeable. */
|
||||
vector4 p = fmod(co, 100000.0);
|
||||
|
||||
return noise("snoise", vector3(p.x, p.y, p.z), p.w);
|
||||
}
|
||||
|
||||
#define NOISE_FBM(T) \
|
||||
|
|
|
@ -684,7 +684,12 @@ ccl_device_inline float noise_scale4(float result)
|
|||
|
||||
ccl_device_inline float snoise_1d(float p)
|
||||
{
|
||||
return noise_scale1(ensure_finite(perlin_1d(p)));
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. */
|
||||
/* The 1D variant of fmod is called fmodf. */
|
||||
p = fmodf(p, 100000.0f);
|
||||
|
||||
return noise_scale1(perlin_1d(p));
|
||||
}
|
||||
|
||||
ccl_device_inline float noise_1d(float p)
|
||||
|
@ -694,7 +699,12 @@ ccl_device_inline float noise_1d(float p)
|
|||
|
||||
ccl_device_inline float snoise_2d(float2 p)
|
||||
{
|
||||
return noise_scale2(ensure_finite(perlin_2d(p.x, p.y)));
|
||||
/* Repeat Perlin noise texture every 100000.0f on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0f, however at such scales
|
||||
* this usually shouldn't be noticeable. */
|
||||
p = fmod(p, 100000.0f);
|
||||
|
||||
return noise_scale2(perlin_2d(p.x, p.y));
|
||||
}
|
||||
|
||||
ccl_device_inline float noise_2d(float2 p)
|
||||
|
@ -704,7 +714,12 @@ ccl_device_inline float noise_2d(float2 p)
|
|||
|
||||
ccl_device_inline float snoise_3d(float3 p)
|
||||
{
|
||||
return noise_scale3(ensure_finite(perlin_3d(p.x, p.y, p.z)));
|
||||
/* Repeat Perlin noise texture every 100000.0f on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0f, however at such scales
|
||||
* this usually shouldn't be noticeable. */
|
||||
p = fmod(p, 100000.0f);
|
||||
|
||||
return noise_scale3(perlin_3d(p.x, p.y, p.z));
|
||||
}
|
||||
|
||||
ccl_device_inline float noise_3d(float3 p)
|
||||
|
@ -714,7 +729,12 @@ ccl_device_inline float noise_3d(float3 p)
|
|||
|
||||
ccl_device_inline float snoise_4d(float4 p)
|
||||
{
|
||||
return noise_scale4(ensure_finite(perlin_4d(p.x, p.y, p.z, p.w)));
|
||||
/* Repeat Perlin noise texture every 100000.0f on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0f, however at such scales
|
||||
* this usually shouldn't be noticeable. */
|
||||
p = fmod(p, 100000.0f);
|
||||
|
||||
return noise_scale4(perlin_4d(p.x, p.y, p.z, p.w));
|
||||
}
|
||||
|
||||
ccl_device_inline float noise_4d(float4 p)
|
||||
|
|
|
@ -107,6 +107,7 @@ endif()
|
|||
if(WITH_CYCLES_OSL)
|
||||
list(APPEND LIB
|
||||
cycles_kernel_osl
|
||||
${OSL_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -198,6 +198,11 @@ ccl_device_inline float2 clamp(const float2 a, const float2 mn, const float2 mx)
|
|||
return min(max(a, mn), mx);
|
||||
}
|
||||
|
||||
ccl_device_inline float2 fmod(const float2 a, const float b)
|
||||
{
|
||||
return make_float2(fmodf(a.x, b), fmodf(a.y, b));
|
||||
}
|
||||
|
||||
ccl_device_inline float2 fabs(const float2 a)
|
||||
{
|
||||
return make_float2(fabsf(a.x), fabsf(a.y));
|
||||
|
|
|
@ -309,6 +309,11 @@ ccl_device_inline float3 fabs(const float3 a)
|
|||
# endif
|
||||
}
|
||||
|
||||
ccl_device_inline float3 fmod(const float3 a, const float b)
|
||||
{
|
||||
return make_float3(fmodf(a.x, b), fmodf(a.y, b), fmodf(a.z, b));
|
||||
}
|
||||
|
||||
ccl_device_inline float3 sqrt(const float3 a)
|
||||
{
|
||||
# ifdef __KERNEL_SSE__
|
||||
|
|
|
@ -465,6 +465,11 @@ ccl_device_inline float4 fabs(const float4 a)
|
|||
# endif
|
||||
}
|
||||
|
||||
ccl_device_inline float4 fmod(const float4 a, const float b)
|
||||
{
|
||||
return make_float4(fmodf(a.x, b), fmodf(a.y, b), fmodf(a.z, b), fmodf(a.w, b));
|
||||
}
|
||||
|
||||
ccl_device_inline float4 floor(const float4 a)
|
||||
{
|
||||
# ifdef __KERNEL_SSE__
|
||||
|
|
|
@ -210,7 +210,7 @@ rbCollisionShape *RB_shape_new_cylinder(float radius, float height);
|
|||
/* Setup (Convex Hull) ------------ */
|
||||
|
||||
rbCollisionShape *RB_shape_new_convex_hull(
|
||||
float *verts, int stride, int count, float margin, bool *can_embed);
|
||||
const float *verts, int stride, int count, float margin, bool *can_embed);
|
||||
|
||||
/* Setup (Triangle Mesh) ---------- */
|
||||
|
||||
|
@ -244,7 +244,7 @@ float RB_shape_get_margin(rbCollisionShape *shape);
|
|||
void RB_shape_set_margin(rbCollisionShape *shape, float value);
|
||||
|
||||
void RB_shape_trimesh_update(rbCollisionShape *shape,
|
||||
float *vertices,
|
||||
const float *vertices,
|
||||
int num_verts,
|
||||
int vert_stride,
|
||||
const float min[3],
|
||||
|
|
|
@ -712,7 +712,7 @@ rbCollisionShape *RB_shape_new_cylinder(float radius, float height)
|
|||
/* Setup (Convex Hull) ------------ */
|
||||
|
||||
rbCollisionShape *RB_shape_new_convex_hull(
|
||||
float *verts, int stride, int count, float margin, bool *can_embed)
|
||||
const float *verts, int stride, int count, float margin, bool *can_embed)
|
||||
{
|
||||
btConvexHullComputer hull_computer = btConvexHullComputer();
|
||||
|
||||
|
@ -800,7 +800,7 @@ rbCollisionShape *RB_shape_new_trimesh(rbMeshData *mesh)
|
|||
}
|
||||
|
||||
void RB_shape_trimesh_update(rbCollisionShape *shape,
|
||||
float *vertices,
|
||||
const float *vertices,
|
||||
int num_verts,
|
||||
int vert_stride,
|
||||
const float min[3],
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 1d44611dd36032c1889c66d673801ef7d699f592
|
||||
Subproject commit 0b910c0a718a1d54d07ecf95c63617576ee9a847
|
Binary file not shown.
|
@ -23,7 +23,10 @@ from bpy.props import (
|
|||
EnumProperty,
|
||||
StringProperty,
|
||||
)
|
||||
from bpy.app.translations import pgettext_data as data_
|
||||
from bpy.app.translations import (
|
||||
pgettext_iface as iface_,
|
||||
pgettext_data as data_,
|
||||
)
|
||||
|
||||
|
||||
def _check_axis_conversion(op):
|
||||
|
@ -96,12 +99,29 @@ class ImportHelper:
|
|||
description="Filepath used for importing the file",
|
||||
maxlen=1024,
|
||||
subtype='FILE_PATH',
|
||||
options={'SKIP_PRESET', 'HIDDEN'}
|
||||
)
|
||||
|
||||
def invoke(self, context, _event):
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
def invoke_popup(self, context, confirm_text=""):
|
||||
if self.properties.is_property_set("filepath"):
|
||||
title = self.filepath
|
||||
if len(self.files) > 1:
|
||||
title = iface_("Import {} files").format(len(self.files))
|
||||
|
||||
if not confirm_text:
|
||||
confirm_text = self.bl_label
|
||||
|
||||
confirm_text = iface_(confirm_text)
|
||||
return context.window_manager.invoke_props_dialog(
|
||||
self, confirm_text=confirm_text, title=title, translate=False)
|
||||
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
def check(self, _context):
|
||||
return _check_axis_conversion(self)
|
||||
|
||||
|
@ -394,6 +414,19 @@ def unpack_face_list(list_of_tuples):
|
|||
return flat_ls
|
||||
|
||||
|
||||
def poll_file_object_drop(context):
|
||||
"""
|
||||
A default implementation for FileHandler poll_drop methods. Allows for both the 3D Viewport and
|
||||
the Outliner (in ViewLayer display mode) to be targets for file drag and drop.
|
||||
"""
|
||||
area = context.area
|
||||
if not area:
|
||||
return False
|
||||
is_v3d = area.type == 'VIEW_3D'
|
||||
is_outliner_view_layer = area.type == 'OUTLINER' and area.spaces.active.display_mode == 'VIEW_LAYER'
|
||||
return is_v3d or is_outliner_view_layer
|
||||
|
||||
|
||||
path_reference_mode = EnumProperty(
|
||||
name="Path Mode",
|
||||
description="Method used to reference paths",
|
||||
|
|
|
@ -2330,8 +2330,7 @@ def km_file_browser(params):
|
|||
("file.next", {"type": 'BACK_SPACE', "value": 'PRESS', "shift": True}, None),
|
||||
("wm.context_toggle", {"type": 'H', "value": 'PRESS'},
|
||||
{"properties": [("data_path", 'space_data.params.show_hidden')]}),
|
||||
("file.directory_new", {"type": 'I', "value": 'PRESS'},
|
||||
{"properties": [("confirm", False)]}),
|
||||
("file.directory_new", {"type": 'I', "value": 'PRESS'}, None),
|
||||
("file.rename", {"type": 'F2', "value": 'PRESS'}, None),
|
||||
("file.delete", {"type": 'X', "value": 'PRESS'}, None),
|
||||
("file.delete", {"type": 'DEL', "value": 'PRESS'}, None),
|
||||
|
@ -7917,6 +7916,21 @@ def km_3d_view_tool_sculpt_lasso_hide(params):
|
|||
)
|
||||
|
||||
|
||||
def km_3d_view_tool_sculpt_line_hide(params):
|
||||
return (
|
||||
"3D View Tool: Sculpt, Line Hide",
|
||||
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
|
||||
{"items": [
|
||||
("paint.hide_show_line_gesture", params.tool_maybe_tweak_event,
|
||||
{"properties": [("action", 'HIDE')]}),
|
||||
("paint.hide_show_line_gesture", {**params.tool_maybe_tweak_event, "ctrl": True},
|
||||
{"properties": [("action", 'SHOW')]}),
|
||||
("paint.hide_show_all", {"type": params.select_mouse, "value": params.select_mouse_value},
|
||||
{"properties": [("action", 'SHOW')]}),
|
||||
]},
|
||||
)
|
||||
|
||||
|
||||
def km_3d_view_tool_sculpt_box_mask(params):
|
||||
return (
|
||||
"3D View Tool: Sculpt, Box Mask",
|
||||
|
@ -8763,6 +8777,7 @@ def generate_keymaps(params=None):
|
|||
km_3d_view_tool_edit_curves_draw(params),
|
||||
km_3d_view_tool_sculpt_box_hide(params),
|
||||
km_3d_view_tool_sculpt_lasso_hide(params),
|
||||
km_3d_view_tool_sculpt_line_hide(params),
|
||||
km_3d_view_tool_sculpt_box_mask(params),
|
||||
km_3d_view_tool_sculpt_lasso_mask(params),
|
||||
km_3d_view_tool_sculpt_box_face_set(params),
|
||||
|
|
|
@ -1240,8 +1240,7 @@ def km_file_browser(params):
|
|||
("file.next", {"type": 'BACK_SPACE', "value": 'PRESS', "shift": True}, None),
|
||||
("wm.context_toggle", {"type": 'H', "value": 'PRESS'},
|
||||
{"properties": [("data_path", 'space_data.params.show_hidden')]}),
|
||||
("file.directory_new", {"type": 'I', "value": 'PRESS'},
|
||||
{"properties": [("confirm", False)]}),
|
||||
("file.directory_new", {"type": 'I', "value": 'PRESS'}, None),
|
||||
("file.rename", {"type": 'F2', "value": 'PRESS'}, None),
|
||||
("file.delete", {"type": 'DEL', "value": 'PRESS'}, None),
|
||||
("file.smoothscroll", {"type": 'TIMER1', "value": 'ANY', "any": True}, None),
|
||||
|
|
|
@ -530,11 +530,12 @@ class ARMATURE_OT_copy_bone_color_to_selected(Operator):
|
|||
|
||||
|
||||
def _armature_from_context(context):
|
||||
pin_armature = getattr(context, 'armature', None)
|
||||
pin_armature = getattr(context, "armature", None)
|
||||
if pin_armature:
|
||||
return pin_armature
|
||||
if context.object and context.object.type == 'ARMATURE':
|
||||
return context.object.data
|
||||
ob = context.object
|
||||
if ob and ob.type == 'ARMATURE':
|
||||
return ob.data
|
||||
return None
|
||||
|
||||
|
||||
|
|
|
@ -270,8 +270,8 @@ class WM_OT_blend_strings_utf8_validate(Operator):
|
|||
continue
|
||||
if prop.type == 'STRING':
|
||||
val_bytes = item.path_resolve(prop.identifier, False).as_bytes()
|
||||
val_utf8 = val_bytes.decode('utf-8', 'replace')
|
||||
val_bytes_valid = val_utf8.encode('utf-8')
|
||||
val_utf8 = val_bytes.decode("utf-8", "replace")
|
||||
val_bytes_valid = val_utf8.encode("utf-8")
|
||||
if val_bytes_valid != val_bytes:
|
||||
print("found bad utf8 encoded string %r, fixing to %r (%r)..."
|
||||
"" % (val_bytes, val_bytes_valid, val_utf8))
|
||||
|
|
|
@ -48,7 +48,8 @@ def geometry_node_group_empty_tool_new(context):
|
|||
group.use_fake_user = True
|
||||
group.is_tool = True
|
||||
|
||||
ob_type = context.object.type if context.object else 'MESH'
|
||||
ob = context.object
|
||||
ob_type = ob.type if ob else 'MESH'
|
||||
if ob_type == 'CURVES':
|
||||
group.is_type_curve = True
|
||||
elif ob_type == 'POINTCLOUD':
|
||||
|
@ -56,7 +57,7 @@ def geometry_node_group_empty_tool_new(context):
|
|||
else:
|
||||
group.is_type_mesh = True
|
||||
|
||||
mode = context.object.mode if context.object else 'OBJECT'
|
||||
mode = ob.mode if ob else 'OBJECT'
|
||||
if mode in {'SCULPT', 'SCULPT_CURVES'}:
|
||||
group.is_mode_sculpt = True
|
||||
elif mode == 'EDIT':
|
||||
|
|
|
@ -145,7 +145,7 @@ class AddPresetBase:
|
|||
|
||||
file_preset.write("%s = %r\n" % (rna_path_step, value))
|
||||
|
||||
file_preset = open(filepath, 'w', encoding="utf-8")
|
||||
file_preset = open(filepath, "w", encoding="utf-8")
|
||||
file_preset.write("import bpy\n")
|
||||
|
||||
if hasattr(self, "preset_defines"):
|
||||
|
|
|
@ -674,7 +674,7 @@ class PREFERENCES_OT_addon_install(Operator):
|
|||
# check to see if the file is in compressed format (.zip)
|
||||
if zipfile.is_zipfile(pyfile):
|
||||
try:
|
||||
file_to_extract = zipfile.ZipFile(pyfile, 'r')
|
||||
file_to_extract = zipfile.ZipFile(pyfile, "r")
|
||||
except BaseException:
|
||||
traceback.print_exc()
|
||||
return {'CANCELLED'}
|
||||
|
@ -926,7 +926,7 @@ class PREFERENCES_OT_app_template_install(Operator):
|
|||
# check to see if the file is in compressed format (.zip)
|
||||
if zipfile.is_zipfile(filepath):
|
||||
try:
|
||||
file_to_extract = zipfile.ZipFile(filepath, 'r')
|
||||
file_to_extract = zipfile.ZipFile(filepath, "r")
|
||||
except BaseException:
|
||||
traceback.print_exc()
|
||||
return {'CANCELLED'}
|
||||
|
|
|
@ -31,10 +31,11 @@ class VIEW3D_OT_edit_mesh_extrude_individual_move(Operator):
|
|||
def execute(self, context):
|
||||
from bpy_extras.object_utils import object_report_if_active_shape_key_is_locked
|
||||
|
||||
if object_report_if_active_shape_key_is_locked(context.object, self):
|
||||
ob = context.object
|
||||
if object_report_if_active_shape_key_is_locked(ob, self):
|
||||
return {'CANCELLED'}
|
||||
|
||||
mesh = context.object.data
|
||||
mesh = ob.data
|
||||
select_mode = context.tool_settings.mesh_select_mode
|
||||
|
||||
totface = mesh.total_face_sel
|
||||
|
@ -99,10 +100,11 @@ class VIEW3D_OT_edit_mesh_extrude_move(Operator):
|
|||
def extrude_region(operator, context, use_vert_normals, dissolve_and_intersect):
|
||||
from bpy_extras.object_utils import object_report_if_active_shape_key_is_locked
|
||||
|
||||
if object_report_if_active_shape_key_is_locked(context.object, operator):
|
||||
ob = context.object
|
||||
if object_report_if_active_shape_key_is_locked(ob, operator):
|
||||
return {'CANCELLED'}
|
||||
|
||||
mesh = context.object.data
|
||||
mesh = ob.data
|
||||
|
||||
totface = mesh.total_face_sel
|
||||
totedge = mesh.total_edge_sel
|
||||
|
|
|
@ -3367,10 +3367,13 @@ class WM_MT_splash_about(Menu):
|
|||
col.scale_y = 0.8
|
||||
col.label(text=iface_("Version: %s") % bpy.app.version_string, translate=False)
|
||||
col.separator(factor=2.5)
|
||||
col.label(text=iface_("Date: %s %s") % (bpy.app.build_commit_date.decode('utf-8', 'replace'),
|
||||
bpy.app.build_commit_time.decode('utf-8', 'replace')), translate=False)
|
||||
col.label(text=iface_("Hash: %s") % bpy.app.build_hash.decode('ascii'), translate=False)
|
||||
col.label(text=iface_("Branch: %s") % bpy.app.build_branch.decode('utf-8', 'replace'), translate=False)
|
||||
col.label(text=iface_("Date: %s %s") % (
|
||||
bpy.app.build_commit_date.decode("utf-8", "replace"),
|
||||
bpy.app.build_commit_time.decode("utf-8", "replace")),
|
||||
translate=False
|
||||
)
|
||||
col.label(text=iface_("Hash: %s") % bpy.app.build_hash.decode("ascii"), translate=False)
|
||||
col.label(text=iface_("Branch: %s") % bpy.app.build_branch.decode("utf-8", "replace"), translate=False)
|
||||
|
||||
# This isn't useful information on MS-Windows or Apple systems as dynamically switching
|
||||
# between windowing systems is only supported between X11/WAYLAND.
|
||||
|
|
|
@ -82,7 +82,8 @@ class GREASE_PENCIL_MT_grease_pencil_add_layer_extra(Menu):
|
|||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
grease_pencil = context.object.data
|
||||
ob = context.object
|
||||
grease_pencil = ob.data
|
||||
space = context.space_data
|
||||
|
||||
if space.type == 'PROPERTIES':
|
||||
|
|
|
@ -417,20 +417,23 @@ class AnnotationDataPanel:
|
|||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw_header(self, context):
|
||||
if context.space_data.type not in {
|
||||
space = context.space_data
|
||||
if space.type not in {
|
||||
'VIEW_3D',
|
||||
'TOPBAR',
|
||||
'SEQUENCE_EDITOR',
|
||||
'IMAGE_EDITOR',
|
||||
'NODE_EDITOR',
|
||||
'PROPERTIES'}:
|
||||
self.layout.prop(context.space_data, "show_annotation", text="")
|
||||
'PROPERTIES',
|
||||
}:
|
||||
self.layout.prop(space, "show_annotation", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_decorate = False
|
||||
space = context.space_data
|
||||
|
||||
is_clip_editor = context.space_data.type == 'CLIP_EDITOR'
|
||||
is_clip_editor = space.type == 'CLIP_EDITOR'
|
||||
|
||||
# Grease Pencil owner.
|
||||
gpd_owner = context.annotation_data_owner
|
||||
|
@ -441,7 +444,7 @@ class AnnotationDataPanel:
|
|||
col = layout.column()
|
||||
col.label(text="Data Source:")
|
||||
row = col.row()
|
||||
row.prop(context.space_data, "annotation_source", expand=True)
|
||||
row.prop(space, "annotation_source", expand=True)
|
||||
|
||||
# Only allow adding annotation ID if its owner exist
|
||||
if context.annotation_data_owner is None:
|
||||
|
|
|
@ -1480,6 +1480,10 @@ def brush_basic_grease_pencil_paint_settings(layout, context, brush, *, compact=
|
|||
if gp_settings.eraser_mode == "HARD":
|
||||
layout.prop(gp_settings, "use_keep_caps_eraser")
|
||||
layout.prop(gp_settings, "use_active_layer_only")
|
||||
elif grease_pencil_tool == 'TINT':
|
||||
layout.prop(gp_settings, "vertex_mode", text="Mode")
|
||||
layout.popover("VIEW3D_PT_tools_brush_settings_advanced", text="Brush")
|
||||
layout.popover("VIEW3D_PT_tools_brush_falloff")
|
||||
|
||||
|
||||
def brush_basic_gpencil_sculpt_settings(layout, _context, brush, *, compact=False):
|
||||
|
|
|
@ -258,9 +258,9 @@ class ToolSelectPanelHelper:
|
|||
|
||||
# tool flattening
|
||||
#
|
||||
# usually 'tools' is already expanded into `ToolDef`
|
||||
# usually "tools" is already expanded into `ToolDef`
|
||||
# but when registering a tool, this can still be a function
|
||||
# (_tools_flatten is usually called with cls.tools_from_context(context)
|
||||
# (`_tools_flatten` is usually called with `cls.tools_from_context(context)`
|
||||
# [that already yields from the function])
|
||||
# so if item is still a function (e.g._defs_XXX.generate_from_brushes)
|
||||
# seems like we cannot expand here (have no context yet)
|
||||
|
|
|
@ -1423,6 +1423,21 @@ class _defs_sculpt:
|
|||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def hide_line():
|
||||
def draw_settings(_context, layout, tool):
|
||||
props = tool.operator_properties("paint.hide_show_line_gesture")
|
||||
layout.prop(props, "use_limit_to_segment", expand=False)
|
||||
|
||||
return dict(
|
||||
idname="builtin.line_hide",
|
||||
label="Line Hide",
|
||||
icon="ops.sculpt.line_hide",
|
||||
widget=None,
|
||||
keymap=(),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def mask_border():
|
||||
def draw_settings(_context, layout, tool):
|
||||
|
@ -1862,6 +1877,15 @@ class _defs_paint_grease_pencil:
|
|||
data_block='ERASE',
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def tint():
|
||||
return dict(
|
||||
idname="builtin_brush.Tint",
|
||||
label="Tint",
|
||||
icon="brush.gpencil_draw.tint",
|
||||
data_block='TINT',
|
||||
)
|
||||
|
||||
|
||||
class _defs_image_generic:
|
||||
|
||||
|
@ -3162,7 +3186,8 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
|
|||
),
|
||||
(
|
||||
_defs_sculpt.hide_border,
|
||||
_defs_sculpt.hide_lasso
|
||||
_defs_sculpt.hide_lasso,
|
||||
_defs_sculpt.hide_line,
|
||||
),
|
||||
(
|
||||
_defs_sculpt.face_set_box,
|
||||
|
@ -3235,6 +3260,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
|
|||
None,
|
||||
_defs_paint_grease_pencil.draw,
|
||||
_defs_paint_grease_pencil.erase,
|
||||
_defs_paint_grease_pencil.tint,
|
||||
],
|
||||
'PAINT_GPENCIL': [
|
||||
_defs_view3d_generic.cursor,
|
||||
|
|
|
@ -409,27 +409,27 @@ class USERPREF_PT_edit_objects_duplicate_data(EditingPanel, CenterAlignMixIn, Pa
|
|||
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
|
||||
|
||||
datablock_types = (
|
||||
("use_duplicate_action", "Action", 'ACTION', ''),
|
||||
("use_duplicate_armature", "Armature", 'OUTLINER_DATA_ARMATURE', ''),
|
||||
("use_duplicate_camera", "Camera", 'OUTLINER_DATA_CAMERA', ''),
|
||||
("use_duplicate_curve", "Curve", 'OUTLINER_DATA_CURVE', ''),
|
||||
("use_duplicate_curves", "Curves", 'OUTLINER_DATA_CURVES', ''),
|
||||
("use_duplicate_grease_pencil", "Grease Pencil", 'OUTLINER_OB_GREASEPENCIL', ''),
|
||||
("use_duplicate_lattice", "Lattice", 'OUTLINER_DATA_LATTICE', ''),
|
||||
("use_duplicate_action", "Action", 'ACTION', ""),
|
||||
("use_duplicate_armature", "Armature", 'OUTLINER_DATA_ARMATURE', ""),
|
||||
("use_duplicate_camera", "Camera", 'OUTLINER_DATA_CAMERA', ""),
|
||||
("use_duplicate_curve", "Curve", 'OUTLINER_DATA_CURVE', ""),
|
||||
("use_duplicate_curves", "Curves", 'OUTLINER_DATA_CURVES', ""),
|
||||
("use_duplicate_grease_pencil", "Grease Pencil", 'OUTLINER_OB_GREASEPENCIL', ""),
|
||||
("use_duplicate_lattice", "Lattice", 'OUTLINER_DATA_LATTICE', ""),
|
||||
(None, None, None, None),
|
||||
("use_duplicate_light", "Light", 'OUTLINER_DATA_LIGHT', ''),
|
||||
("use_duplicate_lightprobe", "Light Probe", 'OUTLINER_DATA_LIGHTPROBE', ''),
|
||||
("use_duplicate_material", "Material", 'MATERIAL_DATA', ''),
|
||||
("use_duplicate_mesh", "Mesh", 'OUTLINER_DATA_MESH', ''),
|
||||
("use_duplicate_metaball", "Metaball", 'OUTLINER_DATA_META', ''),
|
||||
("use_duplicate_node_tree", "Node Tree", 'NODETREE', ''),
|
||||
("use_duplicate_particle", "Particle", 'PARTICLES', ''),
|
||||
("use_duplicate_light", "Light", 'OUTLINER_DATA_LIGHT', ""),
|
||||
("use_duplicate_lightprobe", "Light Probe", 'OUTLINER_DATA_LIGHTPROBE', ""),
|
||||
("use_duplicate_material", "Material", 'MATERIAL_DATA', ""),
|
||||
("use_duplicate_mesh", "Mesh", 'OUTLINER_DATA_MESH', ""),
|
||||
("use_duplicate_metaball", "Metaball", 'OUTLINER_DATA_META', ""),
|
||||
("use_duplicate_node_tree", "Node Tree", 'NODETREE', ""),
|
||||
("use_duplicate_particle", "Particle", 'PARTICLES', ""),
|
||||
(None, None, None, None),
|
||||
("use_duplicate_pointcloud", "Point Cloud", 'OUTLINER_DATA_POINTCLOUD', ''),
|
||||
("use_duplicate_speaker", "Speaker", 'OUTLINER_DATA_SPEAKER', ''),
|
||||
("use_duplicate_surface", "Surface", 'OUTLINER_DATA_SURFACE', ''),
|
||||
("use_duplicate_text", "Text", 'OUTLINER_DATA_FONT', ''),
|
||||
("use_duplicate_volume", "Volume", 'OUTLINER_DATA_VOLUME', 'i18n_contexts.id_id'),
|
||||
("use_duplicate_pointcloud", "Point Cloud", 'OUTLINER_DATA_POINTCLOUD', ""),
|
||||
("use_duplicate_speaker", "Speaker", 'OUTLINER_DATA_SPEAKER', ""),
|
||||
("use_duplicate_surface", "Surface", 'OUTLINER_DATA_SURFACE', ""),
|
||||
("use_duplicate_text", "Text", 'OUTLINER_DATA_FONT', ""),
|
||||
("use_duplicate_volume", "Volume", 'OUTLINER_DATA_VOLUME', "i18n_contexts.id_id"),
|
||||
)
|
||||
|
||||
col = flow.column()
|
||||
|
@ -2727,7 +2727,7 @@ class USERPREF_PT_experimental_debugging(ExperimentalPanel, Panel):
|
|||
# Class Registration
|
||||
|
||||
# Order of registration defines order in UI,
|
||||
# so dynamically generated classes are 'injected' in the intended order.
|
||||
# so dynamically generated classes are "injected" in the intended order.
|
||||
classes = (
|
||||
USERPREF_PT_theme_user_interface,
|
||||
*ThemeGenericClassGenerator.generate_panel_classes_for_wcols(),
|
||||
|
|
|
@ -139,17 +139,20 @@ class VIEW3D_HT_tool_header(Header):
|
|||
return row, sub
|
||||
|
||||
if mode_string == 'EDIT_ARMATURE':
|
||||
ob = context.object
|
||||
_row, sub = row_for_mirror()
|
||||
sub.prop(context.object.data, "use_mirror_x", text="X", toggle=True)
|
||||
sub.prop(ob.data, "use_mirror_x", text="X", toggle=True)
|
||||
elif mode_string == 'POSE':
|
||||
ob = context.object
|
||||
_row, sub = row_for_mirror()
|
||||
sub.prop(context.object.pose, "use_mirror_x", text="X", toggle=True)
|
||||
sub.prop(ob.pose, "use_mirror_x", text="X", toggle=True)
|
||||
elif mode_string in {'EDIT_MESH', 'PAINT_WEIGHT', 'SCULPT', 'PAINT_VERTEX', 'PAINT_TEXTURE'}:
|
||||
# Mesh Modes, Use Mesh Symmetry
|
||||
ob = context.object
|
||||
row, sub = row_for_mirror()
|
||||
sub.prop(context.object, "use_mesh_mirror_x", text="X", toggle=True)
|
||||
sub.prop(context.object, "use_mesh_mirror_y", text="Y", toggle=True)
|
||||
sub.prop(context.object, "use_mesh_mirror_z", text="Z", toggle=True)
|
||||
sub.prop(ob, "use_mesh_mirror_x", text="X", toggle=True)
|
||||
sub.prop(ob, "use_mesh_mirror_y", text="Y", toggle=True)
|
||||
sub.prop(ob, "use_mesh_mirror_z", text="Z", toggle=True)
|
||||
if mode_string == 'EDIT_MESH':
|
||||
tool_settings = context.tool_settings
|
||||
layout.prop(tool_settings, "use_mesh_automerge", text="")
|
||||
|
@ -160,12 +163,13 @@ class VIEW3D_HT_tool_header(Header):
|
|||
elif mode_string == 'PAINT_VERTEX':
|
||||
row.popover(panel="VIEW3D_PT_tools_vertexpaint_symmetry_for_topbar", text="")
|
||||
elif mode_string == 'SCULPT_CURVES':
|
||||
ob = context.object
|
||||
_row, sub = row_for_mirror()
|
||||
sub.prop(context.object.data, "use_mirror_x", text="X", toggle=True)
|
||||
sub.prop(context.object.data, "use_mirror_y", text="Y", toggle=True)
|
||||
sub.prop(context.object.data, "use_mirror_z", text="Z", toggle=True)
|
||||
sub.prop(ob.data, "use_mirror_x", text="X", toggle=True)
|
||||
sub.prop(ob.data, "use_mirror_y", text="Y", toggle=True)
|
||||
sub.prop(ob.data, "use_mirror_z", text="Z", toggle=True)
|
||||
|
||||
layout.prop(context.object.data, "use_sculpt_collision", icon='MOD_PHYSICS', icon_only=True, toggle=True)
|
||||
layout.prop(ob.data, "use_sculpt_collision", icon='MOD_PHYSICS', icon_only=True, toggle=True)
|
||||
|
||||
# Expand panels from the side-bar as popovers.
|
||||
popover_kw = {"space_type": 'VIEW_3D', "region_type": 'UI', "category": "Tool"}
|
||||
|
@ -373,19 +377,20 @@ class _draw_tool_settings_context_mode:
|
|||
if brush is None:
|
||||
return False
|
||||
|
||||
ob = context.object
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
row = layout.row(align=True)
|
||||
settings = tool_settings.gpencil_paint
|
||||
row.template_ID_preview(settings, "brush", rows=3, cols=8, hide_buttons=True)
|
||||
|
||||
if context.object and brush.gpencil_tool in {'FILL', 'DRAW'}:
|
||||
if ob and brush.gpencil_tool in {'FILL', 'DRAW'}:
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic__draw_color_selector,
|
||||
)
|
||||
brush_basic__draw_color_selector(context, layout, brush, gp_settings, None)
|
||||
|
||||
if context.object and brush.gpencil_tool == 'TINT':
|
||||
if ob and brush.gpencil_tool == 'TINT':
|
||||
row.separator(factor=0.4)
|
||||
row.prop_with_popover(brush, "color", text="", panel="TOPBAR_PT_gpencil_vertexcolor")
|
||||
|
||||
|
@ -604,6 +609,9 @@ class _draw_tool_settings_context_mode:
|
|||
)
|
||||
brush_basic__draw_color_selector(context, layout, brush, brush.gpencil_settings, None)
|
||||
|
||||
if grease_pencil_tool == 'TINT':
|
||||
UnifiedPaintPanel.prop_unified_color(row, context, brush, "color", text="")
|
||||
|
||||
from bl_ui.properties_paint_common import (
|
||||
brush_basic__draw_color_selector,
|
||||
brush_basic_grease_pencil_paint_settings,
|
||||
|
@ -2717,6 +2725,8 @@ class VIEW3D_MT_object(Menu):
|
|||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
ob = context.object
|
||||
|
||||
layout.menu("VIEW3D_MT_transform_object")
|
||||
layout.operator_menu_enum("object.origin_set", text="Set Origin", property="type")
|
||||
layout.menu("VIEW3D_MT_mirror")
|
||||
|
@ -2752,7 +2762,7 @@ class VIEW3D_MT_object(Menu):
|
|||
layout.separator()
|
||||
|
||||
layout.operator("object.shade_smooth")
|
||||
if context.object and context.object.type == 'MESH':
|
||||
if ob and ob.type == 'MESH':
|
||||
layout.operator("object.shade_smooth_by_angle")
|
||||
layout.operator("object.shade_flat")
|
||||
|
||||
|
@ -3568,6 +3578,12 @@ class VIEW3D_MT_sculpt(Menu):
|
|||
props = layout.operator("paint.hide_show_lasso_gesture", text="Lasso Show")
|
||||
props.action = 'SHOW'
|
||||
|
||||
props = layout.operator("paint.hide_show_line_gesture", text="Line Hide")
|
||||
props.action = 'HIDE'
|
||||
|
||||
props = layout.operator("paint.hide_show_line_gesture", text="Line Show")
|
||||
props.action = 'SHOW'
|
||||
|
||||
layout.separator()
|
||||
|
||||
props = layout.operator("sculpt.face_set_change_visibility", text="Toggle Visibility")
|
||||
|
@ -4078,9 +4094,10 @@ class VIEW3D_MT_bone_collections(Menu):
|
|||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if not context.object or context.object.type != 'ARMATURE':
|
||||
ob = context.object
|
||||
if not (ob and ob.type == 'ARMATURE'):
|
||||
return False
|
||||
if context.object.data.library:
|
||||
if ob.data.library:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
@ -4534,7 +4551,8 @@ class VIEW3D_MT_edit_mesh_extrude(Menu):
|
|||
|
||||
tool_settings = context.tool_settings
|
||||
select_mode = tool_settings.mesh_select_mode
|
||||
mesh = context.object.data
|
||||
ob = context.object
|
||||
mesh = ob.data
|
||||
|
||||
if mesh.total_face_sel:
|
||||
layout.operator("view3d.edit_mesh_extrude_move_normal", text="Extrude Faces")
|
||||
|
@ -7728,13 +7746,16 @@ class VIEW3D_PT_overlay_gpencil_options(Panel):
|
|||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.object and context.object.type == 'GPENCIL'
|
||||
ob = context.object
|
||||
return ob and ob.type == 'GPENCIL'
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
view = context.space_data
|
||||
overlay = view.overlay
|
||||
|
||||
ob = context.object
|
||||
|
||||
layout.label(text={
|
||||
'PAINT_GPENCIL': iface_("Draw Grease Pencil"),
|
||||
'EDIT_GPENCIL': iface_("Edit Grease Pencil"),
|
||||
|
@ -7767,15 +7788,15 @@ class VIEW3D_PT_overlay_gpencil_options(Panel):
|
|||
sub.prop(overlay, "gpencil_fade_objects", text="Fade Inactive Objects", slider=True)
|
||||
sub.prop(overlay, "use_gpencil_fade_gp_objects", text="", icon='OUTLINER_OB_GREASEPENCIL')
|
||||
|
||||
if context.object.mode in {'EDIT_GPENCIL', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL', 'VERTEX_GPENCIL'}:
|
||||
if ob.mode in {'EDIT_GPENCIL', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL', 'VERTEX_GPENCIL'}:
|
||||
split = layout.split()
|
||||
col = split.column()
|
||||
col.prop(overlay, "use_gpencil_edit_lines", text="Edit Lines")
|
||||
col = split.column()
|
||||
col.prop(overlay, "use_gpencil_multiedit_line_only", text="Only in Multiframe")
|
||||
|
||||
if context.object.mode == 'EDIT_GPENCIL':
|
||||
gpd = context.object.data
|
||||
if ob.mode == 'EDIT_GPENCIL':
|
||||
gpd = ob.data
|
||||
split = layout.split()
|
||||
col = split.column()
|
||||
col.prop(overlay, "use_gpencil_show_directions")
|
||||
|
@ -7788,10 +7809,10 @@ class VIEW3D_PT_overlay_gpencil_options(Panel):
|
|||
# Handles for Curve Edit
|
||||
layout.prop(overlay, "display_handle", text="Handles")
|
||||
|
||||
if context.object.mode == 'SCULPT_GPENCIL':
|
||||
if ob.mode == 'SCULPT_GPENCIL':
|
||||
layout.prop(overlay, "vertex_opacity", text="Vertex Opacity", slider=True)
|
||||
|
||||
if context.object.mode in {'PAINT_GPENCIL', 'VERTEX_GPENCIL'}:
|
||||
if ob.mode in {'PAINT_GPENCIL', 'VERTEX_GPENCIL'}:
|
||||
layout.label(text="Vertex Paint")
|
||||
row = layout.row()
|
||||
shading = VIEW3D_PT_shading.get_shading(context)
|
||||
|
@ -7807,20 +7828,23 @@ class VIEW3D_PT_overlay_grease_pencil_options(Panel):
|
|||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.object and context.object.type == 'GREASEPENCIL'
|
||||
ob = context.object
|
||||
return ob and ob.type == 'GREASEPENCIL'
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
view = context.space_data
|
||||
overlay = view.overlay
|
||||
|
||||
ob = context.object
|
||||
|
||||
layout.label(text={
|
||||
'PAINT_GREASE_PENCIL': iface_("Draw Grease Pencil"),
|
||||
'EDIT_GREASE_PENCIL': iface_("Edit Grease Pencil"),
|
||||
'OBJECT': iface_("Grease Pencil"),
|
||||
}[context.mode], translate=False)
|
||||
|
||||
if context.object.mode in {'EDIT'}:
|
||||
if ob.mode in {'EDIT'}:
|
||||
split = layout.split()
|
||||
col = split.column()
|
||||
col.prop(overlay, "use_gpencil_edit_lines", text="Edit Lines")
|
||||
|
@ -8706,7 +8730,7 @@ class TOPBAR_PT_gpencil_materials(GreasePencilMaterialsPanel, Panel):
|
|||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
return ob and (ob.type == 'GPENCIL' or ob.type == 'GREASEPENCIL')
|
||||
return ob and ob.type in {'GPENCIL', 'GREASEPENCIL'}
|
||||
|
||||
|
||||
class TOPBAR_PT_gpencil_vertexcolor(GreasePencilVertexcolorPanel, Panel):
|
||||
|
|
|
@ -610,7 +610,7 @@ class VIEW3D_PT_slots_paint_canvas(SelectPaintSlotHelper, View3DPanel, Panel):
|
|||
def draw_header(self, context):
|
||||
paint = context.tool_settings.paint_mode
|
||||
ob = context.object
|
||||
me = context.object.data
|
||||
me = ob.data
|
||||
mat = ob.active_material
|
||||
|
||||
label = iface_("Canvas")
|
||||
|
@ -641,7 +641,8 @@ class VIEW3D_PT_slots_color_attributes(Panel):
|
|||
)
|
||||
|
||||
def draw(self, context):
|
||||
mesh = context.object.data
|
||||
ob = context.object
|
||||
mesh = ob.data
|
||||
|
||||
layout = self.layout
|
||||
row = layout.row()
|
||||
|
@ -1119,7 +1120,9 @@ class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
|
|||
sculpt = context.tool_settings.sculpt
|
||||
|
||||
row = layout.row(align=True, heading="Mirror")
|
||||
mesh = context.object.data
|
||||
|
||||
ob = context.object
|
||||
mesh = ob.data
|
||||
row.prop(mesh, "use_mirror_x", text="X", toggle=True)
|
||||
row.prop(mesh, "use_mirror_y", text="Y", toggle=True)
|
||||
row.prop(mesh, "use_mirror_z", text="Z", toggle=True)
|
||||
|
@ -1162,14 +1165,16 @@ class VIEW3D_PT_curves_sculpt_symmetry(Panel, View3DPaintPanel):
|
|||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.object and context.object.type == 'CURVES'
|
||||
ob = context.object
|
||||
return ob and ob.type == 'CURVES'
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
curves = context.object.data
|
||||
ob = context.object
|
||||
curves = ob.data
|
||||
|
||||
row = layout.row(align=True, heading="Mirror")
|
||||
row.prop(curves, "use_mirror_x", text="X", toggle=True)
|
||||
|
@ -1206,11 +1211,13 @@ class VIEW3D_PT_tools_weightpaint_symmetry(Panel, View3DPaintPanel):
|
|||
|
||||
tool_settings = context.tool_settings
|
||||
wpaint = tool_settings.weight_paint
|
||||
mesh = context.object.data
|
||||
|
||||
ob = context.object
|
||||
mesh = ob.data
|
||||
|
||||
layout.prop(mesh, "use_mirror_vertex_groups")
|
||||
|
||||
draw_vpaint_symmetry(layout, wpaint, context.object)
|
||||
draw_vpaint_symmetry(layout, wpaint, ob)
|
||||
|
||||
row = layout.row()
|
||||
row.active = mesh.use_mirror_vertex_groups
|
||||
|
@ -1288,7 +1295,9 @@ class VIEW3D_PT_tools_vertexpaint_symmetry(Panel, View3DPaintPanel):
|
|||
tool_settings = context.tool_settings
|
||||
vpaint = tool_settings.vertex_paint
|
||||
|
||||
draw_vpaint_symmetry(layout, vpaint, context.object)
|
||||
ob = context.object
|
||||
|
||||
draw_vpaint_symmetry(layout, vpaint, ob)
|
||||
|
||||
|
||||
class VIEW3D_PT_tools_vertexpaint_symmetry_for_topbar(Panel):
|
||||
|
@ -1353,7 +1362,8 @@ class VIEW3D_PT_tools_imagepaint_symmetry(Panel, View3DPaintPanel):
|
|||
col = split.column()
|
||||
|
||||
row = col.row(align=True)
|
||||
mesh = context.object.data
|
||||
ob = context.object
|
||||
mesh = ob.data
|
||||
row.prop(mesh, "use_mirror_x", text="X", toggle=True)
|
||||
row.prop(mesh, "use_mirror_y", text="Y", toggle=True)
|
||||
row.prop(mesh, "use_mirror_z", text="Z", toggle=True)
|
||||
|
@ -1933,7 +1943,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_paint_falloff(GreasePencilBrushFalloff
|
|||
|
||||
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
|
||||
tool = ToolSelectPanelHelper.tool_active_from_context(context)
|
||||
if tool and tool.idname != 'builtin_brush.Tint':
|
||||
if tool and tool.idname != "builtin_brush.Tint":
|
||||
return False
|
||||
|
||||
gptool = brush.gpencil_tool
|
||||
|
@ -2344,7 +2354,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_mixcolor(View3DPanel, Panel):
|
|||
|
||||
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
|
||||
tool = ToolSelectPanelHelper.tool_active_from_context(context)
|
||||
if tool and tool.idname in {'builtin.cutter', 'builtin.eyedropper', 'builtin.interpolate'}:
|
||||
if tool and tool.idname in {"builtin.cutter", "builtin.eyedropper", "builtin.interpolate"}:
|
||||
return False
|
||||
|
||||
if brush.gpencil_tool == 'TINT':
|
||||
|
@ -2405,7 +2415,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_mix_palette(View3DPanel, Panel):
|
|||
|
||||
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
|
||||
tool = ToolSelectPanelHelper.tool_active_from_context(context)
|
||||
if tool and tool.idname in {'builtin.cutter', 'builtin.eyedropper', 'builtin.interpolate'}:
|
||||
if tool and tool.idname in {"builtin.cutter", "builtin.eyedropper", "builtin.interpolate"}:
|
||||
return False
|
||||
|
||||
if brush.gpencil_tool == 'TINT':
|
||||
|
@ -2570,7 +2580,7 @@ class VIEW3D_PT_tools_grease_pencil_v3_brush_mixcolor(View3DPanel, Panel):
|
|||
|
||||
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
|
||||
tool = ToolSelectPanelHelper.tool_active_from_context(context)
|
||||
if tool and tool.idname in {'builtin.cutter', 'builtin.eyedropper', 'builtin.interpolate'}:
|
||||
if tool and tool.idname in {"builtin.cutter", "builtin.eyedropper", "builtin.interpolate"}:
|
||||
return False
|
||||
|
||||
if brush.gpencil_tool == 'TINT':
|
||||
|
@ -2627,7 +2637,7 @@ class VIEW3D_PT_tools_grease_pencil_v3_brush_mix_palette(View3DPanel, Panel):
|
|||
|
||||
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
|
||||
tool = ToolSelectPanelHelper.tool_active_from_context(context)
|
||||
if tool and tool.idname in {'builtin.cutter', 'builtin.eyedropper', 'builtin.interpolate'}:
|
||||
if tool and tool.idname in {"builtin.cutter", "builtin.eyedropper", "builtin.interpolate"}:
|
||||
return False
|
||||
|
||||
if brush.gpencil_tool == 'TINT':
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <array>
|
||||
|
||||
#include "BLI_array.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
#include "DNA_customdata_types.h"
|
||||
|
||||
|
@ -103,14 +104,16 @@ BMEditMesh *BKE_editmesh_from_object(Object *ob);
|
|||
*/
|
||||
void BKE_editmesh_free_data(BMEditMesh *em);
|
||||
|
||||
float (*BKE_editmesh_vert_coords_alloc(
|
||||
Depsgraph *depsgraph, BMEditMesh *em, Scene *scene, Object *ob, int *r_vert_len))[3];
|
||||
float (*BKE_editmesh_vert_coords_alloc_orco(BMEditMesh *em, int *r_vert_len))[3];
|
||||
const float (*BKE_editmesh_vert_coords_when_deformed(Depsgraph *depsgraph,
|
||||
BMEditMesh *em,
|
||||
Scene *scene,
|
||||
Object *obedit,
|
||||
int *r_vert_len,
|
||||
bool *r_is_alloc))[3];
|
||||
blender::Array<blender::float3> BKE_editmesh_vert_coords_alloc(Depsgraph *depsgraph,
|
||||
BMEditMesh *em,
|
||||
Scene *scene,
|
||||
Object *ob);
|
||||
blender::Array<blender::float3> BKE_editmesh_vert_coords_alloc_orco(BMEditMesh *em);
|
||||
blender::Span<blender::float3> BKE_editmesh_vert_coords_when_deformed(
|
||||
Depsgraph *depsgraph,
|
||||
BMEditMesh *em,
|
||||
Scene *scene,
|
||||
Object *obedit,
|
||||
blender::Array<blender::float3> &r_alloc);
|
||||
|
||||
void BKE_editmesh_lnorspace_update(BMEditMesh *em);
|
||||
|
|
|
@ -18,13 +18,13 @@ namespace blender::bke {
|
|||
|
||||
struct EditMeshData {
|
||||
/** when set, \a vertexNos, faceNos are lazy initialized */
|
||||
Array<float3> vertexCos;
|
||||
Array<float3> vert_positions;
|
||||
|
||||
/** lazy initialize (when \a vertexCos is set) */
|
||||
Array<float3> vertexNos;
|
||||
Array<float3> faceNos;
|
||||
/** also lazy init but don't depend on \a vertexCos */
|
||||
Array<float3> faceCos;
|
||||
/** lazy initialize (when \a vert_positions is set) */
|
||||
Array<float3> vert_normals;
|
||||
Array<float3> face_normals;
|
||||
/** also lazy init but don't depend on \a vert_positions */
|
||||
Array<float3> face_centers;
|
||||
};
|
||||
|
||||
} // namespace blender::bke
|
||||
|
|
|
@ -199,7 +199,7 @@ Mesh *BKE_mesh_new_from_object_to_bmain(Main *bmain,
|
|||
void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob);
|
||||
void BKE_mesh_nomain_to_meshkey(Mesh *mesh_src, Mesh *mesh_dst, KeyBlock *kb);
|
||||
|
||||
/* vertex level transformations & checks (no derived mesh) */
|
||||
/* Vertex level transformations & checks (no evaluated mesh). */
|
||||
|
||||
/* basic vertex data functions */
|
||||
void BKE_mesh_transform(Mesh *mesh, const float mat[4][4], bool do_keys);
|
||||
|
|
|
@ -53,7 +53,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
|
|||
uint corner_tris_len,
|
||||
const blender::Span<bool> sharp_faces,
|
||||
|
||||
CustomData *loopdata,
|
||||
const CustomData *loopdata,
|
||||
bool calc_active_tangent,
|
||||
const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME],
|
||||
int tangent_names_len,
|
||||
|
@ -72,7 +72,7 @@ void BKE_mesh_calc_loop_tangents(Mesh *mesh_eval,
|
|||
int tangent_names_len);
|
||||
|
||||
/* Helpers */
|
||||
void BKE_mesh_add_loop_tangent_named_layer_for_uv(CustomData *uv_data,
|
||||
void BKE_mesh_add_loop_tangent_named_layer_for_uv(const CustomData *uv_data,
|
||||
CustomData *tan_data,
|
||||
int numLoopData,
|
||||
const char *layer_name);
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
struct BMEditMesh;
|
||||
struct BVHCache;
|
||||
struct Mesh;
|
||||
struct ShrinkwrapBoundaryData;
|
||||
class ShrinkwrapBoundaryData;
|
||||
struct SubdivCCG;
|
||||
struct SubsurfRuntimeData;
|
||||
namespace blender::bke {
|
||||
|
|
|
@ -26,15 +26,15 @@ int BKE_mesh_wrapper_face_len(const Mesh *mesh);
|
|||
|
||||
/**
|
||||
* Return a contiguous array of vertex position values, if available.
|
||||
* Otherwise, vertex positions are stored in BMesh vertices.
|
||||
* Otherwise, vertex positions are stored in BMesh vertices and this returns null.
|
||||
*/
|
||||
const float (*BKE_mesh_wrapper_vert_coords(const Mesh *mesh))[3];
|
||||
blender::Span<blender::float3> BKE_mesh_wrapper_vert_coords(const Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Return a contiguous array of face normal values, if available.
|
||||
* Otherwise, normals are stored in BMesh faces.
|
||||
* Otherwise, normals are stored in BMesh faces and this returns null.
|
||||
*/
|
||||
const float (*BKE_mesh_wrapper_face_normals(Mesh *mesh))[3];
|
||||
blender::Span<blender::float3> BKE_mesh_wrapper_face_normals(Mesh *mesh);
|
||||
|
||||
void BKE_mesh_wrapper_tag_positions_changed(Mesh *mesh);
|
||||
|
||||
|
|
|
@ -200,8 +200,8 @@ struct ModifierTypeInfo {
|
|||
/********************* Deform modifier functions *********************/
|
||||
|
||||
/**
|
||||
* Apply a deformation to the positions in the \a vertexCos array. If the \a mesh argument is
|
||||
* non-null, if will contain proper (not wrapped) mesh data. The \a vertexCos array may or may
|
||||
* Apply a deformation to the positions in the \a positions array. If the \a mesh argument is
|
||||
* non-null, if will contain proper (not wrapped) mesh data. The \a positions array may or may
|
||||
* not be the same as the mesh's position attribute.
|
||||
*/
|
||||
void (*deform_verts)(ModifierData *md,
|
||||
|
|
|
@ -242,11 +242,11 @@ Object *BKE_object_duplicate(Main *bmain,
|
|||
*/
|
||||
void BKE_object_obdata_size_init(Object *ob, float size);
|
||||
|
||||
void BKE_object_scale_to_mat3(Object *ob, float r_mat[3][3]);
|
||||
void BKE_object_scale_to_mat3(const Object *ob, float r_mat[3][3]);
|
||||
void BKE_object_rot_to_mat3(const Object *ob, float r_mat[3][3], bool use_drot);
|
||||
void BKE_object_mat3_to_rot(Object *ob, float r_mat[3][3], bool use_compat);
|
||||
void BKE_object_to_mat3(Object *ob, float r_mat[3][3]);
|
||||
void BKE_object_to_mat4(Object *ob, float r_mat[4][4]);
|
||||
void BKE_object_to_mat3(const Object *ob, float r_mat[3][3]);
|
||||
void BKE_object_to_mat4(const Object *ob, float r_mat[4][4]);
|
||||
/**
|
||||
* Applies the global transformation \a mat to the \a ob using a relative parent space if
|
||||
* supplied.
|
||||
|
@ -319,7 +319,7 @@ blender::Vector<Base *> BKE_object_pose_base_array_get(const Scene *scene,
|
|||
ViewLayer *view_layer,
|
||||
View3D *v3d);
|
||||
|
||||
void BKE_object_get_parent_matrix(Object *ob, Object *par, float r_parentmat[4][4]);
|
||||
void BKE_object_get_parent_matrix(const Object *ob, Object *par, float r_parentmat[4][4]);
|
||||
|
||||
/**
|
||||
* Compute object world transform and store it in `ob->object_to_world().ptr()`.
|
||||
|
@ -334,7 +334,7 @@ void BKE_object_where_is_calc_time(Depsgraph *depsgraph, Scene *scene, Object *o
|
|||
* No changes to object and its parent would be done.
|
||||
* Used for bundles orientation in 3d space relative to parented blender camera.
|
||||
*/
|
||||
void BKE_object_where_is_calc_mat4(Object *ob, float r_obmat[4][4]);
|
||||
void BKE_object_where_is_calc_mat4(const Object *ob, float r_obmat[4][4]);
|
||||
|
||||
/* Possibly belong in its own module? */
|
||||
|
||||
|
@ -522,8 +522,9 @@ Mesh *BKE_object_get_pre_modified_mesh(const Object *object);
|
|||
*/
|
||||
Mesh *BKE_object_get_original_mesh(const Object *object);
|
||||
|
||||
Mesh *BKE_object_get_editmesh_eval_final(const Object *object);
|
||||
Mesh *BKE_object_get_editmesh_eval_cage(const Object *object);
|
||||
const Mesh *BKE_object_get_editmesh_eval_final(const Object *object);
|
||||
const Mesh *BKE_object_get_editmesh_eval_cage(const Object *object);
|
||||
const Mesh *BKE_object_get_mesh_deform_eval(const Object *object);
|
||||
|
||||
/* Lattice accessors.
|
||||
* These functions return either the regular lattice, or the edit-mode lattice,
|
||||
|
@ -576,7 +577,7 @@ bool BKE_object_moves_in_time(const Object *object, bool recurse_parent);
|
|||
/** Return the number of scenes using (instantiating) that object in their collections. */
|
||||
int BKE_object_scenes_users_get(Main *bmain, Object *ob);
|
||||
|
||||
MovieClip *BKE_object_movieclip_get(Scene *scene, Object *ob, bool use_default);
|
||||
MovieClip *BKE_object_movieclip_get(Scene *scene, const Object *ob, bool use_default);
|
||||
|
||||
void BKE_object_runtime_reset(Object *object);
|
||||
/**
|
||||
|
|
|
@ -47,7 +47,15 @@ struct ShrinkwrapBoundaryVertData {
|
|||
float normal_plane[3];
|
||||
};
|
||||
|
||||
struct ShrinkwrapBoundaryData {
|
||||
class ShrinkwrapBoundaryData {
|
||||
public:
|
||||
/* Returns true if there is boundary information. If there is no boundary information, then the
|
||||
* mesh from which this data is created from has no boundaries. */
|
||||
inline bool has_boundary() const
|
||||
{
|
||||
return !edge_is_boundary.is_empty();
|
||||
}
|
||||
|
||||
/* True if the edge belongs to exactly one face. */
|
||||
blender::BitVector<> edge_is_boundary;
|
||||
/* True if the triangle has any boundary edges. */
|
||||
|
|
|
@ -75,7 +75,7 @@ void BKE_tracking_settings_init(struct MovieTracking *tracking);
|
|||
* Get transformation matrix for a given object which is used
|
||||
* for parenting motion tracker reconstruction to 3D world.
|
||||
*/
|
||||
void BKE_tracking_get_camera_object_matrix(struct Object *camera_object, float mat[4][4]);
|
||||
void BKE_tracking_get_camera_object_matrix(const struct Object *camera_object, float mat[4][4]);
|
||||
/**
|
||||
* Get projection matrix for camera specified by given tracking object
|
||||
* and frame number.
|
||||
|
|
|
@ -981,18 +981,6 @@ static void mesh_calc_modifiers(Depsgraph *depsgraph,
|
|||
}
|
||||
}
|
||||
|
||||
static blender::Array<float3> editbmesh_vert_coords_alloc(const BMEditMesh *em)
|
||||
{
|
||||
blender::Array<float3> cos(em->bm->totvert);
|
||||
BMIter iter;
|
||||
BMVert *eve;
|
||||
int i;
|
||||
BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
|
||||
cos[i] = eve->co;
|
||||
}
|
||||
return cos;
|
||||
}
|
||||
|
||||
bool editbmesh_modifier_is_enabled(const Scene *scene,
|
||||
const Object *ob,
|
||||
ModifierData *md,
|
||||
|
@ -1022,7 +1010,7 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final)
|
|||
case ME_WRAPPER_TYPE_BMESH: {
|
||||
BMEditMesh &em = *mesh_final->runtime->edit_mesh;
|
||||
blender::bke::EditMeshData &emd = *mesh_final->runtime->edit_data;
|
||||
if (!emd.vertexCos.is_empty()) {
|
||||
if (!emd.vert_positions.is_empty()) {
|
||||
BKE_editmesh_cache_ensure_vert_normals(em, emd);
|
||||
BKE_editmesh_cache_ensure_face_normals(em, emd);
|
||||
}
|
||||
|
@ -1047,11 +1035,11 @@ static MutableSpan<float3> mesh_wrapper_vert_coords_ensure_for_write(Mesh *mesh)
|
|||
{
|
||||
switch (mesh->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_BMESH:
|
||||
if (mesh->runtime->edit_data->vertexCos.is_empty()) {
|
||||
mesh->runtime->edit_data->vertexCos = editbmesh_vert_coords_alloc(
|
||||
mesh->runtime->edit_mesh);
|
||||
if (mesh->runtime->edit_data->vert_positions.is_empty()) {
|
||||
mesh->runtime->edit_data->vert_positions = BM_mesh_vert_coords_alloc(
|
||||
mesh->runtime->edit_mesh->bm);
|
||||
}
|
||||
return mesh->runtime->edit_data->vertexCos;
|
||||
return mesh->runtime->edit_data->vert_positions;
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
case ME_WRAPPER_TYPE_SUBD:
|
||||
return mesh->vert_positions_for_write();
|
||||
|
|
|
@ -1526,13 +1526,11 @@ void BKE_brush_gpencil_vertex_presets(Main *bmain, ToolSettings *ts, const bool
|
|||
}
|
||||
|
||||
/* Set default Vertex brush. */
|
||||
if (reset || brush_prev == nullptr) {
|
||||
BKE_paint_brush_set(vertexpaint, deft_vertex);
|
||||
if ((reset == false) && (brush_prev != nullptr)) {
|
||||
BKE_paint_brush_set(vertexpaint, brush_prev);
|
||||
}
|
||||
else {
|
||||
if (brush_prev != nullptr) {
|
||||
BKE_paint_brush_set(vertexpaint, brush_prev);
|
||||
}
|
||||
BKE_paint_brush_set(vertexpaint, deft_vertex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1603,13 +1601,11 @@ void BKE_brush_gpencil_sculpt_presets(Main *bmain, ToolSettings *ts, const bool
|
|||
}
|
||||
|
||||
/* Set default brush. */
|
||||
if (reset || brush_prev == nullptr) {
|
||||
BKE_paint_brush_set(sculptpaint, deft_sculpt);
|
||||
if ((reset == false) && (brush_prev != nullptr)) {
|
||||
BKE_paint_brush_set(sculptpaint, brush_prev);
|
||||
}
|
||||
else {
|
||||
if (brush_prev != nullptr) {
|
||||
BKE_paint_brush_set(sculptpaint, brush_prev);
|
||||
}
|
||||
BKE_paint_brush_set(sculptpaint, deft_sculpt);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1648,13 +1644,11 @@ void BKE_brush_gpencil_weight_presets(Main *bmain, ToolSettings *ts, const bool
|
|||
}
|
||||
|
||||
/* Set default brush. */
|
||||
if (reset || brush_prev == nullptr) {
|
||||
BKE_paint_brush_set(weightpaint, deft_weight);
|
||||
if ((reset == false) && (brush_prev != nullptr)) {
|
||||
BKE_paint_brush_set(weightpaint, brush_prev);
|
||||
}
|
||||
else {
|
||||
if (brush_prev != nullptr) {
|
||||
BKE_paint_brush_set(weightpaint, brush_prev);
|
||||
}
|
||||
BKE_paint_brush_set(weightpaint, deft_weight);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1424,7 +1424,7 @@ bool data_transfer_layersmapping_vgroups(ListBase *r_map,
|
|||
MDeformVert *data_dst = static_cast<MDeformVert *>(
|
||||
CustomData_get_layer_for_write(cd_dst, CD_MDEFORMVERT, num_elem_dst));
|
||||
if (data_dst && use_dupref_dst && r_map) {
|
||||
/* If dest is a derivedmesh, we do not want to overwrite cdlayers of org mesh! */
|
||||
/* If dest is an evaluated mesh, we do not want to overwrite cdlayers of org mesh! */
|
||||
data_dst = static_cast<MDeformVert *>(
|
||||
CustomData_get_layer_for_write(cd_dst, CD_MDEFORMVERT, num_elem_dst));
|
||||
}
|
||||
|
|
|
@ -218,7 +218,7 @@ struct PaintBakeData {
|
|||
/** UV Image sequence format point */
|
||||
struct PaintUVPoint {
|
||||
/* Pixel / mesh data */
|
||||
/** tri index on domain derived mesh */
|
||||
/** Triangle index on domain evaluated mesh. */
|
||||
uint tri_index;
|
||||
uint pixel_index;
|
||||
/* vertex indexes */
|
||||
|
@ -1825,7 +1825,7 @@ static void dynamic_paint_apply_surface_displace_cb(void *__restrict userdata,
|
|||
madd_v3_v3fl(data->vert_positions[i], data->vert_normals[i], -val);
|
||||
}
|
||||
|
||||
/* apply displacing vertex surface to the derived mesh */
|
||||
/** Apply displacing vertex surface to the evaluated-mesh. */
|
||||
static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, Mesh *result)
|
||||
{
|
||||
PaintSurfaceData *sData = surface->data;
|
||||
|
@ -1911,8 +1911,8 @@ static void dynamic_paint_apply_surface_wave_cb(void *__restrict userdata,
|
|||
madd_v3_v3fl(data->vert_positions[i], data->vert_normals[i], wPoint[i].height);
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply canvas data to the object derived mesh
|
||||
/**
|
||||
* Apply canvas data to the object evaluated-mesh.
|
||||
*/
|
||||
static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *ob, Mesh *mesh)
|
||||
{
|
||||
|
@ -2094,7 +2094,7 @@ static void canvas_copyMesh(DynamicPaintCanvasSettings *canvas, Mesh *mesh)
|
|||
}
|
||||
|
||||
/*
|
||||
* Updates derived mesh copy and processes dynamic paint step / caches.
|
||||
* Updates evaluated-mesh copy and processes dynamic paint step / caches.
|
||||
*/
|
||||
static void dynamicPaint_frameUpdate(
|
||||
DynamicPaintModifierData *pmd, Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *mesh)
|
||||
|
@ -2103,7 +2103,7 @@ static void dynamicPaint_frameUpdate(
|
|||
DynamicPaintCanvasSettings *canvas = pmd->canvas;
|
||||
DynamicPaintSurface *surface = static_cast<DynamicPaintSurface *>(canvas->surfaces.first);
|
||||
|
||||
/* update derived mesh copy */
|
||||
/* update evaluated-mesh copy */
|
||||
canvas_copyMesh(canvas, mesh);
|
||||
|
||||
/* in case image sequence baking, stop here */
|
||||
|
@ -3855,7 +3855,8 @@ static void dynamicPaint_brushMeshCalculateVelocity(Depsgraph *depsgraph,
|
|||
return;
|
||||
}
|
||||
|
||||
/* if mesh is constructive -> num of verts has changed, only use current frame derived mesh */
|
||||
/* If mesh is constructive -> num of verts has changed,
|
||||
* only use current frame evaluated-mesh. */
|
||||
if (numOfVerts_p != numOfVerts_c) {
|
||||
positions_p = positions_c;
|
||||
}
|
||||
|
@ -6174,7 +6175,7 @@ static bool dynamicPaint_generateBakeData(DynamicPaintSurface *surface,
|
|||
}
|
||||
|
||||
/*
|
||||
* Make a transformed copy of canvas derived mesh vertices to avoid recalculation.
|
||||
* Make a transformed copy of canvas evaluated-mesh vertices to avoid recalculation.
|
||||
*/
|
||||
bData->mesh_bounds.valid = false;
|
||||
for (index = 0; index < canvasNumOfVerts; index++) {
|
||||
|
@ -6404,7 +6405,7 @@ int dynamicPaint_calculateFrame(
|
|||
{
|
||||
float timescale = 1.0f;
|
||||
|
||||
/* apply previous displace on derivedmesh if incremental surface */
|
||||
/* Apply previous displace on evaluated-mesh if incremental surface. */
|
||||
if (surface->flags & MOD_DPAINT_DISP_INCREMENTAL) {
|
||||
dynamicPaint_applySurfaceDisplace(surface, dynamicPaint_canvas_mesh_get(surface->canvas));
|
||||
}
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
|
||||
using blender::Array;
|
||||
using blender::float3;
|
||||
using blender::Span;
|
||||
|
||||
BMEditMesh *BKE_editmesh_create(BMesh *bm)
|
||||
{
|
||||
BMEditMesh *em = MEM_new<BMEditMesh>(__func__);
|
||||
|
@ -124,7 +128,7 @@ void BKE_editmesh_free_data(BMEditMesh *em)
|
|||
|
||||
struct CageUserData {
|
||||
int totvert;
|
||||
float (*cos_cage)[3];
|
||||
blender::MutableSpan<float3> positions_cage;
|
||||
BLI_bitmap *visit_bitmap;
|
||||
};
|
||||
|
||||
|
@ -137,16 +141,17 @@ static void cage_mapped_verts_callback(void *user_data,
|
|||
|
||||
if ((index >= 0 && index < data->totvert) && !BLI_BITMAP_TEST(data->visit_bitmap, index)) {
|
||||
BLI_BITMAP_ENABLE(data->visit_bitmap, index);
|
||||
copy_v3_v3(data->cos_cage[index], co);
|
||||
copy_v3_v3(data->positions_cage[index], co);
|
||||
}
|
||||
}
|
||||
|
||||
float (*BKE_editmesh_vert_coords_alloc(
|
||||
Depsgraph *depsgraph, BMEditMesh *em, Scene *scene, Object *ob, int *r_vert_len))[3]
|
||||
Array<float3> BKE_editmesh_vert_coords_alloc(Depsgraph *depsgraph,
|
||||
BMEditMesh *em,
|
||||
Scene *scene,
|
||||
Object *ob)
|
||||
{
|
||||
Mesh *cage = editbmesh_get_eval_cage(depsgraph, scene, ob, em, &CD_MASK_BAREMESH);
|
||||
float(*cos_cage)[3] = static_cast<float(*)[3]>(
|
||||
MEM_callocN(sizeof(*cos_cage) * em->bm->totvert, __func__));
|
||||
Array<float3> positions_cage(em->bm->totvert);
|
||||
|
||||
/* When initializing cage verts, we only want the first cage coordinate for each vertex,
|
||||
* so that e.g. mirror or array use original vertex coordinates and not mirrored or duplicate. */
|
||||
|
@ -154,38 +159,29 @@ float (*BKE_editmesh_vert_coords_alloc(
|
|||
|
||||
CageUserData data;
|
||||
data.totvert = em->bm->totvert;
|
||||
data.cos_cage = cos_cage;
|
||||
data.positions_cage = positions_cage;
|
||||
data.visit_bitmap = visit_bitmap;
|
||||
|
||||
BKE_mesh_foreach_mapped_vert(cage, cage_mapped_verts_callback, &data, MESH_FOREACH_NOP);
|
||||
|
||||
MEM_freeN(visit_bitmap);
|
||||
|
||||
if (r_vert_len) {
|
||||
*r_vert_len = em->bm->totvert;
|
||||
}
|
||||
|
||||
return cos_cage;
|
||||
return positions_cage;
|
||||
}
|
||||
|
||||
const float (*BKE_editmesh_vert_coords_when_deformed(Depsgraph *depsgraph,
|
||||
BMEditMesh *em,
|
||||
Scene *scene,
|
||||
Object *ob,
|
||||
int *r_vert_len,
|
||||
bool *r_is_alloc))[3]
|
||||
Span<float3> BKE_editmesh_vert_coords_when_deformed(
|
||||
Depsgraph *depsgraph, BMEditMesh *em, Scene *scene, Object *ob, Array<float3> &r_alloc)
|
||||
{
|
||||
const float(*coords)[3] = nullptr;
|
||||
*r_is_alloc = false;
|
||||
|
||||
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||
Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object_eval);
|
||||
Mesh *mesh_cage = BKE_object_get_editmesh_eval_cage(ob);
|
||||
const Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||
const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object_eval);
|
||||
const Mesh *mesh_cage = BKE_object_get_editmesh_eval_cage(ob);
|
||||
|
||||
Span<float3> vert_positions;
|
||||
if (mesh_cage && mesh_cage->runtime->deformed_only) {
|
||||
BLI_assert(BKE_mesh_wrapper_vert_len(mesh_cage) == em->bm->totvert);
|
||||
/* Deformed, and we have deformed coords already. */
|
||||
coords = BKE_mesh_wrapper_vert_coords(mesh_cage);
|
||||
vert_positions = BKE_mesh_wrapper_vert_coords(mesh_cage);
|
||||
}
|
||||
else if ((editmesh_eval_final != nullptr) &&
|
||||
(editmesh_eval_final->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH))
|
||||
|
@ -194,15 +190,15 @@ const float (*BKE_editmesh_vert_coords_when_deformed(Depsgraph *depsgraph,
|
|||
}
|
||||
else {
|
||||
/* Constructive modifiers have been used, we need to allocate coordinates. */
|
||||
*r_is_alloc = true;
|
||||
coords = BKE_editmesh_vert_coords_alloc(depsgraph, em, scene, ob, r_vert_len);
|
||||
r_alloc = BKE_editmesh_vert_coords_alloc(depsgraph, em, scene, ob);
|
||||
return r_alloc.as_span();
|
||||
}
|
||||
return coords;
|
||||
return vert_positions;
|
||||
}
|
||||
|
||||
float (*BKE_editmesh_vert_coords_alloc_orco(BMEditMesh *em, int *r_vert_len))[3]
|
||||
Array<float3> BKE_editmesh_vert_coords_alloc_orco(BMEditMesh *em)
|
||||
{
|
||||
return BM_mesh_vert_coords_alloc(em->bm, r_vert_len);
|
||||
return BM_mesh_vert_coords_alloc(em->bm);
|
||||
}
|
||||
|
||||
void BKE_editmesh_lnorspace_update(BMEditMesh *em)
|
||||
|
|
|
@ -23,12 +23,12 @@
|
|||
|
||||
void BKE_editmesh_cache_ensure_face_normals(BMEditMesh &em, blender::bke::EditMeshData &emd)
|
||||
{
|
||||
if (emd.vertexCos.is_empty() || !emd.faceNos.is_empty()) {
|
||||
if (emd.vert_positions.is_empty() || !emd.face_normals.is_empty()) {
|
||||
return;
|
||||
}
|
||||
BMesh *bm = em.bm;
|
||||
|
||||
emd.faceNos.reinitialize(bm->totface);
|
||||
emd.face_normals.reinitialize(bm->totface);
|
||||
|
||||
BM_mesh_elem_index_ensure(bm, BM_VERT);
|
||||
BMFace *efa;
|
||||
|
@ -36,15 +36,17 @@ void BKE_editmesh_cache_ensure_face_normals(BMEditMesh &em, blender::bke::EditMe
|
|||
int i;
|
||||
BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
|
||||
BM_elem_index_set(efa, i); /* set_inline */
|
||||
BM_face_calc_normal_vcos(
|
||||
bm, efa, emd.faceNos[i], reinterpret_cast<const float(*)[3]>(emd.vertexCos.data()));
|
||||
BM_face_calc_normal_vcos(bm,
|
||||
efa,
|
||||
emd.face_normals[i],
|
||||
reinterpret_cast<const float(*)[3]>(emd.vert_positions.data()));
|
||||
}
|
||||
bm->elem_index_dirty &= ~BM_FACE;
|
||||
}
|
||||
|
||||
void BKE_editmesh_cache_ensure_vert_normals(BMEditMesh &em, blender::bke::EditMeshData &emd)
|
||||
{
|
||||
if (emd.vertexCos.is_empty() || !emd.vertexNos.is_empty()) {
|
||||
if (emd.vert_positions.is_empty() || !emd.vert_normals.is_empty()) {
|
||||
return;
|
||||
}
|
||||
BMesh *bm = em.bm;
|
||||
|
@ -52,37 +54,36 @@ void BKE_editmesh_cache_ensure_vert_normals(BMEditMesh &em, blender::bke::EditMe
|
|||
/* Calculate vertex normals from face normals. */
|
||||
BKE_editmesh_cache_ensure_face_normals(em, emd);
|
||||
|
||||
emd.vertexNos.reinitialize(bm->totvert);
|
||||
emd.vert_normals.reinitialize(bm->totvert);
|
||||
|
||||
BM_mesh_elem_index_ensure(bm, BM_FACE);
|
||||
BM_verts_calc_normal_vcos(bm,
|
||||
reinterpret_cast<const float(*)[3]>(emd.faceNos.data()),
|
||||
reinterpret_cast<const float(*)[3]>(emd.vertexCos.data()),
|
||||
reinterpret_cast<float(*)[3]>(emd.vertexNos.data()));
|
||||
reinterpret_cast<const float(*)[3]>(emd.face_normals.data()),
|
||||
reinterpret_cast<const float(*)[3]>(emd.vert_positions.data()),
|
||||
reinterpret_cast<float(*)[3]>(emd.vert_normals.data()));
|
||||
}
|
||||
|
||||
void BKE_editmesh_cache_ensure_face_centers(BMEditMesh &em, blender::bke::EditMeshData &emd)
|
||||
{
|
||||
if (!emd.faceCos.is_empty()) {
|
||||
if (!emd.face_centers.is_empty()) {
|
||||
return;
|
||||
}
|
||||
BMesh *bm = em.bm;
|
||||
|
||||
emd.faceCos.reinitialize(bm->totface);
|
||||
emd.face_centers.reinitialize(bm->totface);
|
||||
|
||||
BMFace *efa;
|
||||
BMIter fiter;
|
||||
int i;
|
||||
if (emd.vertexCos.is_empty()) {
|
||||
if (emd.vert_positions.is_empty()) {
|
||||
BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
|
||||
BM_face_calc_center_median(efa, emd.faceCos[i]);
|
||||
BM_face_calc_center_median(efa, emd.face_centers[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BM_mesh_elem_index_ensure(bm, BM_VERT);
|
||||
BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
|
||||
BM_face_calc_center_median_vcos(
|
||||
bm, efa, emd.faceCos[i], reinterpret_cast<const float(*)[3]>(emd.vertexCos.data()));
|
||||
BM_face_calc_center_median_vcos(bm, efa, emd.face_centers[i], emd.vert_positions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +103,7 @@ std::optional<blender::Bounds<blender::float3>> BKE_editmesh_cache_calc_minmax(
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (emd.vertexCos.is_empty()) {
|
||||
if (emd.vert_positions.is_empty()) {
|
||||
BMVert *eve;
|
||||
BMIter iter;
|
||||
float3 min(std::numeric_limits<float>::max());
|
||||
|
@ -113,7 +114,7 @@ std::optional<blender::Bounds<blender::float3>> BKE_editmesh_cache_calc_minmax(
|
|||
return Bounds<float3>{min, max};
|
||||
}
|
||||
|
||||
return bounds::min_max(emd.vertexCos.as_span());
|
||||
return bounds::min_max(emd.vert_positions.as_span());
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -727,13 +727,13 @@ Material *BKE_object_material_get(Object *ob, short act)
|
|||
return ma_p ? *ma_p : nullptr;
|
||||
}
|
||||
|
||||
static ID *get_evaluated_object_data_with_materials(Object *ob)
|
||||
static const ID *get_evaluated_object_data_with_materials(Object *ob)
|
||||
{
|
||||
ID *data = static_cast<ID *>(ob->data);
|
||||
const ID *data = static_cast<ID *>(ob->data);
|
||||
/* Meshes in edit mode need special handling. */
|
||||
if (ob->type == OB_MESH && ob->mode == OB_MODE_EDIT) {
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob);
|
||||
const Mesh *mesh = static_cast<const Mesh *>(ob->data);
|
||||
const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob);
|
||||
if (mesh->runtime->edit_mesh && editmesh_eval_final) {
|
||||
data = &editmesh_eval_final->id;
|
||||
}
|
||||
|
@ -745,8 +745,8 @@ Material *BKE_object_material_get_eval(Object *ob, short act)
|
|||
{
|
||||
BLI_assert(DEG_is_evaluated_object(ob));
|
||||
|
||||
ID *data = get_evaluated_object_data_with_materials(ob);
|
||||
const short *tot_slots_data_ptr = BKE_id_material_len_p(data);
|
||||
const ID *data = get_evaluated_object_data_with_materials(ob);
|
||||
const short *tot_slots_data_ptr = BKE_id_material_len_p(const_cast<ID *>(data));
|
||||
const int tot_slots_data = tot_slots_data_ptr ? *tot_slots_data_ptr : 0;
|
||||
|
||||
if (tot_slots_data == 0) {
|
||||
|
@ -757,7 +757,7 @@ Material *BKE_object_material_get_eval(Object *ob, short act)
|
|||
const int slot_index = clamp_i(act - 1, 0, tot_slots_data - 1);
|
||||
const int tot_slots_object = ob->totcol;
|
||||
|
||||
Material ***materials_data_ptr = BKE_id_material_array_p(data);
|
||||
Material ***materials_data_ptr = BKE_id_material_array_p(const_cast<ID *>(data));
|
||||
Material **materials_data = materials_data_ptr ? *materials_data_ptr : nullptr;
|
||||
Material **materials_object = ob->mat;
|
||||
|
||||
|
|
|
@ -769,15 +769,15 @@ static Mesh *mesh_new_from_mball_object(Object *object)
|
|||
return BKE_mesh_copy_for_eval(mesh_eval);
|
||||
}
|
||||
|
||||
static Mesh *mesh_new_from_mesh(Object *object, Mesh *mesh)
|
||||
static Mesh *mesh_new_from_mesh(Object *object, const Mesh *mesh)
|
||||
{
|
||||
/* While we could copy this into the new mesh,
|
||||
* add the data to 'mesh' so future calls to this function don't need to re-convert the data. */
|
||||
if (mesh->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) {
|
||||
BKE_mesh_wrapper_ensure_mdata(mesh);
|
||||
BKE_mesh_wrapper_ensure_mdata(const_cast<Mesh *>(mesh));
|
||||
}
|
||||
else {
|
||||
mesh = BKE_mesh_wrapper_ensure_subdivision(mesh);
|
||||
mesh = BKE_mesh_wrapper_ensure_subdivision(const_cast<Mesh *>(mesh));
|
||||
}
|
||||
|
||||
Mesh *mesh_result = (Mesh *)BKE_id_copy_ex(
|
||||
|
@ -828,12 +828,11 @@ static Mesh *mesh_new_from_mesh_object(Depsgraph *depsgraph,
|
|||
if (preserve_all_data_layers || preserve_origindex) {
|
||||
return mesh_new_from_mesh_object_with_layers(depsgraph, object, preserve_origindex);
|
||||
}
|
||||
Mesh *mesh_input = (Mesh *)object->data;
|
||||
const Mesh *mesh_input = (const Mesh *)object->data;
|
||||
/* If we are in edit mode, use evaluated mesh from edit structure, matching to what
|
||||
* viewport is using for visualization. */
|
||||
if (mesh_input->runtime->edit_mesh != nullptr) {
|
||||
Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object);
|
||||
if (editmesh_eval_final != nullptr) {
|
||||
if (const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object)) {
|
||||
mesh_input = editmesh_eval_final;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,12 +41,12 @@ void BKE_mesh_foreach_mapped_vert(
|
|||
BMIter iter;
|
||||
BMVert *eve;
|
||||
int i;
|
||||
if (!mesh->runtime->edit_data->vertexCos.is_empty()) {
|
||||
const blender::Span<blender::float3> positions = mesh->runtime->edit_data->vertexCos;
|
||||
if (!mesh->runtime->edit_data->vert_positions.is_empty()) {
|
||||
const blender::Span<blender::float3> positions = mesh->runtime->edit_data->vert_positions;
|
||||
blender::Span<blender::float3> vert_normals;
|
||||
if (flag & MESH_FOREACH_USE_NORMAL) {
|
||||
BKE_editmesh_cache_ensure_vert_normals(*em, *mesh->runtime->edit_data);
|
||||
vert_normals = mesh->runtime->edit_data->vertexNos;
|
||||
vert_normals = mesh->runtime->edit_data->vert_normals;
|
||||
}
|
||||
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
|
||||
const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? &vert_normals[i].x : nullptr;
|
||||
|
@ -100,8 +100,8 @@ void BKE_mesh_foreach_mapped_edge(
|
|||
BMIter iter;
|
||||
BMEdge *eed;
|
||||
int i;
|
||||
if (!mesh->runtime->edit_data->vertexCos.is_empty()) {
|
||||
const blender::Span<blender::float3> positions = mesh->runtime->edit_data->vertexCos;
|
||||
if (!mesh->runtime->edit_data->vert_positions.is_empty()) {
|
||||
const blender::Span<blender::float3> positions = mesh->runtime->edit_data->vert_positions;
|
||||
BM_mesh_elem_index_ensure(bm, BM_VERT);
|
||||
BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
|
||||
func(user_data,
|
||||
|
@ -159,7 +159,7 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
|
|||
BMIter iter;
|
||||
BMFace *efa;
|
||||
|
||||
const blender::Span<blender::float3> positions = mesh->runtime->edit_data->vertexCos;
|
||||
const blender::Span<blender::float3> positions = mesh->runtime->edit_data->vert_positions;
|
||||
|
||||
/* XXX: investigate using EditMesh data. */
|
||||
blender::Span<blender::float3> corner_normals;
|
||||
|
@ -243,11 +243,11 @@ void BKE_mesh_foreach_mapped_face_center(
|
|||
int i;
|
||||
|
||||
BKE_editmesh_cache_ensure_face_centers(*em, *mesh->runtime->edit_data);
|
||||
face_centers = mesh->runtime->edit_data->faceCos; /* always set */
|
||||
face_centers = mesh->runtime->edit_data->face_centers; /* always set */
|
||||
|
||||
if (flag & MESH_FOREACH_USE_NORMAL) {
|
||||
BKE_editmesh_cache_ensure_face_normals(*em, *mesh->runtime->edit_data);
|
||||
face_normals = mesh->runtime->edit_data->faceNos; /* maybe nullptr */
|
||||
face_normals = mesh->runtime->edit_data->face_normals; /* maybe nullptr */
|
||||
}
|
||||
|
||||
if (!face_normals.is_empty()) {
|
||||
|
|
|
@ -297,7 +297,7 @@ static void DM_calc_loop_tangents_thread(TaskPool *__restrict /*pool*/, void *ta
|
|||
mikk.genTangSpace();
|
||||
}
|
||||
|
||||
void BKE_mesh_add_loop_tangent_named_layer_for_uv(CustomData *uv_data,
|
||||
void BKE_mesh_add_loop_tangent_named_layer_for_uv(const CustomData *uv_data,
|
||||
CustomData *tan_data,
|
||||
int numLoopData,
|
||||
const char *layer_name)
|
||||
|
@ -393,7 +393,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
|
|||
const uint corner_tris_len,
|
||||
const blender::Span<bool> sharp_faces,
|
||||
|
||||
CustomData *loopdata,
|
||||
const CustomData *loopdata,
|
||||
bool calc_active_tangent,
|
||||
const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME],
|
||||
int tangent_names_len,
|
||||
|
@ -554,7 +554,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
|
|||
if (act_uv_index != -1) {
|
||||
int tan_index = CustomData_get_named_layer_index(
|
||||
loopdata, CD_TANGENT, loopdata->layers[act_uv_index].name);
|
||||
CustomData_set_layer_active_index(loopdata, CD_TANGENT, tan_index);
|
||||
CustomData_set_layer_active_index(loopdata_out, CD_TANGENT, tan_index);
|
||||
} /* else tangent has been built from orco */
|
||||
|
||||
/* Update render layer index */
|
||||
|
@ -564,7 +564,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
|
|||
if (ren_uv_index != -1) {
|
||||
int tan_index = CustomData_get_named_layer_index(
|
||||
loopdata, CD_TANGENT, loopdata->layers[ren_uv_index].name);
|
||||
CustomData_set_layer_render_index(loopdata, CD_TANGENT, tan_index);
|
||||
CustomData_set_layer_render_index(loopdata_out, CD_TANGENT, tan_index);
|
||||
} /* else tangent has been built from orco */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,8 +124,8 @@ void BKE_mesh_wrapper_ensure_mdata(Mesh *mesh)
|
|||
BKE_mesh_ensure_default_orig_index_customdata_no_check(mesh);
|
||||
|
||||
blender::bke::EditMeshData &edit_data = *mesh->runtime->edit_data;
|
||||
if (!edit_data.vertexCos.is_empty()) {
|
||||
mesh->vert_positions_for_write().copy_from(edit_data.vertexCos);
|
||||
if (!edit_data.vert_positions.is_empty()) {
|
||||
mesh->vert_positions_for_write().copy_from(edit_data.vert_positions);
|
||||
mesh->runtime->is_original_bmesh = false;
|
||||
}
|
||||
|
||||
|
@ -148,35 +148,31 @@ void BKE_mesh_wrapper_ensure_mdata(Mesh *mesh)
|
|||
/** \name Mesh Coordinate Access
|
||||
* \{ */
|
||||
|
||||
const float (*BKE_mesh_wrapper_vert_coords(const Mesh *mesh))[3]
|
||||
Span<float3> BKE_mesh_wrapper_vert_coords(const Mesh *mesh)
|
||||
{
|
||||
switch (mesh->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_BMESH:
|
||||
if (mesh->runtime->edit_data->vertexCos.is_empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<const float(*)[3]>(mesh->runtime->edit_data->vertexCos.data());
|
||||
return mesh->runtime->edit_data->vert_positions;
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
case ME_WRAPPER_TYPE_SUBD:
|
||||
return reinterpret_cast<const float(*)[3]>(mesh->vert_positions().data());
|
||||
return mesh->vert_positions();
|
||||
}
|
||||
return nullptr;
|
||||
BLI_assert_unreachable();
|
||||
return {};
|
||||
}
|
||||
|
||||
const float (*BKE_mesh_wrapper_face_normals(Mesh *mesh))[3]
|
||||
Span<float3> BKE_mesh_wrapper_face_normals(Mesh *mesh)
|
||||
{
|
||||
switch (mesh->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_BMESH:
|
||||
BKE_editmesh_cache_ensure_face_normals(*mesh->runtime->edit_mesh, *mesh->runtime->edit_data);
|
||||
if (mesh->runtime->edit_data->faceNos.is_empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<const float(*)[3]>(mesh->runtime->edit_data->faceNos.data());
|
||||
return mesh->runtime->edit_data->face_normals;
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
case ME_WRAPPER_TYPE_SUBD:
|
||||
return reinterpret_cast<const float(*)[3]>(mesh->face_normals().data());
|
||||
return mesh->face_normals();
|
||||
}
|
||||
return nullptr;
|
||||
BLI_assert_unreachable();
|
||||
return {};
|
||||
}
|
||||
|
||||
void BKE_mesh_wrapper_tag_positions_changed(Mesh *mesh)
|
||||
|
@ -184,9 +180,9 @@ void BKE_mesh_wrapper_tag_positions_changed(Mesh *mesh)
|
|||
switch (mesh->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_BMESH:
|
||||
if (mesh->runtime->edit_data) {
|
||||
mesh->runtime->edit_data->vertexNos = {};
|
||||
mesh->runtime->edit_data->faceCos = {};
|
||||
mesh->runtime->edit_data->faceNos = {};
|
||||
mesh->runtime->edit_data->vert_normals = {};
|
||||
mesh->runtime->edit_data->face_centers = {};
|
||||
mesh->runtime->edit_data->face_normals = {};
|
||||
}
|
||||
break;
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
|
@ -202,8 +198,8 @@ void BKE_mesh_wrapper_vert_coords_copy(const Mesh *mesh, blender::MutableSpan<fl
|
|||
case ME_WRAPPER_TYPE_BMESH: {
|
||||
BMesh *bm = mesh->runtime->edit_mesh->bm;
|
||||
const blender::bke::EditMeshData &edit_data = *mesh->runtime->edit_data;
|
||||
if (!edit_data.vertexCos.is_empty()) {
|
||||
positions.copy_from(edit_data.vertexCos);
|
||||
if (!edit_data.vert_positions.is_empty()) {
|
||||
positions.copy_from(edit_data.vert_positions);
|
||||
}
|
||||
else {
|
||||
BMIter iter;
|
||||
|
@ -234,9 +230,9 @@ void BKE_mesh_wrapper_vert_coords_copy_with_mat4(const Mesh *mesh,
|
|||
BMesh *bm = mesh->runtime->edit_mesh->bm;
|
||||
BLI_assert(vert_coords_len == bm->totvert);
|
||||
const blender::bke::EditMeshData &edit_data = *mesh->runtime->edit_data;
|
||||
if (!edit_data.vertexCos.is_empty()) {
|
||||
if (!edit_data.vert_positions.is_empty()) {
|
||||
for (int i = 0; i < vert_coords_len; i++) {
|
||||
mul_v3_m4v3(vert_coords[i], mat, edit_data.vertexCos[i]);
|
||||
mul_v3_m4v3(vert_coords[i], mat, edit_data.vert_positions[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -879,7 +879,7 @@ static void modwrap_dependsOnNormals(Mesh *mesh)
|
|||
switch (mesh->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_BMESH: {
|
||||
blender::bke::EditMeshData &edit_data = *mesh->runtime->edit_data;
|
||||
if (!edit_data.vertexCos.is_empty()) {
|
||||
if (!edit_data.vert_positions.is_empty()) {
|
||||
/* Note that 'ensure' is acceptable here since these values aren't modified in-place.
|
||||
* If that changes we'll need to recalculate. */
|
||||
BKE_editmesh_cache_ensure_vert_normals(*mesh->runtime->edit_mesh, edit_data);
|
||||
|
@ -952,10 +952,10 @@ Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(Object *ob_eval)
|
|||
|
||||
if ((ob_eval->type == OB_MESH) && (ob_eval->mode & OB_MODE_EDIT)) {
|
||||
/* In EditMode, evaluated mesh is stored in BMEditMesh, not the object... */
|
||||
BMEditMesh *em = BKE_editmesh_from_object(ob_eval);
|
||||
const BMEditMesh *em = BKE_editmesh_from_object(ob_eval);
|
||||
/* 'em' might not exist yet in some cases, just after loading a .blend file, see #57878. */
|
||||
if (em != nullptr) {
|
||||
mesh = BKE_object_get_editmesh_eval_final(ob_eval);
|
||||
mesh = const_cast<Mesh *>(BKE_object_get_editmesh_eval_final(ob_eval));
|
||||
}
|
||||
}
|
||||
if (mesh == nullptr) {
|
||||
|
|
|
@ -2764,7 +2764,7 @@ void BKE_object_obdata_size_init(Object *ob, const float size)
|
|||
/** \name Object Matrix Get/Set API
|
||||
* \{ */
|
||||
|
||||
void BKE_object_scale_to_mat3(Object *ob, float mat[3][3])
|
||||
void BKE_object_scale_to_mat3(const Object *ob, float mat[3][3])
|
||||
{
|
||||
float3 vec;
|
||||
mul_v3_v3v3(vec, ob->scale, ob->dscale);
|
||||
|
@ -2946,7 +2946,7 @@ void BKE_object_tfm_copy(Object *object_dst, const Object *object_src)
|
|||
#undef TFMCPY4D
|
||||
}
|
||||
|
||||
void BKE_object_to_mat3(Object *ob, float r_mat[3][3]) /* no parent */
|
||||
void BKE_object_to_mat3(const Object *ob, float r_mat[3][3]) /* no parent */
|
||||
{
|
||||
float smat[3][3];
|
||||
float rmat[3][3];
|
||||
|
@ -2959,7 +2959,7 @@ void BKE_object_to_mat3(Object *ob, float r_mat[3][3]) /* no parent */
|
|||
mul_m3_m3m3(r_mat, rmat, smat);
|
||||
}
|
||||
|
||||
void BKE_object_to_mat4(Object *ob, float r_mat[4][4])
|
||||
void BKE_object_to_mat4(const Object *ob, float r_mat[4][4])
|
||||
{
|
||||
float tmat[3][3];
|
||||
|
||||
|
@ -2987,7 +2987,7 @@ void BKE_object_matrix_local_get(Object *ob, float r_mat[4][4])
|
|||
/**
|
||||
* \return success if \a mat is set.
|
||||
*/
|
||||
static bool ob_parcurve(Object *ob, Object *par, float r_mat[4][4])
|
||||
static bool ob_parcurve(const Object *ob, Object *par, float r_mat[4][4])
|
||||
{
|
||||
Curve *cu = (Curve *)par->data;
|
||||
float vec[4], quat[4], radius, ctime;
|
||||
|
@ -3046,7 +3046,7 @@ static bool ob_parcurve(Object *ob, Object *par, float r_mat[4][4])
|
|||
return true;
|
||||
}
|
||||
|
||||
static void ob_parbone(Object *ob, Object *par, float r_mat[4][4])
|
||||
static void ob_parbone(const Object *ob, const Object *par, float r_mat[4][4])
|
||||
{
|
||||
float3 vec;
|
||||
|
||||
|
@ -3056,7 +3056,7 @@ static void ob_parbone(Object *ob, Object *par, float r_mat[4][4])
|
|||
}
|
||||
|
||||
/* Make sure the bone is still valid */
|
||||
bPoseChannel *pchan = BKE_pose_channel_find_name(par->pose, ob->parsubstr);
|
||||
const bPoseChannel *pchan = BKE_pose_channel_find_name(par->pose, ob->parsubstr);
|
||||
if (!pchan || !pchan->bone) {
|
||||
CLOG_WARN(
|
||||
&LOG, "Parent Bone: '%s' for Object: '%s' doesn't exist", ob->parsubstr, ob->id.name + 2);
|
||||
|
@ -3080,15 +3080,15 @@ static void ob_parbone(Object *ob, Object *par, float r_mat[4][4])
|
|||
}
|
||||
}
|
||||
|
||||
static void give_parvert(Object *par, int nr, float vec[3])
|
||||
static void give_parvert(const Object *par, int nr, float vec[3])
|
||||
{
|
||||
zero_v3(vec);
|
||||
|
||||
if (par->type == OB_MESH) {
|
||||
Mesh *mesh = (Mesh *)par->data;
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
Mesh *mesh_eval = (em) ? BKE_object_get_editmesh_eval_final(par) :
|
||||
BKE_object_get_evaluated_mesh(par);
|
||||
const Mesh *mesh = (const Mesh *)par->data;
|
||||
const BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
const Mesh *mesh_eval = (em) ? BKE_object_get_editmesh_eval_final(par) :
|
||||
BKE_object_get_evaluated_mesh(par);
|
||||
|
||||
if (mesh_eval) {
|
||||
const Span<float3> positions = mesh_eval->vert_positions();
|
||||
|
@ -3111,9 +3111,9 @@ static void give_parvert(Object *par, int nr, float vec[3])
|
|||
}
|
||||
if (nr < numVerts) {
|
||||
if (mesh_eval && mesh_eval->runtime->edit_data &&
|
||||
!mesh_eval->runtime->edit_data->vertexCos.is_empty())
|
||||
!mesh_eval->runtime->edit_data->vert_positions.is_empty())
|
||||
{
|
||||
add_v3_v3(vec, mesh_eval->runtime->edit_data->vertexCos[nr]);
|
||||
add_v3_v3(vec, mesh_eval->runtime->edit_data->vert_positions[nr]);
|
||||
}
|
||||
else {
|
||||
const BMVert *v = BM_vert_at_index(em->bm, nr);
|
||||
|
@ -3201,7 +3201,7 @@ static void give_parvert(Object *par, int nr, float vec[3])
|
|||
}
|
||||
}
|
||||
|
||||
static void ob_parvert3(Object *ob, Object *par, float r_mat[4][4])
|
||||
static void ob_parvert3(const Object *ob, const Object *par, float r_mat[4][4])
|
||||
{
|
||||
/* in local ob space */
|
||||
if (OB_TYPE_SUPPORT_PARVERT(par->type)) {
|
||||
|
@ -3222,7 +3222,7 @@ static void ob_parvert3(Object *ob, Object *par, float r_mat[4][4])
|
|||
}
|
||||
}
|
||||
|
||||
void BKE_object_get_parent_matrix(Object *ob, Object *par, float r_parentmat[4][4])
|
||||
void BKE_object_get_parent_matrix(const Object *ob, Object *par, float r_parentmat[4][4])
|
||||
{
|
||||
float tmat[4][4];
|
||||
float vec[3];
|
||||
|
@ -3277,8 +3277,11 @@ void BKE_object_get_parent_matrix(Object *ob, Object *par, float r_parentmat[4][
|
|||
* \param r_originmat: Optional matrix that stores the space the object is in
|
||||
* (without its own matrix applied)
|
||||
*/
|
||||
static void solve_parenting(
|
||||
Object *ob, Object *par, const bool set_origin, float r_obmat[4][4], float r_originmat[3][3])
|
||||
static void solve_parenting(const Object *ob,
|
||||
Object *par,
|
||||
const bool set_origin,
|
||||
float r_obmat[4][4],
|
||||
float r_originmat[3][3])
|
||||
{
|
||||
float totmat[4][4];
|
||||
float tmat[4][4];
|
||||
|
@ -3358,7 +3361,7 @@ void BKE_object_where_is_calc_time(Depsgraph *depsgraph, Scene *scene, Object *o
|
|||
object_where_is_calc_ex(depsgraph, scene, ob, ctime, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void BKE_object_where_is_calc_mat4(Object *ob, float r_obmat[4][4])
|
||||
void BKE_object_where_is_calc_mat4(const Object *ob, float r_obmat[4][4])
|
||||
{
|
||||
if (ob->parent) {
|
||||
Object *par = ob->parent;
|
||||
|
@ -4202,7 +4205,7 @@ Mesh *BKE_object_get_original_mesh(const Object *object)
|
|||
return result;
|
||||
}
|
||||
|
||||
Mesh *BKE_object_get_editmesh_eval_final(const Object *object)
|
||||
const Mesh *BKE_object_get_editmesh_eval_final(const Object *object)
|
||||
{
|
||||
BLI_assert(!DEG_is_original_id(&object->id));
|
||||
BLI_assert(object->type == OB_MESH);
|
||||
|
@ -4217,7 +4220,7 @@ Mesh *BKE_object_get_editmesh_eval_final(const Object *object)
|
|||
return reinterpret_cast<Mesh *>(object->runtime->data_eval);
|
||||
}
|
||||
|
||||
Mesh *BKE_object_get_editmesh_eval_cage(const Object *object)
|
||||
const Mesh *BKE_object_get_editmesh_eval_cage(const Object *object)
|
||||
{
|
||||
BLI_assert(!DEG_is_original_id(&object->id));
|
||||
BLI_assert(object->type == OB_MESH);
|
||||
|
@ -4229,6 +4232,13 @@ Mesh *BKE_object_get_editmesh_eval_cage(const Object *object)
|
|||
return object->runtime->editmesh_eval_cage;
|
||||
}
|
||||
|
||||
const Mesh *BKE_object_get_mesh_deform_eval(const Object *object)
|
||||
{
|
||||
BLI_assert(!DEG_is_original_id(&object->id));
|
||||
BLI_assert(object->type == OB_MESH);
|
||||
return object->runtime->mesh_deform_eval;
|
||||
}
|
||||
|
||||
Lattice *BKE_object_get_lattice(const Object *object)
|
||||
{
|
||||
ID *data = (ID *)object->data;
|
||||
|
@ -4806,7 +4816,7 @@ int BKE_object_scenes_users_get(Main *bmain, Object *ob)
|
|||
return num_scenes;
|
||||
}
|
||||
|
||||
MovieClip *BKE_object_movieclip_get(Scene *scene, Object *ob, bool use_default)
|
||||
MovieClip *BKE_object_movieclip_get(Scene *scene, const Object *ob, bool use_default)
|
||||
{
|
||||
MovieClip *clip = use_default ? scene->clip : nullptr;
|
||||
bConstraint *con = (bConstraint *)ob->constraints.first, *scon = nullptr;
|
||||
|
@ -5039,8 +5049,9 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot)
|
|||
Mesh *mesh = (Mesh *)ob->data;
|
||||
uint i;
|
||||
|
||||
Mesh *mesh_eval = ob->runtime->mesh_deform_eval ? ob->runtime->mesh_deform_eval :
|
||||
BKE_object_get_evaluated_mesh(ob);
|
||||
const Mesh *mesh_eval = BKE_object_get_mesh_deform_eval(ob) ?
|
||||
BKE_object_get_mesh_deform_eval(ob) :
|
||||
BKE_object_get_evaluated_mesh(ob);
|
||||
const int *index;
|
||||
|
||||
if (mesh_eval &&
|
||||
|
|
|
@ -472,11 +472,11 @@ static const Mesh *mesh_data_from_duplicator_object(Object *ob,
|
|||
*r_em = em;
|
||||
mesh_eval = nullptr;
|
||||
|
||||
if ((emd != nullptr) && !emd->vertexCos.is_empty()) {
|
||||
*r_vert_coords = reinterpret_cast<const float(*)[3]>(emd->vertexCos.data());
|
||||
if ((emd != nullptr) && !emd->vert_positions.is_empty()) {
|
||||
*r_vert_coords = reinterpret_cast<const float(*)[3]>(emd->vert_positions.data());
|
||||
if (r_vert_normals != nullptr) {
|
||||
BKE_editmesh_cache_ensure_vert_normals(*em, *emd);
|
||||
*r_vert_normals = reinterpret_cast<const float(*)[3]>(emd->vertexNos.data());
|
||||
*r_vert_normals = reinterpret_cast<const float(*)[3]>(emd->vert_normals.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1755,7 +1755,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
|||
Scene *scene = DEG_get_input_scene(depsgraph);
|
||||
Sculpt *sd = scene->toolsettings->sculpt;
|
||||
SculptSession *ss = ob->sculpt;
|
||||
Mesh *mesh = BKE_object_get_original_mesh(ob);
|
||||
Mesh *mesh_orig = BKE_object_get_original_mesh(ob);
|
||||
Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval);
|
||||
MultiresModifierData *mmd = sculpt_multires_modifier_get(scene, ob, true);
|
||||
const bool use_face_sets = (ob->mode & OB_MODE_SCULPT) != 0;
|
||||
|
@ -1786,28 +1786,28 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
|||
ss->multires.level = mmd->sculptlvl;
|
||||
ss->totvert = mesh_eval->verts_num;
|
||||
ss->faces_num = mesh_eval->faces_num;
|
||||
ss->totfaces = mesh->faces_num;
|
||||
ss->totfaces = mesh_orig->faces_num;
|
||||
|
||||
/* These are assigned to the base mesh in Multires. This is needed because Face Sets operators
|
||||
* and tools use the Face Sets data from the base mesh when Multires is active. */
|
||||
ss->vert_positions = mesh->vert_positions_for_write();
|
||||
ss->faces = mesh->faces();
|
||||
ss->corner_verts = mesh->corner_verts();
|
||||
ss->vert_positions = mesh_orig->vert_positions_for_write();
|
||||
ss->faces = mesh_orig->faces();
|
||||
ss->corner_verts = mesh_orig->corner_verts();
|
||||
}
|
||||
else {
|
||||
ss->totvert = mesh->verts_num;
|
||||
ss->faces_num = mesh->faces_num;
|
||||
ss->totfaces = mesh->faces_num;
|
||||
ss->vert_positions = mesh->vert_positions_for_write();
|
||||
ss->faces = mesh->faces();
|
||||
ss->corner_verts = mesh->corner_verts();
|
||||
ss->totvert = mesh_orig->verts_num;
|
||||
ss->faces_num = mesh_orig->faces_num;
|
||||
ss->totfaces = mesh_orig->faces_num;
|
||||
ss->vert_positions = mesh_orig->vert_positions_for_write();
|
||||
ss->faces = mesh_orig->faces();
|
||||
ss->corner_verts = mesh_orig->corner_verts();
|
||||
ss->multires.active = false;
|
||||
ss->multires.modifier = nullptr;
|
||||
ss->multires.level = 0;
|
||||
|
||||
CustomDataLayer *layer;
|
||||
AttrDomain domain;
|
||||
if (BKE_pbvh_get_color_layer(mesh, &layer, &domain)) {
|
||||
if (BKE_pbvh_get_color_layer(mesh_orig, &layer, &domain)) {
|
||||
if (layer->type == CD_PROP_COLOR) {
|
||||
ss->vcol = static_cast<MPropCol *>(layer->data);
|
||||
}
|
||||
|
@ -1830,13 +1830,14 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
|||
/* Sculpt Face Sets. */
|
||||
if (use_face_sets) {
|
||||
ss->face_sets = static_cast<const int *>(
|
||||
CustomData_get_layer_named(&mesh->face_data, CD_PROP_INT32, ".sculpt_face_set"));
|
||||
CustomData_get_layer_named(&mesh_orig->face_data, CD_PROP_INT32, ".sculpt_face_set"));
|
||||
}
|
||||
else {
|
||||
ss->face_sets = nullptr;
|
||||
}
|
||||
|
||||
ss->hide_poly = (bool *)CustomData_get_layer_named(&mesh->face_data, CD_PROP_BOOL, ".hide_poly");
|
||||
ss->hide_poly = (bool *)CustomData_get_layer_named(
|
||||
&mesh_orig->face_data, CD_PROP_BOOL, ".hide_poly");
|
||||
|
||||
ss->subdiv_ccg = mesh_eval->runtime->subdiv_ccg.get();
|
||||
|
||||
|
@ -1850,7 +1851,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
|||
sculpt_update_persistent_base(ob);
|
||||
|
||||
if (ob->type == OB_MESH) {
|
||||
ss->vert_to_face_map = mesh->vert_to_face_map();
|
||||
ss->vert_to_face_map = mesh_orig->vert_to_face_map();
|
||||
}
|
||||
|
||||
if (ss->pbvh) {
|
||||
|
@ -1862,7 +1863,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
|||
bool used_me_eval = false;
|
||||
|
||||
if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
|
||||
Mesh *me_eval_deform = ob_eval->runtime->mesh_deform_eval;
|
||||
const Mesh *me_eval_deform = BKE_object_get_mesh_deform_eval(ob_eval);
|
||||
|
||||
/* If the fully evaluated mesh has the same topology as the deform-only version, use it.
|
||||
* This matters because crazyspace evaluation is very restrictive and excludes even modifiers
|
||||
|
@ -1873,7 +1874,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
|||
{
|
||||
BKE_sculptsession_free_deformMats(ss);
|
||||
|
||||
BLI_assert(me_eval_deform->verts_num == mesh->verts_num);
|
||||
BLI_assert(me_eval_deform->verts_num == mesh_orig->verts_num);
|
||||
|
||||
ss->deform_cos = mesh_eval->vert_positions();
|
||||
BKE_pbvh_vert_coords_apply(ss->pbvh, ss->deform_cos);
|
||||
|
@ -1887,8 +1888,8 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
|||
|
||||
ss->orig_cos = (ss->shapekey_active) ?
|
||||
Span(static_cast<const float3 *>(ss->shapekey_active->data),
|
||||
mesh->verts_num) :
|
||||
mesh->vert_positions();
|
||||
mesh_orig->verts_num) :
|
||||
mesh_orig->vert_positions();
|
||||
|
||||
BKE_crazyspace_build_sculpt(depsgraph, scene, ob, ss->deform_imats, ss->deform_cos);
|
||||
BKE_pbvh_vert_coords_apply(ss->pbvh, ss->deform_cos);
|
||||
|
@ -1903,14 +1904,16 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
|||
}
|
||||
|
||||
if (ss->shapekey_active != nullptr && ss->deform_cos.is_empty()) {
|
||||
ss->deform_cos = Span(static_cast<const float3 *>(ss->shapekey_active->data), mesh->verts_num);
|
||||
ss->deform_cos = Span(static_cast<const float3 *>(ss->shapekey_active->data),
|
||||
mesh_orig->verts_num);
|
||||
}
|
||||
|
||||
/* if pbvh is deformed, key block is already applied to it */
|
||||
if (ss->shapekey_active) {
|
||||
bool pbvh_deformed = BKE_pbvh_is_deformed(ss->pbvh);
|
||||
if (!pbvh_deformed || ss->deform_cos.is_empty()) {
|
||||
const Span key_data(static_cast<const float3 *>(ss->shapekey_active->data), mesh->verts_num);
|
||||
const Span key_data(static_cast<const float3 *>(ss->shapekey_active->data),
|
||||
mesh_orig->verts_num);
|
||||
|
||||
if (key_data.data() != nullptr) {
|
||||
if (!pbvh_deformed) {
|
||||
|
@ -2220,7 +2223,7 @@ static PBVH *build_pbvh_for_dynamic_topology(Object *ob)
|
|||
ob->sculpt->attrs.dyntopo_node_id_face->bmesh_cd_offset);
|
||||
}
|
||||
|
||||
static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform)
|
||||
static PBVH *build_pbvh_from_regular_mesh(Object *ob, const Mesh *me_eval_deform)
|
||||
{
|
||||
Mesh *mesh = BKE_object_get_original_mesh(ob);
|
||||
PBVH *pbvh = pbvh::build_mesh(mesh);
|
||||
|
@ -2293,7 +2296,7 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
|||
pbvh = build_pbvh_from_ccg(ob, mesh_eval->runtime->subdiv_ccg.get());
|
||||
}
|
||||
else if (ob->type == OB_MESH) {
|
||||
Mesh *me_eval_deform = object_eval->runtime->mesh_deform_eval;
|
||||
const Mesh *me_eval_deform = BKE_object_get_mesh_deform_eval(object_eval);
|
||||
pbvh = build_pbvh_from_regular_mesh(ob, me_eval_deform);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include "BKE_mesh.hh"
|
||||
#include "BKE_mesh_runtime.hh"
|
||||
#include "BKE_object.hh"
|
||||
#include "BKE_object_types.hh"
|
||||
#include "BKE_pointcache.h"
|
||||
#include "BKE_report.hh"
|
||||
#include "BKE_rigidbody.h"
|
||||
|
@ -338,13 +337,13 @@ void BKE_rigidbody_object_copy(Main *bmain, Object *ob_dst, const Object *ob_src
|
|||
/* Setup Utilities - Validate Sim Instances */
|
||||
|
||||
/* get the appropriate evaluated mesh based on rigid body mesh source */
|
||||
static Mesh *rigidbody_get_mesh(Object *ob)
|
||||
static const Mesh *rigidbody_get_mesh(Object *ob)
|
||||
{
|
||||
BLI_assert(ob->type == OB_MESH);
|
||||
|
||||
switch (ob->rigidbody_object->mesh_source) {
|
||||
case RBO_MESH_DEFORM:
|
||||
return ob->runtime->mesh_deform_eval;
|
||||
return BKE_object_get_mesh_deform_eval(ob);
|
||||
case RBO_MESH_FINAL:
|
||||
return BKE_object_get_evaluated_mesh(ob);
|
||||
case RBO_MESH_BASE:
|
||||
|
@ -366,13 +365,13 @@ static rbCollisionShape *rigidbody_get_shape_convexhull_from_mesh(Object *ob,
|
|||
bool *can_embed)
|
||||
{
|
||||
rbCollisionShape *shape = nullptr;
|
||||
Mesh *mesh = nullptr;
|
||||
float(*positions)[3] = nullptr;
|
||||
const Mesh *mesh = nullptr;
|
||||
const float(*positions)[3] = nullptr;
|
||||
int totvert = 0;
|
||||
|
||||
if (ob->type == OB_MESH && ob->data) {
|
||||
mesh = rigidbody_get_mesh(ob);
|
||||
positions = (mesh) ? reinterpret_cast<float(*)[3]>(mesh->vert_positions_for_write().data()) :
|
||||
positions = (mesh) ? reinterpret_cast<const float(*)[3]>(mesh->vert_positions().data()) :
|
||||
nullptr;
|
||||
totvert = (mesh) ? mesh->verts_num : 0;
|
||||
}
|
||||
|
@ -399,7 +398,7 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
|
|||
rbCollisionShape *shape = nullptr;
|
||||
|
||||
if (ob->type == OB_MESH) {
|
||||
Mesh *mesh = rigidbody_get_mesh(ob);
|
||||
const Mesh *mesh = rigidbody_get_mesh(ob);
|
||||
if (mesh == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -668,7 +667,7 @@ void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
|
|||
case RB_SHAPE_CONVEXH:
|
||||
case RB_SHAPE_TRIMESH: {
|
||||
if (ob->type == OB_MESH) {
|
||||
Mesh *mesh = rigidbody_get_mesh(ob);
|
||||
const Mesh *mesh = rigidbody_get_mesh(ob);
|
||||
if (mesh == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
@ -742,7 +741,7 @@ void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_center[3])
|
|||
case RB_SHAPE_CONVEXH:
|
||||
case RB_SHAPE_TRIMESH: {
|
||||
if (ob->type == OB_MESH) {
|
||||
Mesh *mesh = rigidbody_get_mesh(ob);
|
||||
const Mesh *mesh = rigidbody_get_mesh(ob);
|
||||
if (mesh == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
@ -1763,10 +1762,10 @@ static void rigidbody_update_sim_ob(Depsgraph *depsgraph, Object *ob, RigidBodyO
|
|||
const bool is_selected = base ? (base->flag & BASE_SELECTED) != 0 : false;
|
||||
|
||||
if (rbo->shape == RB_SHAPE_TRIMESH && rbo->flag & RBO_FLAG_USE_DEFORM) {
|
||||
Mesh *mesh = ob->runtime->mesh_deform_eval;
|
||||
const Mesh *mesh = BKE_object_get_mesh_deform_eval(ob);
|
||||
if (mesh) {
|
||||
float(*positions)[3] = reinterpret_cast<float(*)[3]>(
|
||||
mesh->vert_positions_for_write().data());
|
||||
const float(*positions)[3] = reinterpret_cast<const float(*)[3]>(
|
||||
mesh->vert_positions().data());
|
||||
int totvert = mesh->verts_num;
|
||||
const std::optional<blender::Bounds<blender::float3>> bounds = BKE_object_boundbox_get(ob);
|
||||
|
||||
|
|
|
@ -1032,7 +1032,9 @@ static void mesh_corner_tris_target_project(void *userdata,
|
|||
update_hit(nearest, index, co, hit_co, hit_no);
|
||||
}
|
||||
/* Boundary edges */
|
||||
else if (tree->boundary && tree->boundary->tri_has_boundary[index]) {
|
||||
else if (tree->boundary && tree->boundary->has_boundary() &&
|
||||
tree->boundary->tri_has_boundary[index])
|
||||
{
|
||||
const BitSpan is_boundary = tree->boundary->edge_is_boundary;
|
||||
const int3 edges = bke::mesh::corner_tri_get_real_edges(
|
||||
data->edges, data->corner_verts, tree->corner_edges, tri);
|
||||
|
|
|
@ -367,7 +367,7 @@ void BKE_tracking_settings_init(MovieTracking *tracking)
|
|||
BKE_tracking_object_add(tracking, DATA_("Camera"));
|
||||
}
|
||||
|
||||
void BKE_tracking_get_camera_object_matrix(Object *camera_object, float mat[4][4])
|
||||
void BKE_tracking_get_camera_object_matrix(const Object *camera_object, float mat[4][4])
|
||||
{
|
||||
BLI_assert(camera_object != nullptr);
|
||||
/* NOTE: Construct matrix from scratch rather than using obmat because the camera object here
|
||||
|
|
|
@ -490,21 +490,40 @@ BLI_INLINE float perlin_noise(float4 position)
|
|||
|
||||
float perlin_signed(float position)
|
||||
{
|
||||
/* Repeat Perlin noise texture every 100000.0 on each axis to prevent floating point
|
||||
* representation issues. */
|
||||
position = math::mod(position, 100000.0f);
|
||||
|
||||
return perlin_noise(position) * 0.2500f;
|
||||
}
|
||||
|
||||
float perlin_signed(float2 position)
|
||||
{
|
||||
/* Repeat Perlin noise texture every 100000.0f on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0f, however at such scales
|
||||
* this usually shouldn't be noticeable. */
|
||||
position = math::mod(position, 100000.0f);
|
||||
|
||||
return perlin_noise(position) * 0.6616f;
|
||||
}
|
||||
|
||||
float perlin_signed(float3 position)
|
||||
{
|
||||
/* Repeat Perlin noise texture every 100000.0f on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0f, however at such scales
|
||||
* this usually shouldn't be noticeable. */
|
||||
position = math::mod(position, 100000.0f);
|
||||
|
||||
return perlin_noise(position) * 0.9820f;
|
||||
}
|
||||
|
||||
float perlin_signed(float4 position)
|
||||
{
|
||||
/* Repeat Perlin noise texture every 100000.0f on each axis to prevent floating point
|
||||
* representation issues. This causes discontinuities every 100000.0f, however at such scales
|
||||
* this usually shouldn't be noticeable. */
|
||||
position = math::mod(position, 100000.0f);
|
||||
|
||||
return perlin_noise(position) * 0.8344f;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
|
||||
#include "bmesh.hh"
|
||||
|
||||
using blender::Array;
|
||||
using blender::float3;
|
||||
using blender::MutableSpan;
|
||||
|
||||
const BMAllocTemplate bm_mesh_allocsize_default = {512, 1024, 2048, 512};
|
||||
const BMAllocTemplate bm_mesh_chunksize_default = {512, 1024, 2048, 512};
|
||||
|
||||
|
@ -1328,23 +1332,21 @@ void BM_mesh_toolflags_set(BMesh *bm, bool use_toolflags)
|
|||
/** \name BMesh Coordinate Access
|
||||
* \{ */
|
||||
|
||||
void BM_mesh_vert_coords_get(BMesh *bm, float (*vert_coords)[3])
|
||||
void BM_mesh_vert_coords_get(BMesh *bm, MutableSpan<float3> positions)
|
||||
{
|
||||
BMIter iter;
|
||||
BMVert *v;
|
||||
int i;
|
||||
BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
|
||||
copy_v3_v3(vert_coords[i], v->co);
|
||||
positions[i] = v->co;
|
||||
}
|
||||
}
|
||||
|
||||
float (*BM_mesh_vert_coords_alloc(BMesh *bm, int *r_vert_len))[3]
|
||||
Array<float3> BM_mesh_vert_coords_alloc(BMesh *bm)
|
||||
{
|
||||
float(*vert_coords)[3] = static_cast<float(*)[3]>(
|
||||
MEM_mallocN(bm->totvert * sizeof(*vert_coords), __func__));
|
||||
BM_mesh_vert_coords_get(bm, vert_coords);
|
||||
*r_vert_len = bm->totvert;
|
||||
return vert_coords;
|
||||
Array<float3> positions(bm->totvert);
|
||||
BM_mesh_vert_coords_get(bm, positions);
|
||||
return positions;
|
||||
}
|
||||
|
||||
void BM_mesh_vert_coords_apply(BMesh *bm, const float (*vert_coords)[3])
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
* \ingroup bmesh
|
||||
*/
|
||||
|
||||
#include "BLI_array.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_span.hh"
|
||||
|
||||
#include "bmesh_class.hh"
|
||||
|
||||
struct BMAllocTemplate;
|
||||
|
@ -197,8 +201,8 @@ extern const BMAllocTemplate bm_mesh_chunksize_default;
|
|||
VA_NARGS_CALL_OVERLOAD(_VA_BMALLOC_TEMPLATE_FROM_ME_, __VA_ARGS__)
|
||||
|
||||
/* Vertex coords access. */
|
||||
void BM_mesh_vert_coords_get(BMesh *bm, float (*vert_coords)[3]);
|
||||
float (*BM_mesh_vert_coords_alloc(BMesh *bm, int *r_vert_len))[3];
|
||||
void BM_mesh_vert_coords_get(BMesh *bm, blender::MutableSpan<blender::float3> positions);
|
||||
blender::Array<blender::float3> BM_mesh_vert_coords_alloc(BMesh *bm);
|
||||
void BM_mesh_vert_coords_apply(BMesh *bm, const float (*vert_coords)[3]);
|
||||
void BM_mesh_vert_coords_apply_with_mat4(BMesh *bm,
|
||||
const float (*vert_coords)[3],
|
||||
|
|
|
@ -90,9 +90,8 @@ static float bm_face_calc_poly_normal_vertex_cos(const BMFace *f,
|
|||
/**
|
||||
* \brief COMPUTE POLY CENTER (BMFace)
|
||||
*/
|
||||
static void bm_face_calc_poly_center_median_vertex_cos(const BMFace *f,
|
||||
float r_cent[3],
|
||||
float const (*vertexCos)[3])
|
||||
static void bm_face_calc_poly_center_median_vertex_cos(
|
||||
const BMFace *f, float r_cent[3], const blender::Span<blender::float3> vert_positions)
|
||||
{
|
||||
const BMLoop *l_first, *l_iter;
|
||||
|
||||
|
@ -101,7 +100,7 @@ static void bm_face_calc_poly_center_median_vertex_cos(const BMFace *f,
|
|||
/* Newell's Method */
|
||||
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
||||
do {
|
||||
add_v3_v3(r_cent, vertexCos[BM_elem_index_get(l_iter->v)]);
|
||||
add_v3_v3(r_cent, vert_positions[BM_elem_index_get(l_iter->v)]);
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
mul_v3_fl(r_cent, 1.0f / f->len);
|
||||
}
|
||||
|
@ -520,7 +519,7 @@ void BM_face_calc_center_bounds(const BMFace *f, float r_cent[3])
|
|||
void BM_face_calc_center_bounds_vcos(const BMesh *bm,
|
||||
const BMFace *f,
|
||||
float r_cent[3],
|
||||
float const (*vertexCos)[3])
|
||||
const blender::Span<blender::float3> vert_positions)
|
||||
{
|
||||
/* must have valid index data */
|
||||
BLI_assert((bm->elem_index_dirty & BM_VERT) == 0);
|
||||
|
@ -533,7 +532,7 @@ void BM_face_calc_center_bounds_vcos(const BMesh *bm,
|
|||
|
||||
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
||||
do {
|
||||
minmax_v3v3_v3(min, max, vertexCos[BM_elem_index_get(l_iter->v)]);
|
||||
minmax_v3v3_v3(min, max, vert_positions[BM_elem_index_get(l_iter->v)]);
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
|
||||
mid_v3_v3v3(r_cent, min, max);
|
||||
|
@ -900,13 +899,13 @@ float BM_face_calc_normal_subset(const BMLoop *l_first, const BMLoop *l_last, fl
|
|||
void BM_face_calc_center_median_vcos(const BMesh *bm,
|
||||
const BMFace *f,
|
||||
float r_cent[3],
|
||||
float const (*vertexCos)[3])
|
||||
const blender::Span<blender::float3> vert_positions)
|
||||
{
|
||||
/* must have valid index data */
|
||||
BLI_assert((bm->elem_index_dirty & BM_VERT) == 0);
|
||||
(void)bm;
|
||||
|
||||
bm_face_calc_poly_center_median_vertex_cos(f, r_cent, vertexCos);
|
||||
bm_face_calc_poly_center_median_vertex_cos(f, r_cent, vert_positions);
|
||||
}
|
||||
|
||||
void BM_face_normal_flip_ex(BMesh *bm,
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
struct Heap;
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_span.hh"
|
||||
|
||||
/**
|
||||
* For tools that insist on using triangles, ideally we would cache this data.
|
||||
|
@ -128,7 +130,7 @@ void BM_face_calc_center_bounds(const BMFace *f, float r_cent[3]) ATTR_NONNULL()
|
|||
void BM_face_calc_center_bounds_vcos(const BMesh *bm,
|
||||
const BMFace *f,
|
||||
float r_center[3],
|
||||
float const (*vertexCos)[3]) ATTR_NONNULL();
|
||||
blender::Span<blender::float3> vert_positions) ATTR_NONNULL();
|
||||
/**
|
||||
* computes the center of a face, using the mean average
|
||||
*/
|
||||
|
@ -137,7 +139,8 @@ void BM_face_calc_center_median(const BMFace *f, float r_center[3]) ATTR_NONNULL
|
|||
void BM_face_calc_center_median_vcos(const BMesh *bm,
|
||||
const BMFace *f,
|
||||
float r_center[3],
|
||||
float const (*vertexCos)[3]) ATTR_NONNULL();
|
||||
const blender::Span<blender::float3> vert_positions)
|
||||
ATTR_NONNULL();
|
||||
/**
|
||||
* computes the center of a face, using the mean average
|
||||
* weighted by edge length
|
||||
|
|
|
@ -586,6 +586,7 @@ set(GLSL_SRC
|
|||
engines/eevee_next/shaders/eevee_shadow_tag_usage_vert.glsl
|
||||
engines/eevee_next/shaders/eevee_shadow_tag_usage_volume_comp.glsl
|
||||
engines/eevee_next/shaders/eevee_shadow_test.glsl
|
||||
engines/eevee_next/shaders/eevee_shadow_tilemap_amend_comp.glsl
|
||||
engines/eevee_next/shaders/eevee_shadow_tilemap_bounds_comp.glsl
|
||||
engines/eevee_next/shaders/eevee_shadow_tilemap_finalize_comp.glsl
|
||||
engines/eevee_next/shaders/eevee_shadow_tilemap_init_comp.glsl
|
||||
|
|
|
@ -87,6 +87,8 @@
|
|||
#define SHADOW_TILEDATA_PER_TILEMAP \
|
||||
(SHADOW_TILEMAP_LOD0_LEN + SHADOW_TILEMAP_LOD1_LEN + SHADOW_TILEMAP_LOD2_LEN + \
|
||||
SHADOW_TILEMAP_LOD3_LEN + SHADOW_TILEMAP_LOD4_LEN + SHADOW_TILEMAP_LOD5_LEN)
|
||||
/* Maximum number of relative LOD distance we can store. */
|
||||
#define SHADOW_TILEMAP_MAX_CLIPMAP_LOD 8
|
||||
#if 0
|
||||
/* Useful for debugging the tile-copy version of the shadow rendering without making debugging
|
||||
* tools unresponsive. */
|
||||
|
|
|
@ -241,6 +241,8 @@ const char *ShaderModule::static_shader_create_info_name_get(eShaderType shader_
|
|||
return "eevee_shadow_page_free";
|
||||
case SHADOW_PAGE_MASK:
|
||||
return "eevee_shadow_page_mask";
|
||||
case SHADOW_TILEMAP_AMEND:
|
||||
return "eevee_shadow_tilemap_amend";
|
||||
case SHADOW_TILEMAP_BOUNDS:
|
||||
return "eevee_shadow_tilemap_bounds";
|
||||
case SHADOW_TILEMAP_FINALIZE:
|
||||
|
|
|
@ -120,6 +120,7 @@ enum eShaderType {
|
|||
SHADOW_PAGE_MASK,
|
||||
SHADOW_PAGE_TILE_CLEAR,
|
||||
SHADOW_PAGE_TILE_STORE,
|
||||
SHADOW_TILEMAP_AMEND,
|
||||
SHADOW_TILEMAP_BOUNDS,
|
||||
SHADOW_TILEMAP_FINALIZE,
|
||||
SHADOW_TILEMAP_INIT,
|
||||
|
|
|
@ -1231,8 +1231,6 @@ struct ShadowTileData {
|
|||
uint3 page;
|
||||
/** Page index inside pages_cached_buf. Only valid if `is_cached` is true. */
|
||||
uint cache_index;
|
||||
/** LOD pointed to LOD 0 tile page. (cube-map only). */
|
||||
uint lod;
|
||||
/** If the tile is needed for rendering. */
|
||||
bool is_used;
|
||||
/** True if an update is needed. This persists even if the tile gets unused. */
|
||||
|
@ -1279,8 +1277,7 @@ static inline ShadowTileData shadow_tile_unpack(ShadowTileDataPacked data)
|
|||
ShadowTileData tile;
|
||||
tile.page = shadow_page_unpack(data);
|
||||
/* -- 12 bits -- */
|
||||
BLI_STATIC_ASSERT(SHADOW_TILEMAP_LOD < 8, "Update page packing")
|
||||
tile.lod = (data >> 12u) & 7u;
|
||||
/* Unused bits. */
|
||||
/* -- 15 bits -- */
|
||||
BLI_STATIC_ASSERT(SHADOW_MAX_PAGE <= 4096, "Update page packing")
|
||||
tile.cache_index = (data >> 15u) & 4095u;
|
||||
|
@ -1299,7 +1296,6 @@ static inline ShadowTileDataPacked shadow_tile_pack(ShadowTileData tile)
|
|||
/* NOTE: Page might be set to invalid values for tracking invalid usages.
|
||||
* So we have to mask the result. */
|
||||
data = shadow_page_pack(tile.page) & uint(SHADOW_MAX_PAGE - 1);
|
||||
data |= (tile.lod & 7u) << 12u;
|
||||
data |= (tile.cache_index & 4095u) << 15u;
|
||||
data |= (tile.is_used ? uint(SHADOW_IS_USED) : 0);
|
||||
data |= (tile.is_allocated ? uint(SHADOW_IS_ALLOCATED) : 0);
|
||||
|
@ -1309,6 +1305,89 @@ static inline ShadowTileDataPacked shadow_tile_pack(ShadowTileData tile)
|
|||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decoded tile data structure.
|
||||
* Similar to ShadowTileData, this one is only used for rendering and packed into `tilemap_tx`.
|
||||
* This allow to reuse some bits for other purpose.
|
||||
*/
|
||||
struct ShadowSamplingTile {
|
||||
/** Page inside the virtual shadow map atlas. */
|
||||
uint3 page;
|
||||
/** LOD pointed to LOD 0 tile page. */
|
||||
uint lod;
|
||||
/** Offset to the texel position to align with the LOD page start. (directional only). */
|
||||
uint2 lod_offset;
|
||||
/** If the tile is needed for rendering. */
|
||||
bool is_valid;
|
||||
};
|
||||
/** \note Stored packed as a uint. */
|
||||
#define ShadowSamplingTilePacked uint
|
||||
|
||||
/* NOTE: Trust the input to be in valid range [0, (1 << SHADOW_TILEMAP_MAX_CLIPMAP_LOD) - 1].
|
||||
* Maximum LOD level index we can store is SHADOW_TILEMAP_MAX_CLIPMAP_LOD,
|
||||
* so we need SHADOW_TILEMAP_MAX_CLIPMAP_LOD bits to store the offset in each dimension.
|
||||
* Result fits into SHADOW_TILEMAP_MAX_CLIPMAP_LOD * 2 bits. */
|
||||
static inline uint shadow_lod_offset_pack(uint2 ofs)
|
||||
{
|
||||
BLI_STATIC_ASSERT(SHADOW_TILEMAP_MAX_CLIPMAP_LOD <= 8, "Update page packing")
|
||||
return ofs.x | (ofs.y << SHADOW_TILEMAP_MAX_CLIPMAP_LOD);
|
||||
}
|
||||
static inline uint2 shadow_lod_offset_unpack(uint data)
|
||||
{
|
||||
return (uint2(data) >> uint2(0, SHADOW_TILEMAP_MAX_CLIPMAP_LOD)) &
|
||||
uint2((1 << SHADOW_TILEMAP_MAX_CLIPMAP_LOD) - 1);
|
||||
}
|
||||
|
||||
static inline ShadowSamplingTile shadow_sampling_tile_unpack(ShadowSamplingTilePacked data)
|
||||
{
|
||||
ShadowSamplingTile tile;
|
||||
tile.page = shadow_page_unpack(data);
|
||||
/* -- 12 bits -- */
|
||||
/* Max value is actually SHADOW_TILEMAP_MAX_CLIPMAP_LOD but we mask the bits. */
|
||||
tile.lod = (data >> 12u) & 15u;
|
||||
/* -- 16 bits -- */
|
||||
tile.lod_offset = shadow_lod_offset_unpack(data >> 16u);
|
||||
/* -- 32 bits -- */
|
||||
tile.is_valid = data != 0u;
|
||||
#ifndef GPU_SHADER
|
||||
/* Make tests pass on CPU but it is not required for proper rendering. */
|
||||
if (tile.lod == 0) {
|
||||
tile.lod_offset.x = 0;
|
||||
}
|
||||
#endif
|
||||
return tile;
|
||||
}
|
||||
|
||||
static inline ShadowSamplingTilePacked shadow_sampling_tile_pack(ShadowSamplingTile tile)
|
||||
{
|
||||
if (!tile.is_valid) {
|
||||
return 0u;
|
||||
}
|
||||
/* Tag a valid tile of LOD0 valid by setting their offset to 1.
|
||||
* This doesn't change the sampling and allows to use of all bits for data.
|
||||
* This makes sure no valid packed tile is 0u. */
|
||||
if (tile.lod == 0) {
|
||||
tile.lod_offset.x = 1;
|
||||
}
|
||||
uint data = shadow_page_pack(tile.page);
|
||||
/* Max value is actually SHADOW_TILEMAP_MAX_CLIPMAP_LOD but we mask the bits. */
|
||||
data |= (tile.lod & 15u) << 12u;
|
||||
data |= shadow_lod_offset_pack(tile.lod_offset) << 16u;
|
||||
return data;
|
||||
}
|
||||
|
||||
static inline ShadowSamplingTile shadow_sampling_tile_create(ShadowTileData tile_data, uint lod)
|
||||
{
|
||||
ShadowSamplingTile tile;
|
||||
tile.page = tile_data.page;
|
||||
tile.lod = lod;
|
||||
tile.lod_offset = uint2(0, 0); /* Computed during tilemap amend phase. */
|
||||
/* At this point, it should be the case that all given tiles that have been tagged as used are
|
||||
* ready for sampling. Otherwise tile_data should be SHADOW_NO_DATA. */
|
||||
tile.is_valid = tile_data.is_used;
|
||||
return tile;
|
||||
}
|
||||
|
||||
struct ShadowSceneData {
|
||||
/* Number of shadow rays to shoot for each light. */
|
||||
int ray_count;
|
||||
|
|
|
@ -1199,6 +1199,15 @@ void ShadowModule::end_sync()
|
|||
sub.barrier(GPU_BARRIER_SHADER_STORAGE | GPU_BARRIER_UNIFORM | GPU_BARRIER_TEXTURE_FETCH |
|
||||
GPU_BARRIER_SHADER_IMAGE_ACCESS);
|
||||
}
|
||||
{
|
||||
/* Amend tilemap_tx content to support clipmap LODs. */
|
||||
PassSimple::Sub &sub = pass.sub("Amend");
|
||||
sub.shader_set(inst_.shaders.static_shader_get(SHADOW_TILEMAP_AMEND));
|
||||
sub.bind_image("tilemaps_img", tilemap_pool.tilemap_tx);
|
||||
sub.bind_resources(inst_.lights);
|
||||
sub.dispatch(int3(1));
|
||||
sub.barrier(GPU_BARRIER_TEXTURE_FETCH);
|
||||
}
|
||||
|
||||
/* NOTE: We do not need to run the clear pass when using the TBDR update variant, as tiles
|
||||
* will be fully cleared as part of the shadow raster step. */
|
||||
|
|
|
@ -33,7 +33,6 @@ void debug_tile_print(ShadowTileData tile, ivec4 tile_coord)
|
|||
{
|
||||
#ifdef DRW_DEBUG_PRINT
|
||||
drw_print("Tile (", tile_coord.x, ",", tile_coord.y, ") in Tilemap ", tile_coord.z, " : ");
|
||||
drw_print(tile.lod);
|
||||
drw_print(tile.page);
|
||||
drw_print(tile.cache_index);
|
||||
#endif
|
||||
|
@ -41,10 +40,6 @@ void debug_tile_print(ShadowTileData tile, ivec4 tile_coord)
|
|||
|
||||
vec3 debug_tile_state_color(ShadowTileData tile)
|
||||
{
|
||||
if (tile.lod > 0) {
|
||||
/* Uses data from another LOD. */
|
||||
return neon_gradient(float(tile.lod) / float(SHADOW_TILEMAP_LOD));
|
||||
}
|
||||
if (tile.do_update && tile.is_used) {
|
||||
/* Updated. */
|
||||
return vec3(0.5, 1, 0);
|
||||
|
@ -63,6 +58,17 @@ vec3 debug_tile_state_color(ShadowTileData tile)
|
|||
return col;
|
||||
}
|
||||
|
||||
vec3 debug_tile_state_color(eLightType type, ShadowSamplingTile tile)
|
||||
{
|
||||
if (!tile.is_valid) {
|
||||
return vec3(1, 0, 0);
|
||||
}
|
||||
/* Uses data from another LOD. */
|
||||
return neon_gradient(float(tile.lod) / float((type == LIGHT_SUN) ?
|
||||
SHADOW_TILEMAP_MAX_CLIPMAP_LOD :
|
||||
SHADOW_TILEMAP_LOD));
|
||||
}
|
||||
|
||||
ShadowSampleParams debug_shadow_sample_get(vec3 P, LightData light)
|
||||
{
|
||||
if (is_sun_light(light.type)) {
|
||||
|
@ -73,7 +79,7 @@ ShadowSampleParams debug_shadow_sample_get(vec3 P, LightData light)
|
|||
}
|
||||
}
|
||||
|
||||
ShadowTileData debug_tile_get(vec3 P, LightData light)
|
||||
ShadowSamplingTile debug_tile_get(vec3 P, LightData light)
|
||||
{
|
||||
return shadow_tile_data_get(shadow_tilemaps_tx, debug_shadow_sample_get(P, light));
|
||||
}
|
||||
|
@ -106,6 +112,26 @@ bool debug_tilemaps(vec3 P, LightData light)
|
|||
int tilemap = px.x / SHADOW_TILEMAP_RES;
|
||||
int tilemap_index = light.tilemap_index + tilemap;
|
||||
if ((px.y < SHADOW_TILEMAP_RES) && (tilemap_index <= light_tilemap_max_get(light))) {
|
||||
#if 1
|
||||
/* Debug values in the tilemap_tx. */
|
||||
ivec2 tilemap_texel = shadow_tile_coord_in_atlas(px, tilemap_index);
|
||||
ShadowSamplingTile tile = shadow_sampling_tile_unpack(
|
||||
texelFetch(shadow_tilemaps_tx, tilemap_texel, 0).x);
|
||||
/* Leave 1 px border between tile-maps. */
|
||||
if (!any(equal(ivec2(gl_FragCoord.xy) % (SHADOW_TILEMAP_RES * debug_tile_size_px), ivec2(0))))
|
||||
{
|
||||
gl_FragDepth = 0.0;
|
||||
out_color_add = vec4(debug_tile_state_color(light.type, tile), 0.0);
|
||||
out_color_mul = vec4(0.0);
|
||||
|
||||
# ifdef DRW_DEBUG_PRINT
|
||||
if (all(equal(ivec2(gl_FragCoord.xy), ivec2(0)))) {
|
||||
drw_print(light.object_mat);
|
||||
}
|
||||
# endif
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
/* Debug actual values in the tile-map buffer. */
|
||||
ShadowTileMapData tilemap = tilemaps_buf[tilemap_index];
|
||||
int tile_index = shadow_tile_offset(
|
||||
|
@ -118,21 +144,22 @@ bool debug_tilemaps(vec3 P, LightData light)
|
|||
out_color_add = vec4(debug_tile_state_color(tile), 0.0);
|
||||
out_color_mul = vec4(0.0);
|
||||
|
||||
#ifdef DRW_DEBUG_PRINT
|
||||
# ifdef DRW_DEBUG_PRINT
|
||||
if (all(equal(ivec2(gl_FragCoord.xy), ivec2(0)))) {
|
||||
drw_print(light.object_mat);
|
||||
}
|
||||
#endif
|
||||
# endif
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void debug_tile_state(vec3 P, LightData light)
|
||||
{
|
||||
ShadowTileData tile = debug_tile_get(P, light);
|
||||
out_color_add = vec4(debug_tile_state_color(tile), 0) * 0.5;
|
||||
ShadowSamplingTile tile = debug_tile_get(P, light);
|
||||
out_color_add = vec4(debug_tile_state_color(light.type, tile), 0) * 0.5;
|
||||
out_color_mul = vec4(0.5);
|
||||
}
|
||||
|
||||
|
@ -146,7 +173,7 @@ void debug_atlas_values(vec3 P, LightData light)
|
|||
|
||||
void debug_random_tile_color(vec3 P, LightData light)
|
||||
{
|
||||
ShadowTileData tile = debug_tile_get(P, light);
|
||||
ShadowSamplingTile tile = debug_tile_get(P, light);
|
||||
out_color_add = vec4(debug_random_color(ivec2(tile.page.xy)), 0) * 0.5;
|
||||
out_color_mul = vec4(0.5);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ struct ShadowSampleParams {
|
|||
float z_range;
|
||||
};
|
||||
|
||||
ShadowTileData shadow_tile_data_get(usampler2D tilemaps_tx, ShadowSampleParams params)
|
||||
ShadowSamplingTile shadow_tile_data_get(usampler2D tilemaps_tx, ShadowSampleParams params)
|
||||
{
|
||||
/* Prevent out of bound access. Assumes the input is already non negative. */
|
||||
vec2 tilemap_uv = min(params.uv.xy, vec2(0.99999));
|
||||
|
@ -46,9 +46,9 @@ float shadow_read_depth(SHADOW_ATLAS_TYPE atlas_tx,
|
|||
const int page_shift = SHADOW_PAGE_LOD;
|
||||
|
||||
ivec2 tile_coord = texel_coord >> page_shift;
|
||||
ShadowTileData tile = shadow_tile_load(tilemaps_tx, tile_coord, params.tilemap_index);
|
||||
ShadowSamplingTile tile = shadow_tile_load(tilemaps_tx, tile_coord, params.tilemap_index);
|
||||
|
||||
if (!tile.is_allocated) {
|
||||
if (!tile.is_valid) {
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ void main()
|
|||
ShadowTileData tile = shadow_tile_unpack(tiles_buf[tile_index]);
|
||||
if (tile.is_used && !tile.is_allocated) {
|
||||
shadow_page_alloc(tile);
|
||||
tile.lod = lod;
|
||||
tiles_buf[tile_index] = shadow_tile_pack(tile);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/**
|
||||
* Virtual shadow-mapping: Amend sampling tile atlas.
|
||||
*
|
||||
* In order to support sampling different LOD for clipmap shadow projections, we need to scan
|
||||
* through the LOD tilemaps from lowest LOD to highest LOD, gathering the last valid tile along the
|
||||
* way for the current destination tile. For each new level we gather the previous level tiles from
|
||||
* local memory using the correct relative offset from the previous level as they might not be
|
||||
* aligned.
|
||||
*
|
||||
* TODO(fclem): This shader **should** be dispatched for one thread-group per directional light.
|
||||
* Currently this shader is dispatched with one thread-group for all directional light.
|
||||
*/
|
||||
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_utildefines_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_math_matrix_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_light_iter_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_shadow_tilemap_lib.glsl)
|
||||
|
||||
shared ShadowSamplingTilePacked tiles_local[SHADOW_TILEMAP_RES][SHADOW_TILEMAP_RES];
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 tile_co = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
LIGHT_FOREACH_BEGIN_DIRECTIONAL (light_cull_buf, l_idx) {
|
||||
LightData light = light_buf[l_idx];
|
||||
/* This only works on clipmaps. Cascade have already the same LOD for every tilemaps. */
|
||||
if (light.type != LIGHT_SUN) {
|
||||
break;
|
||||
}
|
||||
ivec2 base_offset_neg = light_sun_data_get(light).clipmap_base_offset_neg;
|
||||
ivec2 base_offset_pos = light_sun_data_get(light).clipmap_base_offset_pos;
|
||||
/* LOD relative max with respect to clipmap_lod_min. */
|
||||
int lod_max = light_sun_data_get(light).clipmap_lod_max -
|
||||
light_sun_data_get(light).clipmap_lod_min;
|
||||
/* Iterate in reverse. */
|
||||
for (int lod = lod_max; lod >= 0; lod--) {
|
||||
int tilemap_index = light.tilemap_index + lod;
|
||||
ivec2 atlas_texel = shadow_tile_coord_in_atlas(tile_co, tilemap_index);
|
||||
|
||||
ShadowSamplingTilePacked tile_packed = imageLoad(tilemaps_img, atlas_texel).x;
|
||||
ShadowSamplingTile tile = shadow_sampling_tile_unpack(tile_packed);
|
||||
|
||||
if (lod != lod_max && !tile.is_valid) {
|
||||
/* Offset this LOD has with the previous one. In unit of tile of the current LOD. */
|
||||
ivec2 offset_binary = ((base_offset_pos >> lod) & 1) - ((base_offset_neg >> lod) & 1);
|
||||
ivec2 offset_centered = ivec2(SHADOW_TILEMAP_RES / 2) + offset_binary;
|
||||
ivec2 tile_co_prev = (tile_co + offset_centered) >> 1;
|
||||
|
||||
/* Load tile from the previous LOD. */
|
||||
ShadowSamplingTilePacked tile_prev_packed = tiles_local[tile_co_prev.y][tile_co_prev.x];
|
||||
ShadowSamplingTile tile_prev = shadow_sampling_tile_unpack(tile_prev_packed);
|
||||
|
||||
/* We can only propagate LODs up to a certain level.
|
||||
* Afterwards we run out of bits to store the offsets. */
|
||||
if (tile_prev.is_valid && tile_prev.lod < SHADOW_TILEMAP_MAX_CLIPMAP_LOD - 1) {
|
||||
/* Relative LOD. Used for reducing pixel rate at sampling time.
|
||||
* Increase with each new invalid level. */
|
||||
tile_prev.lod += 1;
|
||||
|
||||
/* The offset (in tile of current LOD) is equal to the offset from the bottom left corner
|
||||
* of both LODs modulo the size of a tile of the source LOD (in tile of current LOD). */
|
||||
|
||||
/* Offset corner to center. */
|
||||
tile_prev.lod_offset = uvec2(SHADOW_TILEMAP_RES / 2) << tile_prev.lod;
|
||||
/* Align center of both LODs. */
|
||||
tile_prev.lod_offset -= uvec2(SHADOW_TILEMAP_RES / 2);
|
||||
/* Add the offset relative to the source LOD. */
|
||||
tile_prev.lod_offset += uvec2(bitfieldExtract(base_offset_pos, lod, int(tile_prev.lod)) -
|
||||
bitfieldExtract(base_offset_neg, lod, int(tile_prev.lod)));
|
||||
/* Wrap to valid range. */
|
||||
tile_prev.lod_offset &= ~(~0u << tile_prev.lod);
|
||||
|
||||
tile_prev_packed = shadow_sampling_tile_pack(tile_prev);
|
||||
/* Replace the missing page with the one from the lower LOD. */
|
||||
imageStore(tilemaps_img, atlas_texel, uvec4(tile_prev_packed));
|
||||
/* Push this amended tile to the local tiles. */
|
||||
tile_packed = tile_prev_packed;
|
||||
tile.is_valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
barrier();
|
||||
tiles_local[tile_co.y][tile_co.x] = (tile.is_valid) ? tile_packed : SHADOW_NO_DATA;
|
||||
barrier();
|
||||
}
|
||||
}
|
||||
LIGHT_FOREACH_END
|
||||
}
|
|
@ -57,6 +57,7 @@ void main()
|
|||
bool is_cubemap = (tilemap_data.projection_type == SHADOW_PROJECTION_CUBEFACE);
|
||||
int lod_max = is_cubemap ? SHADOW_TILEMAP_LOD : 0;
|
||||
int valid_tile_index = -1;
|
||||
uint valid_lod = 0u;
|
||||
/* With all threads (LOD0 size dispatch) load each lod tile from the highest lod
|
||||
* to the lowest, keeping track of the lowest one allocated which will be use for shadowing.
|
||||
* This guarantee a O(1) lookup time.
|
||||
|
@ -176,12 +177,17 @@ void main()
|
|||
if (tile.is_used && tile.is_allocated && (!tile.do_update || lod_is_rendered)) {
|
||||
/* Save highest lod for this thread. */
|
||||
valid_tile_index = tile_index;
|
||||
valid_lod = uint(lod);
|
||||
}
|
||||
}
|
||||
|
||||
/* Store the highest LOD valid page for rendering. */
|
||||
uint tile_packed = (valid_tile_index != -1) ? tiles_buf[valid_tile_index] : SHADOW_NO_DATA;
|
||||
imageStore(tilemaps_img, atlas_texel, uvec4(tile_packed));
|
||||
ShadowTileDataPacked tile_packed = (valid_tile_index != -1) ? tiles_buf[valid_tile_index] :
|
||||
SHADOW_NO_DATA;
|
||||
ShadowTileData tile_data = shadow_tile_unpack(tile_packed);
|
||||
ShadowSamplingTile tile_sampling = shadow_sampling_tile_create(tile_data, valid_lod);
|
||||
ShadowSamplingTilePacked tile_sampling_packed = shadow_sampling_tile_pack(tile_sampling);
|
||||
imageStore(tilemaps_img, atlas_texel, uvec4(tile_sampling_packed));
|
||||
|
||||
if (all(equal(gl_GlobalInvocationID, uvec3(0)))) {
|
||||
/* Clamp it as it can underflow if there is too much tile present on screen. */
|
||||
|
|
|
@ -91,14 +91,14 @@ int shadow_tile_offset(ivec2 tile, int tiles_index, int lod)
|
|||
* \{ */
|
||||
|
||||
/** \note: Will clamp if out of bounds. */
|
||||
ShadowTileData shadow_tile_load(usampler2D tilemaps_tx, ivec2 tile_co, int tilemap_index)
|
||||
ShadowSamplingTile shadow_tile_load(usampler2D tilemaps_tx, ivec2 tile_co, int tilemap_index)
|
||||
{
|
||||
/* NOTE(@fclem): This clamp can hide some small imprecision at clip-map transition.
|
||||
* Can be disabled to check if the clip-map is well centered. */
|
||||
tile_co = clamp(tile_co, ivec2(0), ivec2(SHADOW_TILEMAP_RES - 1));
|
||||
uint tile_data =
|
||||
texelFetch(tilemaps_tx, shadow_tile_coord_in_atlas(tile_co, tilemap_index), 0).x;
|
||||
return shadow_tile_unpack(tile_data);
|
||||
ivec2 texel = shadow_tile_coord_in_atlas(tile_co, tilemap_index);
|
||||
uint tile_data = texelFetch(tilemaps_tx, texel, 0).x;
|
||||
return shadow_sampling_tile_unpack(tile_data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,16 +23,19 @@ float shadow_read_depth_at_tilemap_uv(int tilemap_index, vec2 tilemap_uv)
|
|||
ivec2 texel_coord = ivec2(tilemap_uv * float(SHADOW_MAP_MAX_RES));
|
||||
/* Using bitwise ops is way faster than integer ops. */
|
||||
const int page_shift = SHADOW_PAGE_LOD;
|
||||
const int page_mask = ~(0xFFFFFFFF << SHADOW_PAGE_LOD);
|
||||
|
||||
ivec2 tile_coord = texel_coord >> page_shift;
|
||||
ShadowTileData tile = shadow_tile_load(shadow_tilemaps_tx, tile_coord, tilemap_index);
|
||||
ShadowSamplingTile tile = shadow_tile_load(shadow_tilemaps_tx, tile_coord, tilemap_index);
|
||||
|
||||
if (!tile.is_allocated) {
|
||||
if (!tile.is_valid) {
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
int page_mask = ~(0xFFFFFFFF << (SHADOW_PAGE_LOD + int(tile.lod)));
|
||||
ivec2 texel_page = (texel_coord & page_mask) >> int(tile.lod);
|
||||
/* Shift LOD0 pixels so that they get wrapped at the right position for the given LOD. */
|
||||
/* TODO convert everything to uint to avoid signed int operations. */
|
||||
texel_coord += ivec2(tile.lod_offset << SHADOW_PAGE_LOD);
|
||||
/* Scale to LOD pixels (merge LOD0 pixels together) then mask to get pixel in page. */
|
||||
ivec2 texel_page = (texel_coord >> int(tile.lod)) & page_mask;
|
||||
ivec3 texel = ivec3((ivec2(tile.page.xy) << page_shift) | texel_page, tile.page.z);
|
||||
|
||||
return uintBitsToFloat(texelFetch(shadow_atlas_tx, texel, 0).r);
|
||||
|
@ -439,8 +442,8 @@ vec3 shadow_pcf_offset(LightData light, const bool is_directional, vec3 P, vec3
|
|||
else {
|
||||
params = shadow_punctual_sample_params_get(light, P);
|
||||
}
|
||||
ShadowTileData tile = shadow_tile_data_get(shadow_tilemaps_tx, params);
|
||||
if (!tile.is_allocated) {
|
||||
ShadowSamplingTile tile = shadow_tile_data_get(shadow_tilemaps_tx, params);
|
||||
if (!tile.is_valid) {
|
||||
return vec3(0.0);
|
||||
}
|
||||
|
||||
|
|
|
@ -195,6 +195,13 @@ GPU_SHADER_CREATE_INFO(eevee_shadow_tilemap_finalize)
|
|||
.additional_info("eevee_shared")
|
||||
.compute_source("eevee_shadow_tilemap_finalize_comp.glsl");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(eevee_shadow_tilemap_amend)
|
||||
.do_static_compilation(true)
|
||||
.local_group_size(SHADOW_TILEMAP_RES, SHADOW_TILEMAP_RES)
|
||||
.image(0, GPU_R32UI, Qualifier::READ_WRITE, ImageType::UINT_2D, "tilemaps_img")
|
||||
.additional_info("eevee_shared", "eevee_light_data", "draw_view")
|
||||
.compute_source("eevee_shadow_tilemap_amend_comp.glsl");
|
||||
|
||||
/* AtomicMin clear implementation. */
|
||||
GPU_SHADER_CREATE_INFO(eevee_shadow_page_clear)
|
||||
.do_static_compilation(true)
|
||||
|
|
|
@ -237,8 +237,8 @@ static void overlay_edit_mesh_add_ob_to_pass(OVERLAY_PrivateData *pd, Object *ob
|
|||
/* TODO: Should be its own function. */
|
||||
Mesh *mesh = (Mesh *)ob->data;
|
||||
if (BMEditMesh *em = mesh->runtime->edit_mesh) {
|
||||
Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob);
|
||||
Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob);
|
||||
const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob);
|
||||
const Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob);
|
||||
|
||||
has_edit_mesh_cage = editmesh_eval_cage && (editmesh_eval_cage != editmesh_eval_final);
|
||||
has_skin_roots = CustomData_get_offset(&em->bm->vdata, CD_MVERT_SKIN) != -1;
|
||||
|
|
|
@ -177,11 +177,11 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
|
|||
bool is_mesh_verts_only = false;
|
||||
if (is_mesh) {
|
||||
/* TODO: Should be its own function. */
|
||||
Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
const Mesh *mesh = static_cast<const Mesh *>(ob->data);
|
||||
if (is_edit_mode) {
|
||||
BLI_assert(mesh->runtime->edit_mesh);
|
||||
Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob);
|
||||
Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob);
|
||||
const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob);
|
||||
const Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob);
|
||||
has_edit_mesh_cage = editmesh_eval_cage && (editmesh_eval_cage != editmesh_eval_final);
|
||||
if (editmesh_eval_final) {
|
||||
mesh = editmesh_eval_final;
|
||||
|
|
|
@ -336,8 +336,7 @@ void mesh_render_data_update_faces_sorted(MeshRenderData &mr,
|
|||
const Mesh *editmesh_final_or_this(const Object *object, const Mesh *mesh)
|
||||
{
|
||||
if (mesh->runtime->edit_mesh != nullptr) {
|
||||
Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object);
|
||||
if (editmesh_eval_final != nullptr) {
|
||||
if (const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object)) {
|
||||
return editmesh_eval_final;
|
||||
}
|
||||
}
|
||||
|
@ -507,7 +506,7 @@ void mesh_render_data_update_normals(MeshRenderData &mr, const eMRDataType data_
|
|||
const float(*vert_normals)[3] = nullptr;
|
||||
const float(*face_normals)[3] = nullptr;
|
||||
|
||||
if (mr.edit_data && !mr.edit_data->vertexCos.is_empty()) {
|
||||
if (mr.edit_data && !mr.edit_data->vert_positions.is_empty()) {
|
||||
vert_coords = reinterpret_cast<const float(*)[3]>(mr.bm_vert_coords.data());
|
||||
vert_normals = reinterpret_cast<const float(*)[3]>(mr.bm_vert_normals.data());
|
||||
face_normals = reinterpret_cast<const float(*)[3]>(mr.bm_face_normals.data());
|
||||
|
@ -559,8 +558,8 @@ MeshRenderData *mesh_render_data_create(Object *object,
|
|||
mr->use_hide = use_hide;
|
||||
|
||||
if (is_editmode) {
|
||||
Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object);
|
||||
Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(object);
|
||||
const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object);
|
||||
const Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(object);
|
||||
|
||||
BLI_assert(editmesh_eval_cage && editmesh_eval_final);
|
||||
mr->bm = mesh->runtime->edit_mesh->bm;
|
||||
|
@ -573,15 +572,14 @@ MeshRenderData *mesh_render_data_create(Object *object,
|
|||
|
||||
if (mr->edit_data) {
|
||||
bke::EditMeshData *emd = mr->edit_data;
|
||||
if (!emd->vertexCos.is_empty()) {
|
||||
if (!emd->vert_positions.is_empty()) {
|
||||
BKE_editmesh_cache_ensure_vert_normals(*mr->edit_bmesh, *emd);
|
||||
BKE_editmesh_cache_ensure_face_normals(*mr->edit_bmesh, *emd);
|
||||
}
|
||||
|
||||
mr->bm_vert_coords = mr->edit_data->vertexCos;
|
||||
mr->bm_vert_normals = mr->edit_data->vertexNos;
|
||||
mr->bm_face_normals = mr->edit_data->faceNos;
|
||||
mr->bm_face_centers = mr->edit_data->faceCos;
|
||||
mr->bm_vert_coords = mr->edit_data->vert_positions;
|
||||
mr->bm_vert_normals = mr->edit_data->vert_normals;
|
||||
mr->bm_face_normals = mr->edit_data->face_normals;
|
||||
}
|
||||
|
||||
int bm_ensure_types = BM_VERT | BM_EDGE | BM_LOOP | BM_FACE;
|
||||
|
|
|
@ -1407,7 +1407,8 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
|
|||
/* Modifiers will only generate an orco layer if the mesh is deformed. */
|
||||
if (cache.cd_needed.orco != 0) {
|
||||
/* Orco is always extracted from final mesh. */
|
||||
Mesh *me_final = (mesh->runtime->edit_mesh) ? BKE_object_get_editmesh_eval_final(ob) : mesh;
|
||||
const Mesh *me_final = (mesh->runtime->edit_mesh) ? BKE_object_get_editmesh_eval_final(ob) :
|
||||
mesh;
|
||||
if (CustomData_get_layer(&me_final->vert_data, CD_ORCO) == nullptr) {
|
||||
/* Skip orco calculation */
|
||||
cache.cd_needed.orco = 0;
|
||||
|
@ -1512,8 +1513,8 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
|
|||
|
||||
bool do_cage = false, do_uvcage = false;
|
||||
if (is_editmode && is_mode_active) {
|
||||
Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob);
|
||||
Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob);
|
||||
const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob);
|
||||
const Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob);
|
||||
|
||||
do_cage = editmesh_eval_final != editmesh_eval_cage;
|
||||
do_uvcage = !(editmesh_eval_final->runtime->is_original_bmesh &&
|
||||
|
|
|
@ -750,7 +750,7 @@ static void draw_subdiv_cache_extra_coarse_face_data_bm(BMesh *bm,
|
|||
}
|
||||
|
||||
static void draw_subdiv_cache_extra_coarse_face_data_mesh(const MeshRenderData &mr,
|
||||
Mesh *mesh,
|
||||
const Mesh *mesh,
|
||||
uint32_t *flags_data)
|
||||
{
|
||||
const OffsetIndices faces = mesh->faces();
|
||||
|
@ -771,7 +771,7 @@ static void draw_subdiv_cache_extra_coarse_face_data_mesh(const MeshRenderData &
|
|||
}
|
||||
}
|
||||
|
||||
static void draw_subdiv_cache_extra_coarse_face_data_mapped(Mesh *mesh,
|
||||
static void draw_subdiv_cache_extra_coarse_face_data_mapped(const Mesh *mesh,
|
||||
BMesh *bm,
|
||||
MeshRenderData &mr,
|
||||
uint32_t *flags_data)
|
||||
|
@ -797,7 +797,7 @@ static void draw_subdiv_cache_extra_coarse_face_data_mapped(Mesh *mesh,
|
|||
}
|
||||
|
||||
static void draw_subdiv_cache_update_extra_coarse_face_data(DRWSubdivCache &cache,
|
||||
Mesh *mesh,
|
||||
const Mesh *mesh,
|
||||
MeshRenderData &mr)
|
||||
{
|
||||
if (cache.extra_coarse_face_data == nullptr) {
|
||||
|
@ -839,7 +839,7 @@ static DRWSubdivCache &mesh_batch_cache_ensure_subdiv_cache(MeshBatchCache &mbc)
|
|||
return *subdiv_cache;
|
||||
}
|
||||
|
||||
static void draw_subdiv_invalidate_evaluator_for_orco(Subdiv *subdiv, Mesh *mesh)
|
||||
static void draw_subdiv_invalidate_evaluator_for_orco(Subdiv *subdiv, const Mesh *mesh)
|
||||
{
|
||||
if (!(subdiv && subdiv->evaluator)) {
|
||||
return;
|
||||
|
@ -1167,7 +1167,7 @@ static void build_vertex_face_adjacency_maps(DRWSubdivCache &cache)
|
|||
|
||||
static bool draw_subdiv_build_cache(DRWSubdivCache &cache,
|
||||
Subdiv *subdiv,
|
||||
Mesh *mesh_eval,
|
||||
const Mesh *mesh_eval,
|
||||
const SubsurfRuntimeData *runtime_data)
|
||||
{
|
||||
SubdivToMeshSettings to_mesh_settings;
|
||||
|
@ -2020,7 +2020,7 @@ void draw_subdiv_build_edituv_stretch_angle_buffer(const DRWSubdivCache &cache,
|
|||
* since all sub-faces are contiguous, they all share the same offset.
|
||||
*/
|
||||
static void draw_subdiv_cache_ensure_mat_offsets(DRWSubdivCache &cache,
|
||||
Mesh *mesh_eval,
|
||||
const Mesh *mesh_eval,
|
||||
uint mat_len)
|
||||
{
|
||||
draw_subdiv_cache_free_material_data(cache);
|
||||
|
@ -2108,7 +2108,7 @@ static bool draw_subdiv_create_requested_buffers(Object *ob,
|
|||
return false;
|
||||
}
|
||||
|
||||
Mesh *mesh_eval = mesh;
|
||||
const Mesh *mesh_eval = mesh;
|
||||
BMesh *bm = nullptr;
|
||||
if (mesh->runtime->edit_mesh) {
|
||||
mesh_eval = BKE_object_get_editmesh_eval_final(ob);
|
||||
|
|
|
@ -46,6 +46,9 @@
|
|||
#include "draw_manager_text.hh"
|
||||
#include "intern/bmesh_polygon.hh"
|
||||
|
||||
using blender::float3;
|
||||
using blender::Span;
|
||||
|
||||
struct ViewCachedString {
|
||||
float vec[3];
|
||||
union {
|
||||
|
@ -255,7 +258,7 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
|
|||
*/
|
||||
DRWTextStore *dt = DRW_text_cache_ensure();
|
||||
const short txt_flag = DRW_TEXT_CACHE_GLOBALSPACE;
|
||||
Mesh *mesh = BKE_object_get_editmesh_eval_cage(ob);
|
||||
const Mesh *mesh = BKE_object_get_editmesh_eval_cage(ob);
|
||||
BMEditMesh *em = mesh->runtime->edit_mesh;
|
||||
float v1[3], v2[3], v3[3], vmid[3], fvec[3];
|
||||
char numstr[32]; /* Stores the measurement display text here */
|
||||
|
@ -269,8 +272,8 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
|
|||
float clip_planes[4][4];
|
||||
/* allow for displaying shape keys and deform mods */
|
||||
BMIter iter;
|
||||
const float(*vert_coords)[3] = BKE_mesh_wrapper_vert_coords(mesh);
|
||||
const bool use_coords = (vert_coords != nullptr);
|
||||
const Span<float3> vert_positions = BKE_mesh_wrapper_vert_coords(mesh);
|
||||
const bool use_coords = !vert_positions.is_empty();
|
||||
|
||||
/* when 2 or more edge-info options are enabled, space apart */
|
||||
short edge_tex_count = 0;
|
||||
|
@ -329,9 +332,9 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
|
|||
{
|
||||
float v1_clip[3], v2_clip[3];
|
||||
|
||||
if (vert_coords) {
|
||||
copy_v3_v3(v1, vert_coords[BM_elem_index_get(eed->v1)]);
|
||||
copy_v3_v3(v2, vert_coords[BM_elem_index_get(eed->v2)]);
|
||||
if (use_coords) {
|
||||
copy_v3_v3(v1, vert_positions[BM_elem_index_get(eed->v1)]);
|
||||
copy_v3_v3(v2, vert_positions[BM_elem_index_get(eed->v2)]);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(v1, eed->v1->co);
|
||||
|
@ -373,10 +376,12 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
|
|||
|
||||
UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGEANG, col);
|
||||
|
||||
const float(*face_normals)[3] = nullptr;
|
||||
Span<float3> face_normals;
|
||||
if (use_coords) {
|
||||
BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
|
||||
face_normals = BKE_mesh_wrapper_face_normals(mesh);
|
||||
/* TODO: This is not const correct for wrapper meshes, but it should be okay because
|
||||
* every evaluated object gets its own evaluated cage mesh (they are not shared). */
|
||||
face_normals = BKE_mesh_wrapper_face_normals(const_cast<Mesh *>(mesh));
|
||||
}
|
||||
|
||||
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
|
||||
|
@ -395,9 +400,9 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
|
|||
{
|
||||
float v1_clip[3], v2_clip[3];
|
||||
|
||||
if (vert_coords) {
|
||||
copy_v3_v3(v1, vert_coords[BM_elem_index_get(eed->v1)]);
|
||||
copy_v3_v3(v2, vert_coords[BM_elem_index_get(eed->v2)]);
|
||||
if (use_coords) {
|
||||
copy_v3_v3(v1, vert_positions[BM_elem_index_get(eed->v1)]);
|
||||
copy_v3_v3(v2, vert_positions[BM_elem_index_get(eed->v2)]);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(v1, eed->v1->co);
|
||||
|
@ -462,9 +467,9 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
|
|||
for (int j = 0; j < f_corner_tris_len; j++) {
|
||||
|
||||
if (use_coords) {
|
||||
copy_v3_v3(v1, vert_coords[BM_elem_index_get(ltri_array[j][0]->v)]);
|
||||
copy_v3_v3(v2, vert_coords[BM_elem_index_get(ltri_array[j][1]->v)]);
|
||||
copy_v3_v3(v3, vert_coords[BM_elem_index_get(ltri_array[j][2]->v)]);
|
||||
copy_v3_v3(v1, vert_positions[BM_elem_index_get(ltri_array[j][0]->v)]);
|
||||
copy_v3_v3(v2, vert_positions[BM_elem_index_get(ltri_array[j][1]->v)]);
|
||||
copy_v3_v3(v3, vert_positions[BM_elem_index_get(ltri_array[j][2]->v)]);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(v1, ltri_array[j][0]->v->co);
|
||||
|
@ -537,7 +542,7 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
|
|||
/* lazy init center calc */
|
||||
if (is_first) {
|
||||
if (use_coords) {
|
||||
BM_face_calc_center_bounds_vcos(em->bm, efa, vmid, vert_coords);
|
||||
BM_face_calc_center_bounds_vcos(em->bm, efa, vmid, vert_positions);
|
||||
}
|
||||
else {
|
||||
BM_face_calc_center_bounds(efa, vmid);
|
||||
|
@ -545,9 +550,9 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
|
|||
is_first = false;
|
||||
}
|
||||
if (use_coords) {
|
||||
copy_v3_v3(v1, vert_coords[BM_elem_index_get(loop->prev->v)]);
|
||||
copy_v3_v3(v2, vert_coords[BM_elem_index_get(loop->v)]);
|
||||
copy_v3_v3(v3, vert_coords[BM_elem_index_get(loop->next->v)]);
|
||||
copy_v3_v3(v1, vert_positions[BM_elem_index_get(loop->prev->v)]);
|
||||
copy_v3_v3(v2, vert_positions[BM_elem_index_get(loop->v)]);
|
||||
copy_v3_v3(v3, vert_positions[BM_elem_index_get(loop->next->v)]);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(v1, loop->prev->v->co);
|
||||
|
@ -595,7 +600,7 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
|
|||
BM_ITER_MESH_INDEX (v, &iter, em->bm, BM_VERTS_OF_MESH, i) {
|
||||
if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
|
||||
if (use_coords) {
|
||||
copy_v3_v3(v1, vert_coords[BM_elem_index_get(v)]);
|
||||
copy_v3_v3(v1, vert_positions[BM_elem_index_get(v)]);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(v1, v->co);
|
||||
|
@ -620,8 +625,8 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
|
|||
float v1_clip[3], v2_clip[3];
|
||||
|
||||
if (use_coords) {
|
||||
copy_v3_v3(v1, vert_coords[BM_elem_index_get(eed->v1)]);
|
||||
copy_v3_v3(v2, vert_coords[BM_elem_index_get(eed->v2)]);
|
||||
copy_v3_v3(v1, vert_positions[BM_elem_index_get(eed->v1)]);
|
||||
copy_v3_v3(v2, vert_positions[BM_elem_index_get(eed->v2)]);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(v1, eed->v1->co);
|
||||
|
@ -658,7 +663,7 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
|
|||
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
|
||||
|
||||
if (use_coords) {
|
||||
BM_face_calc_center_median_vcos(em->bm, f, v1, vert_coords);
|
||||
BM_face_calc_center_median_vcos(em->bm, f, v1, vert_positions);
|
||||
}
|
||||
else {
|
||||
BM_face_calc_center_median(f, v1);
|
||||
|
|
|
@ -101,7 +101,7 @@ struct DRWSubdivLooseGeom {
|
|||
* \{ */
|
||||
|
||||
struct DRWSubdivCache {
|
||||
Mesh *mesh;
|
||||
const Mesh *mesh;
|
||||
BMesh *bm;
|
||||
Subdiv *subdiv;
|
||||
bool optimal_display;
|
||||
|
|
|
@ -197,7 +197,7 @@ static DRWShadingGroup *drw_volume_object_mesh_init(Scene *scene,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (fds->fluid && (fds->type == FLUID_DOMAIN_TYPE_GAS)) {
|
||||
if (fds->type == FLUID_DOMAIN_TYPE_GAS) {
|
||||
DRW_smoke_ensure(fmd, fds->flags & FLUID_DOMAIN_USE_NOISE);
|
||||
}
|
||||
|
||||
|
@ -384,7 +384,7 @@ PassType *drw_volume_object_mesh_init(PassType &ps,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (fds->fluid && (fds->type == FLUID_DOMAIN_TYPE_GAS)) {
|
||||
if (fds->type == FLUID_DOMAIN_TYPE_GAS) {
|
||||
DRW_smoke_ensure(fmd, fds->flags & FLUID_DOMAIN_USE_NOISE);
|
||||
}
|
||||
|
||||
|
|
|
@ -80,7 +80,6 @@ struct MeshRenderData {
|
|||
Span<float3> bm_vert_coords;
|
||||
Span<float3> bm_vert_normals;
|
||||
Span<float3> bm_face_normals;
|
||||
Span<float3> bm_face_centers;
|
||||
Array<float3> bm_loop_normals;
|
||||
|
||||
const int *v_origindex, *e_origindex, *p_origindex;
|
||||
|
@ -90,7 +89,7 @@ struct MeshRenderData {
|
|||
int freestyle_edge_ofs;
|
||||
int freestyle_face_ofs;
|
||||
/** Mesh */
|
||||
Mesh *mesh;
|
||||
const Mesh *mesh;
|
||||
Span<float3> vert_positions;
|
||||
Span<int2> edges;
|
||||
OffsetIndices<int> faces;
|
||||
|
|
|
@ -268,7 +268,7 @@ static void extract_attr_init_subdiv(const DRWSubdivCache &subdiv_cache,
|
|||
const DRW_Attributes *attrs_used = &cache.attr_used;
|
||||
const DRW_AttributeRequest &request = attrs_used->requests[index];
|
||||
|
||||
Mesh *coarse_mesh = subdiv_cache.mesh;
|
||||
const Mesh *coarse_mesh = subdiv_cache.mesh;
|
||||
|
||||
/* Prepare VBO for coarse data. The compute shader only expects floats. */
|
||||
gpu::VertBuf *src_data = GPU_vertbuf_calloc();
|
||||
|
|
|
@ -253,8 +253,8 @@ static void extract_edituv_stretch_angle_init_subdiv(const DRWSubdivCache &subdi
|
|||
|
||||
/* UVs are stored contiguously so we need to compute the offset in the UVs buffer for the active
|
||||
* UV layer. */
|
||||
CustomData *cd_ldata = (mr.extract_type == MR_EXTRACT_MESH) ? &mr.mesh->corner_data :
|
||||
&mr.bm->ldata;
|
||||
const CustomData *cd_ldata = (mr.extract_type == MR_EXTRACT_MESH) ? &mr.mesh->corner_data :
|
||||
&mr.bm->ldata;
|
||||
|
||||
uint32_t uv_layers = cache.cd_used.uv;
|
||||
/* HACK to fix #68857 */
|
||||
|
|
|
@ -37,7 +37,7 @@ static void extract_orco_init(const MeshRenderData &mr,
|
|||
GPU_vertbuf_init_with_format(vbo, &format);
|
||||
GPU_vertbuf_data_alloc(vbo, mr.corners_num);
|
||||
|
||||
CustomData *cd_vdata = &mr.mesh->vert_data;
|
||||
const CustomData *cd_vdata = &mr.mesh->vert_data;
|
||||
|
||||
MeshExtract_Orco_Data *data = static_cast<MeshExtract_Orco_Data *>(tls_data);
|
||||
data->vbo_data = (float(*)[4])GPU_vertbuf_get_data(vbo);
|
||||
|
|
|
@ -48,14 +48,20 @@ static void extract_pos_init(const MeshRenderData &mr,
|
|||
MutableSpan vbo_data(static_cast<float3 *>(GPU_vertbuf_get_data(vbo)),
|
||||
GPU_vertbuf_get_vertex_len(vbo));
|
||||
if (mr.extract_type == MR_EXTRACT_MESH) {
|
||||
array_utils::gather(
|
||||
mr.vert_positions, mr.corner_verts, vbo_data.take_front(mr.corner_verts.size()));
|
||||
extract_mesh_loose_edge_positions(mr.vert_positions,
|
||||
mr.edges,
|
||||
mr.loose_edges,
|
||||
vbo_data.slice(mr.corners_num, mr.loose_edges.size() * 2));
|
||||
array_utils::gather(
|
||||
mr.vert_positions, mr.loose_verts, vbo_data.take_back(mr.loose_verts.size()));
|
||||
threading::memory_bandwidth_bound_task(
|
||||
mr.vert_positions.size_in_bytes() + mr.corner_verts.size_in_bytes() +
|
||||
vbo_data.size_in_bytes() + mr.loose_edges.size(),
|
||||
[&]() {
|
||||
array_utils::gather(
|
||||
mr.vert_positions, mr.corner_verts, vbo_data.take_front(mr.corner_verts.size()));
|
||||
extract_mesh_loose_edge_positions(
|
||||
mr.vert_positions,
|
||||
mr.edges,
|
||||
mr.loose_edges,
|
||||
vbo_data.slice(mr.corners_num, mr.loose_edges.size() * 2));
|
||||
array_utils::gather(
|
||||
mr.vert_positions, mr.loose_verts, vbo_data.take_back(mr.loose_verts.size()));
|
||||
});
|
||||
}
|
||||
else {
|
||||
*static_cast<float3 **>(tls_data) = vbo_data.data();
|
||||
|
|
|
@ -117,7 +117,7 @@ static void extract_sculpt_data_init_subdiv(const DRWSubdivCache &subdiv_cache,
|
|||
{
|
||||
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buffer);
|
||||
|
||||
Mesh *coarse_mesh = mr.mesh;
|
||||
const Mesh *coarse_mesh = mr.mesh;
|
||||
|
||||
/* First, interpolate mask if available. */
|
||||
gpu::VertBuf *mask_vbo = nullptr;
|
||||
|
|
|
@ -38,10 +38,10 @@ static void extract_tan_init_common(const MeshRenderData &mr,
|
|||
{
|
||||
GPU_vertformat_deinterleave(format);
|
||||
|
||||
CustomData *cd_ldata = (mr.extract_type == MR_EXTRACT_BMESH) ? &mr.bm->ldata :
|
||||
&mr.mesh->corner_data;
|
||||
CustomData *cd_vdata = (mr.extract_type == MR_EXTRACT_BMESH) ? &mr.bm->vdata :
|
||||
&mr.mesh->vert_data;
|
||||
const CustomData *cd_ldata = (mr.extract_type == MR_EXTRACT_BMESH) ? &mr.bm->ldata :
|
||||
&mr.mesh->corner_data;
|
||||
const CustomData *cd_vdata = (mr.extract_type == MR_EXTRACT_BMESH) ? &mr.bm->vdata :
|
||||
&mr.mesh->vert_data;
|
||||
uint32_t tan_layers = cache.cd_used.tan;
|
||||
const float(*orco)[3] = (const float(*)[3])CustomData_get_layer(cd_vdata, CD_ORCO);
|
||||
float(*orco_allocated)[3] = nullptr;
|
||||
|
@ -96,7 +96,9 @@ static void extract_tan_init_common(const MeshRenderData &mr,
|
|||
copy_v3_v3(orco_allocated[v], mr.vert_positions[v]);
|
||||
}
|
||||
}
|
||||
BKE_mesh_orco_verts_transform(mr.mesh, orco_allocated, mr.verts_num, false);
|
||||
/* TODO: This is not thread-safe. Draw extraction should not modify the mesh. */
|
||||
BKE_mesh_orco_verts_transform(
|
||||
const_cast<Mesh *>(mr.mesh), orco_allocated, mr.verts_num, false);
|
||||
orco = orco_allocated;
|
||||
}
|
||||
|
||||
|
@ -118,6 +120,7 @@ static void extract_tan_init_common(const MeshRenderData &mr,
|
|||
&tangent_mask);
|
||||
}
|
||||
else {
|
||||
/* TODO: This is not thread-safe. Draw extraction should not modify the mesh. */
|
||||
BKE_mesh_calc_loop_tangent_ex(reinterpret_cast<const float(*)[3]>(mr.vert_positions.data()),
|
||||
mr.faces,
|
||||
mr.corner_verts.data(),
|
||||
|
|
|
@ -22,9 +22,9 @@ namespace blender::draw {
|
|||
/* Initialize the vertex format to be used for UVs. Return true if any UV layer is
|
||||
* found, false otherwise. */
|
||||
static bool mesh_extract_uv_format_init(GPUVertFormat *format,
|
||||
MeshBatchCache &cache,
|
||||
CustomData *cd_ldata,
|
||||
eMRExtractType extract_type,
|
||||
const MeshBatchCache &cache,
|
||||
const CustomData *cd_ldata,
|
||||
const eMRExtractType extract_type,
|
||||
uint32_t &r_uv_layers)
|
||||
{
|
||||
GPU_vertformat_deinterleave(format);
|
||||
|
@ -89,8 +89,8 @@ static void extract_uv_init(const MeshRenderData &mr,
|
|||
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buf);
|
||||
GPUVertFormat format = {0};
|
||||
|
||||
CustomData *cd_ldata = (mr.extract_type == MR_EXTRACT_BMESH) ? &mr.bm->ldata :
|
||||
&mr.mesh->corner_data;
|
||||
const CustomData *cd_ldata = (mr.extract_type == MR_EXTRACT_BMESH) ? &mr.bm->ldata :
|
||||
&mr.mesh->corner_data;
|
||||
int v_len = mr.corners_num;
|
||||
uint32_t uv_layers = cache.cd_used.uv;
|
||||
if (!mesh_extract_uv_format_init(&format, cache, cd_ldata, mr.extract_type, uv_layers)) {
|
||||
|
@ -136,7 +136,7 @@ static void extract_uv_init_subdiv(const DRWSubdivCache &subdiv_cache,
|
|||
void *buffer,
|
||||
void * /*data*/)
|
||||
{
|
||||
Mesh *coarse_mesh = subdiv_cache.mesh;
|
||||
const Mesh *coarse_mesh = subdiv_cache.mesh;
|
||||
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buffer);
|
||||
GPUVertFormat format = {0};
|
||||
|
||||
|
|
|
@ -159,7 +159,7 @@ static void extract_weights_init_subdiv(const DRWSubdivCache &subdiv_cache,
|
|||
void *buffer,
|
||||
void *_data)
|
||||
{
|
||||
Mesh *coarse_mesh = subdiv_cache.mesh;
|
||||
const Mesh *coarse_mesh = subdiv_cache.mesh;
|
||||
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buffer);
|
||||
|
||||
static GPUVertFormat format = {0};
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "BKE_node.hh"
|
||||
#include "BKE_object.hh"
|
||||
|
||||
#include "DEG_depsgraph.hh"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
#include "RNA_define.hh"
|
||||
|
||||
|
@ -1164,6 +1164,375 @@ static void test_eevee_shadow_finalize()
|
|||
}
|
||||
DRAW_TEST(eevee_shadow_finalize)
|
||||
|
||||
static void test_eevee_shadow_tile_packing()
|
||||
{
|
||||
Vector<uint> test_values{0x00000000u, 0x00000001u, 0x0000000Fu, 0x000000FFu, 0xABCDEF01u,
|
||||
0xAAAAAAAAu, 0xBBBBBBBBu, 0xCCCCCCCCu, 0xDDDDDDDDu, 0xEEEEEEEEu,
|
||||
0xFFFFFFFFu, 0xDEADBEEFu, 0x8BADF00Du, 0xABADCAFEu, 0x0D15EA5Eu,
|
||||
0xFEE1DEADu, 0xDEADC0DEu, 0xC00010FFu, 0xBBADBEEFu, 0xBAAAAAADu};
|
||||
|
||||
for (auto value : test_values) {
|
||||
EXPECT_EQ(shadow_page_unpack(value),
|
||||
shadow_page_unpack(shadow_page_pack(shadow_page_unpack(value))));
|
||||
|
||||
EXPECT_EQ(shadow_lod_offset_unpack(value),
|
||||
shadow_lod_offset_unpack(shadow_lod_offset_pack(shadow_lod_offset_unpack(value))));
|
||||
|
||||
ShadowTileData expected_tile = shadow_tile_unpack(value);
|
||||
ShadowTileData result_tile = shadow_tile_unpack(shadow_tile_pack(expected_tile));
|
||||
EXPECT_EQ(expected_tile.page, result_tile.page);
|
||||
EXPECT_EQ(expected_tile.cache_index, result_tile.cache_index);
|
||||
EXPECT_EQ(expected_tile.is_used, result_tile.is_used);
|
||||
EXPECT_EQ(expected_tile.do_update, result_tile.do_update);
|
||||
EXPECT_EQ(expected_tile.is_allocated, result_tile.is_allocated);
|
||||
EXPECT_EQ(expected_tile.is_rendered, result_tile.is_rendered);
|
||||
EXPECT_EQ(expected_tile.is_cached, result_tile.is_cached);
|
||||
|
||||
ShadowSamplingTile expected_sampling_tile = shadow_sampling_tile_unpack(value);
|
||||
ShadowSamplingTile result_sampling_tile = shadow_sampling_tile_unpack(
|
||||
shadow_sampling_tile_pack(expected_sampling_tile));
|
||||
EXPECT_EQ(expected_sampling_tile.page, result_sampling_tile.page);
|
||||
EXPECT_EQ(expected_sampling_tile.lod, result_sampling_tile.lod);
|
||||
EXPECT_EQ(expected_sampling_tile.lod_offset, result_sampling_tile.lod_offset);
|
||||
EXPECT_EQ(expected_sampling_tile.is_valid, result_sampling_tile.is_valid);
|
||||
}
|
||||
}
|
||||
DRAW_TEST(eevee_shadow_tile_packing)
|
||||
|
||||
static void test_eevee_shadow_tilemap_amend()
|
||||
{
|
||||
GPU_render_begin();
|
||||
|
||||
blender::Vector<uint32_t> tilemap_data(SHADOW_TILEMAP_RES * SHADOW_TILEMAP_RES *
|
||||
SHADOW_TILEMAP_PER_ROW);
|
||||
tilemap_data.fill(0);
|
||||
|
||||
auto pixel_get = [&](int x, int y, int tilemap_index) -> uint32_t & {
|
||||
/* Note: assumes that tilemap_index is < SHADOW_TILEMAP_PER_ROW. */
|
||||
return tilemap_data[y * SHADOW_TILEMAP_RES * SHADOW_TILEMAP_PER_ROW + x +
|
||||
tilemap_index * SHADOW_TILEMAP_RES];
|
||||
};
|
||||
ShadowSamplingTile tile;
|
||||
tile.lod = 0;
|
||||
tile.lod_offset = uint2(0);
|
||||
tile.is_valid = true;
|
||||
tile.page = uint3(1, 0, 0);
|
||||
pixel_get(16, 16, 2) = shadow_sampling_tile_pack(tile);
|
||||
tile.page = uint3(2, 0, 0);
|
||||
pixel_get(17, 16, 2) = shadow_sampling_tile_pack(tile);
|
||||
tile.page = uint3(3, 0, 0);
|
||||
pixel_get(20, 20, 1) = shadow_sampling_tile_pack(tile);
|
||||
tile.page = uint3(4, 0, 0);
|
||||
pixel_get(17, 16, 0) = shadow_sampling_tile_pack(tile);
|
||||
|
||||
Texture tilemap_tx = {"tilemap_tx"};
|
||||
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_HOST_READ | GPU_TEXTURE_USAGE_SHADER_READ |
|
||||
GPU_TEXTURE_USAGE_SHADER_WRITE;
|
||||
int2 tilemap_res(SHADOW_TILEMAP_RES * SHADOW_TILEMAP_PER_ROW, SHADOW_TILEMAP_RES);
|
||||
tilemap_tx.ensure_2d(GPU_R32UI, tilemap_res, usage);
|
||||
GPU_texture_update_sub(
|
||||
tilemap_tx, GPU_DATA_UINT, tilemap_data.data(), 0, 0, 0, tilemap_res.x, tilemap_res.y, 0);
|
||||
|
||||
/* Setup one directional light with 3 tilemaps. Fill only the needed data. */
|
||||
LightData light;
|
||||
light.type = LIGHT_SUN;
|
||||
light.sun.clipmap_lod_min = 0;
|
||||
light.sun.clipmap_lod_max = 2;
|
||||
/* Shift LOD0 by 1 tile towards bottom. */
|
||||
light.sun.clipmap_base_offset_neg = int2(0, 1 << 0);
|
||||
/* Shift LOD1 by 1 tile towards right. */
|
||||
light.sun.clipmap_base_offset_pos = int2(1 << 1, 0);
|
||||
light.tilemap_index = 0;
|
||||
|
||||
LightDataBuf culling_light_buf = {"Lights_culled"};
|
||||
culling_light_buf[0] = light;
|
||||
culling_light_buf.push_update();
|
||||
|
||||
LightCullingDataBuf culling_data_buf = {"LightCull_data"};
|
||||
culling_data_buf.local_lights_len = 0;
|
||||
culling_data_buf.sun_lights_len = 1;
|
||||
culling_data_buf.items_count = 1;
|
||||
culling_data_buf.push_update();
|
||||
|
||||
/* Needed for validation. But not used since we use directionals. */
|
||||
LightCullingZbinBuf culling_zbin_buf = {"LightCull_zbin"};
|
||||
LightCullingTileBuf culling_tile_buf = {"LightCull_tile"};
|
||||
|
||||
GPUShader *sh = GPU_shader_create_from_info_name("eevee_shadow_tilemap_amend");
|
||||
|
||||
PassSimple pass("Test");
|
||||
pass.shader_set(sh);
|
||||
pass.bind_image("tilemaps_img", tilemap_tx);
|
||||
pass.bind_ssbo(LIGHT_CULL_BUF_SLOT, culling_data_buf);
|
||||
pass.bind_ssbo(LIGHT_BUF_SLOT, culling_light_buf);
|
||||
pass.bind_ssbo(LIGHT_ZBIN_BUF_SLOT, culling_zbin_buf);
|
||||
pass.bind_ssbo(LIGHT_TILE_BUF_SLOT, culling_tile_buf);
|
||||
pass.dispatch(int3(1));
|
||||
pass.barrier(GPU_BARRIER_TEXTURE_UPDATE);
|
||||
|
||||
Manager manager;
|
||||
manager.submit(pass);
|
||||
|
||||
{
|
||||
uint *pixels = tilemap_tx.read<uint32_t>(GPU_DATA_UINT);
|
||||
|
||||
auto stringify_tilemap = [&](int tilemap_index) -> std::string {
|
||||
std::string result = "";
|
||||
for (auto y : IndexRange(SHADOW_TILEMAP_RES)) {
|
||||
for (auto x : IndexRange(SHADOW_TILEMAP_RES)) {
|
||||
/* Note: assumes that tilemap_index is < SHADOW_TILEMAP_PER_ROW. */
|
||||
int tile_ofs = y * SHADOW_TILEMAP_RES * SHADOW_TILEMAP_PER_ROW + x +
|
||||
tilemap_index * SHADOW_TILEMAP_RES;
|
||||
ShadowSamplingTile tile = shadow_sampling_tile_unpack(pixels[tile_ofs]);
|
||||
result += std::to_string(tile.page.x + tile.page.y * SHADOW_PAGE_PER_ROW);
|
||||
if (x + 1 == SHADOW_TILEMAP_RES / 2) {
|
||||
result += " ";
|
||||
}
|
||||
}
|
||||
result += "\n";
|
||||
if (y + 1 == SHADOW_TILEMAP_RES / 2) {
|
||||
result += "\n";
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
auto stringify_lod = [&](int tilemap_index) -> std::string {
|
||||
std::string result = "";
|
||||
for (auto y : IndexRange(SHADOW_TILEMAP_RES)) {
|
||||
for (auto x : IndexRange(SHADOW_TILEMAP_RES)) {
|
||||
/* Note: assumes that tilemap_index is < SHADOW_TILEMAP_PER_ROW. */
|
||||
int tile_ofs = y * SHADOW_TILEMAP_RES * SHADOW_TILEMAP_PER_ROW + x +
|
||||
tilemap_index * SHADOW_TILEMAP_RES;
|
||||
ShadowSamplingTile tile = shadow_sampling_tile_unpack(pixels[tile_ofs]);
|
||||
result += std::to_string(tile.lod);
|
||||
if (x + 1 == SHADOW_TILEMAP_RES / 2) {
|
||||
result += " ";
|
||||
}
|
||||
}
|
||||
result += "\n";
|
||||
if (y + 1 == SHADOW_TILEMAP_RES / 2) {
|
||||
result += "\n";
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
auto stringify_offset = [&](int tilemap_index) -> std::string {
|
||||
std::string result = "";
|
||||
for (auto y : IndexRange(SHADOW_TILEMAP_RES)) {
|
||||
for (auto x : IndexRange(SHADOW_TILEMAP_RES)) {
|
||||
/* Note: assumes that tilemap_index is < SHADOW_TILEMAP_PER_ROW. */
|
||||
int tile_ofs = y * SHADOW_TILEMAP_RES * SHADOW_TILEMAP_PER_ROW + x +
|
||||
tilemap_index * SHADOW_TILEMAP_RES;
|
||||
ShadowSamplingTile tile = shadow_sampling_tile_unpack(pixels[tile_ofs]);
|
||||
result += std::to_string(tile.lod_offset.x + tile.lod_offset.y);
|
||||
if (x + 1 == SHADOW_TILEMAP_RES / 2) {
|
||||
result += " ";
|
||||
}
|
||||
}
|
||||
result += "\n";
|
||||
if (y + 1 == SHADOW_TILEMAP_RES / 2) {
|
||||
result += "\n";
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/** The layout of these expected strings is Y down. */
|
||||
|
||||
StringRefNull expected_pages_lod2 =
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"\n"
|
||||
"0000000000000000 1200000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n";
|
||||
|
||||
StringRefNull expected_pages_lod1 =
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"\n"
|
||||
"0000000000000001 1220000000000000\n"
|
||||
"0000000000000001 1220000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000300000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n";
|
||||
|
||||
StringRefNull expected_pages_lod0 =
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"\n"
|
||||
"0000000000000000 0400000000000000\n"
|
||||
"0000000000000011 1122220000000000\n"
|
||||
"0000000000000011 1122220000000000\n"
|
||||
"0000000000000011 1122220000000000\n"
|
||||
"0000000000000011 1122220000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000033000000\n"
|
||||
"0000000000000000 0000000033000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n";
|
||||
|
||||
EXPECT_EQ(expected_pages_lod2, stringify_tilemap(2));
|
||||
EXPECT_EQ(expected_pages_lod1, stringify_tilemap(1));
|
||||
EXPECT_EQ(expected_pages_lod0, stringify_tilemap(0));
|
||||
|
||||
StringRefNull expected_lod_lod0 =
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000022 2222220000000000\n"
|
||||
"0000000000000022 2222220000000000\n"
|
||||
"0000000000000022 2222220000000000\n"
|
||||
"0000000000000022 2222220000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000011000000\n"
|
||||
"0000000000000000 0000000011000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n";
|
||||
|
||||
EXPECT_EQ(expected_lod_lod0, stringify_lod(0));
|
||||
|
||||
/* Offset for each axis are added together in this test. */
|
||||
StringRefNull expected_offset_lod0 =
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000055 5555550000000000\n"
|
||||
"0000000000000055 5555550000000000\n"
|
||||
"0000000000000055 5555550000000000\n"
|
||||
"0000000000000055 5555550000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000011000000\n"
|
||||
"0000000000000000 0000000011000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n"
|
||||
"0000000000000000 0000000000000000\n";
|
||||
|
||||
EXPECT_EQ(expected_offset_lod0, stringify_offset(0));
|
||||
MEM_SAFE_FREE(pixels);
|
||||
}
|
||||
|
||||
GPU_shader_free(sh);
|
||||
DRW_shaders_free();
|
||||
GPU_render_end();
|
||||
}
|
||||
DRAW_TEST(eevee_shadow_tilemap_amend)
|
||||
|
||||
static void test_eevee_shadow_page_mask_ex(int max_view_per_tilemap)
|
||||
{
|
||||
GPU_render_begin();
|
||||
|
|
|
@ -390,46 +390,44 @@ static void updateDuplicateSubtarget(EditBone *dup_bone,
|
|||
*/
|
||||
EditBone *oldtarget, *newtarget;
|
||||
bPoseChannel *pchan;
|
||||
ListBase *conlist;
|
||||
|
||||
if ((pchan = BKE_pose_channel_ensure(ob->pose, dup_bone->name))) {
|
||||
if ((conlist = &pchan->constraints)) {
|
||||
LISTBASE_FOREACH (bConstraint *, curcon, conlist) {
|
||||
/* does this constraint have a subtarget in
|
||||
* this armature?
|
||||
*/
|
||||
ListBase targets = {nullptr, nullptr};
|
||||
ListBase *conlist = &pchan->constraints;
|
||||
LISTBASE_FOREACH (bConstraint *, curcon, conlist) {
|
||||
/* does this constraint have a subtarget in
|
||||
* this armature?
|
||||
*/
|
||||
ListBase targets = {nullptr, nullptr};
|
||||
|
||||
if (BKE_constraint_targets_get(curcon, &targets)) {
|
||||
LISTBASE_FOREACH (bConstraintTarget *, ct, &targets) {
|
||||
if ((ct->tar == ob) && (ct->subtarget[0])) {
|
||||
oldtarget = get_named_editbone(editbones, ct->subtarget);
|
||||
if (oldtarget) {
|
||||
/* was the subtarget bone duplicated too? If
|
||||
* so, update the constraint to point at the
|
||||
* duplicate of the old subtarget.
|
||||
*/
|
||||
if (oldtarget->temp.ebone) {
|
||||
newtarget = oldtarget->temp.ebone;
|
||||
if (BKE_constraint_targets_get(curcon, &targets)) {
|
||||
LISTBASE_FOREACH (bConstraintTarget *, ct, &targets) {
|
||||
if ((ct->tar == ob) && (ct->subtarget[0])) {
|
||||
oldtarget = get_named_editbone(editbones, ct->subtarget);
|
||||
if (oldtarget) {
|
||||
/* was the subtarget bone duplicated too? If
|
||||
* so, update the constraint to point at the
|
||||
* duplicate of the old subtarget.
|
||||
*/
|
||||
if (oldtarget->temp.ebone) {
|
||||
newtarget = oldtarget->temp.ebone;
|
||||
STRNCPY(ct->subtarget, newtarget->name);
|
||||
}
|
||||
else if (lookup_mirror_subtarget) {
|
||||
/* The subtarget was not selected for duplication, try to see if a mirror bone of
|
||||
* the current target exists */
|
||||
char name_flip[MAXBONENAME];
|
||||
|
||||
BLI_string_flip_side_name(name_flip, oldtarget->name, false, sizeof(name_flip));
|
||||
newtarget = get_named_editbone(editbones, name_flip);
|
||||
if (newtarget) {
|
||||
STRNCPY(ct->subtarget, newtarget->name);
|
||||
}
|
||||
else if (lookup_mirror_subtarget) {
|
||||
/* The subtarget was not selected for duplication, try to see if a mirror bone of
|
||||
* the current target exists */
|
||||
char name_flip[MAXBONENAME];
|
||||
|
||||
BLI_string_flip_side_name(name_flip, oldtarget->name, false, sizeof(name_flip));
|
||||
newtarget = get_named_editbone(editbones, name_flip);
|
||||
if (newtarget) {
|
||||
STRNCPY(ct->subtarget, newtarget->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BKE_constraint_targets_flush(curcon, &targets, false);
|
||||
}
|
||||
|
||||
BKE_constraint_targets_flush(curcon, &targets, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -774,20 +774,6 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int separate_armature_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
|
||||
{
|
||||
if (RNA_boolean_get(op->ptr, "confirm")) {
|
||||
return WM_operator_confirm_ex(C,
|
||||
op,
|
||||
IFACE_("Move selected bones to a separate armature?"),
|
||||
nullptr,
|
||||
IFACE_("Separate"),
|
||||
ALERT_ICON_NONE,
|
||||
false);
|
||||
}
|
||||
return separate_armature_exec(C, op);
|
||||
}
|
||||
|
||||
void ARMATURE_OT_separate(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
|
@ -796,13 +782,11 @@ void ARMATURE_OT_separate(wmOperatorType *ot)
|
|||
ot->description = "Isolate selected bones into a separate armature";
|
||||
|
||||
/* callbacks */
|
||||
ot->invoke = separate_armature_invoke;
|
||||
ot->exec = separate_armature_exec;
|
||||
ot->poll = ED_operator_editarmature;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
WM_operator_properties_confirm_or_exec(ot);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue