Fix #105435: Pause Win32 Auto-Focus During Text Entry #105446
|
@ -1865,7 +1865,7 @@ def pyrna2sphinx(basepath):
|
|||
else:
|
||||
url_base = API_BASEURL
|
||||
|
||||
fw(" :file: `%s\\:%d <%s/%s$%d>`_\n\n" %
|
||||
fw(" :file:`%s\\:%d <%s/%s#L%d>`_\n\n" %
|
||||
(location[0], location[1], url_base, location[0], location[1]))
|
||||
|
||||
file.close()
|
||||
|
|
|
@ -893,6 +893,23 @@ static std::optional<BL::IntAttribute> find_material_index_attribute(BL::Mesh b_
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
static std::optional<BL::BoolAttribute> find_sharp_face_attribute(BL::Mesh b_mesh)
|
||||
{
|
||||
for (BL::Attribute &b_attribute : b_mesh.attributes) {
|
||||
if (b_attribute.domain() != BL::Attribute::domain_FACE) {
|
||||
continue;
|
||||
}
|
||||
if (b_attribute.data_type() != BL::Attribute::data_type_BOOLEAN) {
|
||||
continue;
|
||||
}
|
||||
if (b_attribute.name() != "sharp_face") {
|
||||
continue;
|
||||
}
|
||||
return BL::BoolAttribute{b_attribute};
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
static void create_mesh(Scene *scene,
|
||||
Mesh *mesh,
|
||||
BL::Mesh &b_mesh,
|
||||
|
@ -983,16 +1000,22 @@ static void create_mesh(Scene *scene,
|
|||
return 0;
|
||||
};
|
||||
|
||||
std::optional<BL::BoolAttribute> sharp_faces = find_sharp_face_attribute(b_mesh);
|
||||
auto get_face_sharp = [&](const int poly_index) -> bool {
|
||||
if (sharp_faces) {
|
||||
return sharp_faces->data[poly_index].value();
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/* create faces */
|
||||
const MPoly *polys = static_cast<const MPoly *>(b_mesh.polygons[0].ptr.data);
|
||||
if (!subdivision) {
|
||||
for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) {
|
||||
const int poly_index = t.polygon_index();
|
||||
const MPoly &b_poly = polys[poly_index];
|
||||
int3 vi = get_int3(t.vertices());
|
||||
|
||||
int shader = get_material_index(poly_index);
|
||||
bool smooth = (b_poly.flag & ME_SMOOTH) || use_loop_normals;
|
||||
bool smooth = !get_face_sharp(poly_index) || use_loop_normals;
|
||||
|
||||
if (use_loop_normals) {
|
||||
BL::Array<float, 9> loop_normals = t.split_normals();
|
||||
|
@ -1012,13 +1035,14 @@ static void create_mesh(Scene *scene,
|
|||
else {
|
||||
vector<int> vi;
|
||||
|
||||
const MPoly *polys = static_cast<const MPoly *>(b_mesh.polygons[0].ptr.data);
|
||||
const MLoop *loops = static_cast<const MLoop *>(b_mesh.loops[0].ptr.data);
|
||||
|
||||
for (int i = 0; i < numfaces; i++) {
|
||||
const MPoly &b_poly = polys[i];
|
||||
int n = b_poly.totloop;
|
||||
int shader = get_material_index(i);
|
||||
bool smooth = (b_poly.flag & ME_SMOOTH) || use_loop_normals;
|
||||
bool smooth = !get_face_sharp(i) || use_loop_normals;
|
||||
|
||||
vi.resize(n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
|
|
|
@ -103,6 +103,9 @@ bool win32_chk(bool result, const char *file, int line, const char *text)
|
|||
_ftprintf(
|
||||
stderr, "%s:%d: [%s] -> Win32 Error# (%lu): %s", file, line, text, ulong(error), msg);
|
||||
# else
|
||||
(void)file;
|
||||
(void)line;
|
||||
(void)text;
|
||||
_ftprintf(stderr, "Win32 Error# (%lu): %s", ulong(error), msg);
|
||||
# endif
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ ULONG __stdcall GHOST_DropTargetWin32::Release(void)
|
|||
* Implementation of IDropTarget::DragEnter
|
||||
*/
|
||||
HRESULT __stdcall GHOST_DropTargetWin32::DragEnter(IDataObject *p_data_object,
|
||||
DWORD grf_key_state,
|
||||
DWORD /*grf_key_state*/,
|
||||
POINTL pt,
|
||||
DWORD *pdw_effect)
|
||||
{
|
||||
|
@ -95,7 +95,7 @@ HRESULT __stdcall GHOST_DropTargetWin32::DragEnter(IDataObject *p_data_object,
|
|||
/*
|
||||
* Implementation of IDropTarget::DragOver
|
||||
*/
|
||||
HRESULT __stdcall GHOST_DropTargetWin32::DragOver(DWORD grf_key_state,
|
||||
HRESULT __stdcall GHOST_DropTargetWin32::DragOver(DWORD /*grf_key_state*/,
|
||||
POINTL pt,
|
||||
DWORD *pdw_effect)
|
||||
{
|
||||
|
@ -128,7 +128,7 @@ HRESULT __stdcall GHOST_DropTargetWin32::DragLeave(void)
|
|||
* the implementation of IDropTarget::DragOver
|
||||
*/
|
||||
HRESULT __stdcall GHOST_DropTargetWin32::Drop(IDataObject *p_data_object,
|
||||
DWORD grf_key_state,
|
||||
DWORD /*grf_key_state*/,
|
||||
POINTL pt,
|
||||
DWORD *pdw_effect)
|
||||
{
|
||||
|
|
|
@ -140,7 +140,7 @@ void GHOST_ImeWin32::SetImeWindowStyle(
|
|||
::DefWindowProc(window_handle, message, wparam, lparam);
|
||||
}
|
||||
|
||||
void GHOST_ImeWin32::DestroyImeWindow(HWND window_handle)
|
||||
void GHOST_ImeWin32::DestroyImeWindow(HWND /*window_handle*/)
|
||||
{
|
||||
/* Destroy the system caret if we have created for this IME input context. */
|
||||
if (system_caret_) {
|
||||
|
@ -149,7 +149,7 @@ void GHOST_ImeWin32::DestroyImeWindow(HWND window_handle)
|
|||
}
|
||||
}
|
||||
|
||||
void GHOST_ImeWin32::MoveImeWindow(HWND window_handle, HIMC imm_context)
|
||||
void GHOST_ImeWin32::MoveImeWindow(HWND /*window_handle*/, HIMC imm_context)
|
||||
{
|
||||
int x = caret_rect_.m_l;
|
||||
int y = caret_rect_.m_t;
|
||||
|
@ -228,7 +228,7 @@ void GHOST_ImeWin32::CheckFirst(HWND window_handle)
|
|||
}
|
||||
}
|
||||
|
||||
void GHOST_ImeWin32::ResetComposition(HWND window_handle)
|
||||
void GHOST_ImeWin32::ResetComposition(HWND /*window_handle*/)
|
||||
{
|
||||
/* Currently, just reset the composition status. */
|
||||
is_composing_ = false;
|
||||
|
|
|
@ -217,7 +217,7 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
|
|||
uint32_t height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_GLSettings glSettings,
|
||||
const bool exclusive,
|
||||
const bool /*exclusive*/,
|
||||
const bool is_dialog,
|
||||
const GHOST_IWindow *parentWindow)
|
||||
{
|
||||
|
@ -568,7 +568,7 @@ GHOST_TKey GHOST_SystemWin32::hardKey(RAWINPUT const &raw, bool *r_key_down)
|
|||
* This function was added in response to bug #25715.
|
||||
* This is going to be a long list #42426.
|
||||
*/
|
||||
GHOST_TKey GHOST_SystemWin32::processSpecialKey(short vKey, short scanCode) const
|
||||
GHOST_TKey GHOST_SystemWin32::processSpecialKey(short vKey, short /*scanCode*/) const
|
||||
{
|
||||
GHOST_TKey key = GHOST_kKeyUnknown;
|
||||
if (vKey == 0xFF) {
|
||||
|
@ -1148,7 +1148,9 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
|
|||
GHOST_TABLET_DATA_NONE);
|
||||
}
|
||||
|
||||
void GHOST_SystemWin32::processWheelEvent(GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam)
|
||||
void GHOST_SystemWin32::processWheelEvent(GHOST_WindowWin32 *window,
|
||||
WPARAM wParam,
|
||||
LPARAM /*lParam*/)
|
||||
{
|
||||
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
|
||||
|
||||
|
@ -2216,7 +2218,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, uint msg, WPARAM wParam,
|
|||
return lResult;
|
||||
}
|
||||
|
||||
char *GHOST_SystemWin32::getClipboard(bool selection) const
|
||||
char *GHOST_SystemWin32::getClipboard(bool /*selection*/) const
|
||||
{
|
||||
if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL)) {
|
||||
wchar_t *buffer;
|
||||
|
|
|
@ -265,14 +265,14 @@ HRESULT GHOST_DirectManipulationViewportEventHandler::OnViewportStatusChanged(
|
|||
}
|
||||
|
||||
HRESULT GHOST_DirectManipulationViewportEventHandler::OnViewportUpdated(
|
||||
IDirectManipulationViewport *viewport)
|
||||
IDirectManipulationViewport * /*viewport*/)
|
||||
{
|
||||
/* Nothing to do here. */
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT GHOST_DirectManipulationViewportEventHandler::OnContentUpdated(
|
||||
IDirectManipulationViewport *viewport, IDirectManipulationContent *content)
|
||||
IDirectManipulationViewport * /*viewport*/, IDirectManipulationContent *content)
|
||||
{
|
||||
float transform[6];
|
||||
HRESULT hr = content->GetContentTransform(transform, ARRAYSIZE(transform));
|
||||
|
|
|
@ -898,7 +898,7 @@ GHOST_TSuccess GHOST_WindowWin32::hasCursorShape(GHOST_TStandardCursor cursorSha
|
|||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::getPointerInfo(
|
||||
std::vector<GHOST_PointerInfoWin32> &outPointerInfo, WPARAM wParam, LPARAM lParam)
|
||||
std::vector<GHOST_PointerInfoWin32> &outPointerInfo, WPARAM wParam, LPARAM /*lParam*/)
|
||||
{
|
||||
int32_t pointerId = GET_POINTERID_WPARAM(wParam);
|
||||
int32_t isPrimary = IS_POINTER_PRIMARY_WPARAM(wParam);
|
||||
|
@ -1109,8 +1109,13 @@ static uint16_t uns16ReverseBits(uint16_t shrt)
|
|||
}
|
||||
#endif
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(
|
||||
uint8_t *bitmap, uint8_t *mask, int sizeX, int sizeY, int hotX, int hotY, bool canInvertColor)
|
||||
GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(uint8_t *bitmap,
|
||||
uint8_t *mask,
|
||||
int sizeX,
|
||||
int sizeY,
|
||||
int hotX,
|
||||
int hotY,
|
||||
bool /*canInvertColor*/)
|
||||
{
|
||||
uint32_t andData[32];
|
||||
uint32_t xorData[32];
|
||||
|
@ -1175,7 +1180,7 @@ GHOST_TSuccess GHOST_WindowWin32::endProgressBar()
|
|||
}
|
||||
|
||||
#ifdef WITH_INPUT_IME
|
||||
void GHOST_WindowWin32::beginIME(int32_t x, int32_t y, int32_t w, int32_t h, bool completed)
|
||||
void GHOST_WindowWin32::beginIME(int32_t x, int32_t y, int32_t /*w*/, int32_t h, bool completed)
|
||||
{
|
||||
m_imeInput.BeginIME(m_hWnd, GHOST_Rect(x, y - h, x, y), completed);
|
||||
}
|
||||
|
|
|
@ -226,4 +226,5 @@ _km_hierarchy = [
|
|||
('Transform Modal Map', 'EMPTY', 'WINDOW', []),
|
||||
('Eyedropper Modal Map', 'EMPTY', 'WINDOW', []),
|
||||
('Eyedropper ColorRamp PointSampling Map', 'EMPTY', 'WINDOW', []),
|
||||
('Mesh Filter Modal Map', 'EMPTY', 'WINDOW', []),
|
||||
]
|
||||
|
|
|
@ -6318,6 +6318,25 @@ def km_sculpt_expand_modal(_params):
|
|||
])
|
||||
return keymap
|
||||
|
||||
def km_sculpt_mesh_filter_modal_map(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Mesh Filter Modal Map",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW', "modal": True},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("CONFIRM", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
|
||||
("CONFIRM", {"type": 'LEFTMOUSE', "value": 'RELEASE', "any": True}, None),
|
||||
("CONFIRM", {"type": 'RET', "value": 'RELEASE', "any": True}, None),
|
||||
("CONFIRM", {"type": 'NUMPAD_ENTER', "value": 'RELEASE', "any": True}, None),
|
||||
|
||||
("CANCEL", {"type": 'ESC', "value": 'PRESS', "any": True}, None),
|
||||
("CANCEL", {"type": 'RIGHTMOUSE', "value": 'PRESS', "any": True}, None),
|
||||
])
|
||||
return keymap
|
||||
|
||||
|
||||
def km_curve_pen_modal_map(_params):
|
||||
items = []
|
||||
|
@ -8126,6 +8145,7 @@ def generate_keymaps(params=None):
|
|||
km_view3d_dolly_modal(params),
|
||||
km_paint_stroke_modal(params),
|
||||
km_sculpt_expand_modal(params),
|
||||
km_sculpt_mesh_filter_modal_map(params),
|
||||
km_curve_pen_modal_map(params),
|
||||
km_node_link_modal_map(params),
|
||||
|
||||
|
|
|
@ -54,6 +54,9 @@ class SCENE_OT_freestyle_fill_range_by_selection(Operator):
|
|||
# Find the reference object
|
||||
if m.type == 'DISTANCE_FROM_CAMERA':
|
||||
ref = scene.camera
|
||||
if ref is None:
|
||||
self.report({'ERROR'}, "No active camera in the scene")
|
||||
return {'CANCELLED'}
|
||||
matrix_to_camera = ref.matrix_world.inverted()
|
||||
elif m.type == 'DISTANCE_FROM_OBJECT':
|
||||
if m.target is None:
|
||||
|
|
|
@ -604,7 +604,7 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel):
|
|||
colliding_names = []
|
||||
for collection in (
|
||||
# Built-in names.
|
||||
{"shade_smooth": None, "crease": None},
|
||||
{"crease": None},
|
||||
mesh.attributes,
|
||||
None if ob is None else ob.vertex_groups,
|
||||
):
|
||||
|
|
|
@ -3221,17 +3221,35 @@ class VIEW3D_MT_sculpt(Menu):
|
|||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator("transform.translate")
|
||||
layout.operator("transform.rotate")
|
||||
layout.operator("transform.resize", text="Scale")
|
||||
|
||||
props = layout.operator("sculpt.mesh_filter", text="Sphere")
|
||||
props.type = 'SPHERE'
|
||||
|
||||
layout.separator()
|
||||
|
||||
props = layout.operator("paint.hide_show", text="Box Hide")
|
||||
props.action = 'HIDE'
|
||||
|
||||
props = layout.operator("paint.hide_show", text="Box Show")
|
||||
props.action = 'SHOW'
|
||||
|
||||
layout.separator()
|
||||
|
||||
props = layout.operator("sculpt.face_set_change_visibility", text="Toggle Visibility")
|
||||
props.mode = 'TOGGLE'
|
||||
|
||||
props = layout.operator("sculpt.face_set_change_visibility", text="Hide Active Face Set")
|
||||
props.mode = 'HIDE_ACTIVE'
|
||||
|
||||
props = layout.operator("paint.hide_show", text="Show All")
|
||||
props.action = 'SHOW'
|
||||
props.area = 'ALL'
|
||||
|
||||
props = layout.operator("paint.hide_show", text="Box Show")
|
||||
props.action = 'SHOW'
|
||||
props.area = 'INSIDE'
|
||||
|
||||
props = layout.operator("paint.hide_show", text="Box Hide")
|
||||
props.action = 'HIDE'
|
||||
props.area = 'INSIDE'
|
||||
props = layout.operator("sculpt.face_set_change_visibility", text="Invert Visible")
|
||||
props.mode = 'INVERT'
|
||||
|
||||
props = layout.operator("paint.hide_show", text="Hide Masked")
|
||||
props.action = 'HIDE'
|
||||
|
@ -3239,10 +3257,55 @@ class VIEW3D_MT_sculpt(Menu):
|
|||
|
||||
layout.separator()
|
||||
|
||||
props = layout.operator("sculpt.trim_box_gesture", text="Box Trim")
|
||||
props.trim_mode = 'DIFFERENCE'
|
||||
|
||||
layout.operator("sculpt.trim_lasso_gesture", text="Lasso Trim")
|
||||
props.trim_mode = 'DIFFERENCE'
|
||||
|
||||
props = layout.operator("sculpt.trim_box_gesture", text="Box Add")
|
||||
props.trim_mode = 'JOIN'
|
||||
|
||||
layout.operator("sculpt.trim_lasso_gesture", text="Lasso Add")
|
||||
props.trim_mode = 'JOIN'
|
||||
|
||||
layout.operator("sculpt.project_line_gesture", text="Line Project")
|
||||
|
||||
layout.separator()
|
||||
|
||||
# Fair Positions
|
||||
props = layout.operator("sculpt.face_set_edit", text="Fair Positions")
|
||||
props.mode = 'FAIR_POSITIONS'
|
||||
|
||||
# Fair Tangency
|
||||
props = layout.operator("sculpt.face_set_edit", text="Fair Tangency")
|
||||
props.mode = 'FAIR_TANGENCY'
|
||||
|
||||
layout.separator()
|
||||
|
||||
sculpt_filters_types = [
|
||||
('SMOOTH', "Smooth"),
|
||||
('SURFACE_SMOOTH', "Surface Smooth"),
|
||||
('INFLATE', "Inflate"),
|
||||
('RELAX', "Relax Topology"),
|
||||
('RELAX_FACE_SETS', "Relax Face Sets"),
|
||||
('SHARPEN', "Sharpen"),
|
||||
('ENHANCE_DETAILS', "Enhance Details"),
|
||||
('ERASE_DISCPLACEMENT', "Erase Multires Displacement"),
|
||||
('RANDOM', "Randomize")
|
||||
]
|
||||
|
||||
for filter_type, ui_name in sculpt_filters_types:
|
||||
props = layout.operator("sculpt.mesh_filter", text=ui_name)
|
||||
props.type = filter_type
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.menu("VIEW3D_MT_sculpt_set_pivot", text="Set Pivot")
|
||||
|
||||
layout.separator()
|
||||
|
||||
# Rebuild BVH
|
||||
layout.operator("sculpt.optimize")
|
||||
|
||||
layout.separator()
|
||||
|
|
|
@ -74,7 +74,7 @@ struct Scene;
|
|||
/* keep in sync with MFace/MPoly types */
|
||||
typedef struct DMFlagMat {
|
||||
short mat_nr;
|
||||
char flag;
|
||||
bool sharp;
|
||||
} DMFlagMat;
|
||||
|
||||
typedef enum DerivedMeshType {
|
||||
|
|
|
@ -259,7 +259,7 @@ extern IDTypeInfo IDType_ID_AC;
|
|||
extern IDTypeInfo IDType_ID_NT;
|
||||
extern IDTypeInfo IDType_ID_BR;
|
||||
extern IDTypeInfo IDType_ID_PA;
|
||||
extern IDTypeInfo IDType_ID_GD;
|
||||
extern IDTypeInfo IDType_ID_GD_LEGACY;
|
||||
extern IDTypeInfo IDType_ID_WM;
|
||||
extern IDTypeInfo IDType_ID_MC;
|
||||
extern IDTypeInfo IDType_ID_MSK;
|
||||
|
|
|
@ -453,12 +453,15 @@ void BKE_mesh_ensure_normals_for_display(struct Mesh *mesh);
|
|||
*
|
||||
* Used when defining an empty custom loop normals data layer,
|
||||
* to keep same shading as with auto-smooth!
|
||||
*
|
||||
* \param sharp_faces: Optional array used to mark specific faces for sharp shading.
|
||||
*/
|
||||
void BKE_edges_sharp_from_angle_set(int numEdges,
|
||||
const struct MLoop *mloops,
|
||||
int numLoops,
|
||||
const struct MPoly *polys,
|
||||
const float (*poly_normals)[3],
|
||||
const bool *sharp_faces,
|
||||
int numPolys,
|
||||
float split_angle,
|
||||
bool *sharp_edges);
|
||||
|
@ -574,6 +577,7 @@ void BKE_lnor_space_custom_normal_to_data(const MLoopNorSpace *lnor_space,
|
|||
* (splitting edges).
|
||||
*
|
||||
* \param loop_to_poly_map: Optional pre-created map from loops to their polygon.
|
||||
* \param sharp_faces: Optional array used to mark specific faces for sharp shading.
|
||||
* \param sharp_edges: Optional array of sharp edge tags, used to split the evaluated normals on
|
||||
* each side of the edge.
|
||||
*/
|
||||
|
@ -591,6 +595,7 @@ void BKE_mesh_normals_loop_split(const float (*vert_positions)[3],
|
|||
bool use_split_normals,
|
||||
float split_angle,
|
||||
const bool *sharp_edges,
|
||||
const bool *sharp_faces,
|
||||
const int *loop_to_poly_map,
|
||||
MLoopNorSpaceArray *r_lnors_spacearr,
|
||||
short (*clnors_data)[2]);
|
||||
|
@ -605,6 +610,7 @@ void BKE_mesh_normals_loop_custom_set(const float (*vert_positions)[3],
|
|||
int numLoops,
|
||||
const struct MPoly *polys,
|
||||
const float (*poly_normals)[3],
|
||||
const bool *sharp_faces,
|
||||
int numPolys,
|
||||
bool *sharp_edges,
|
||||
short (*r_clnors_data)[2]);
|
||||
|
@ -618,6 +624,7 @@ void BKE_mesh_normals_loop_custom_from_verts_set(const float (*vert_positions)[3
|
|||
int numLoops,
|
||||
const struct MPoly *polys,
|
||||
const float (*poly_normals)[3],
|
||||
const bool *sharp_faces,
|
||||
int numPolys,
|
||||
bool *sharp_edges,
|
||||
short (*r_clnors_data)[2]);
|
||||
|
|
|
@ -96,6 +96,9 @@ void BKE_mesh_legacy_convert_loose_edges_to_flag(struct Mesh *mesh);
|
|||
void BKE_mesh_legacy_attribute_flags_to_strings(struct Mesh *mesh);
|
||||
void BKE_mesh_legacy_attribute_strings_to_flags(struct Mesh *mesh);
|
||||
|
||||
void BKE_mesh_legacy_sharp_faces_to_flags(struct Mesh *mesh);
|
||||
void BKE_mesh_legacy_sharp_faces_from_flags(struct Mesh *mesh);
|
||||
|
||||
void BKE_mesh_legacy_sharp_edges_to_flags(struct Mesh *mesh);
|
||||
void BKE_mesh_legacy_sharp_edges_from_flags(struct Mesh *mesh);
|
||||
|
||||
|
|
|
@ -324,6 +324,7 @@ int *BKE_mesh_calc_smoothgroups(int totedge,
|
|||
const struct MLoop *mloop,
|
||||
int totloop,
|
||||
const bool *sharp_edges,
|
||||
const bool *sharp_faces,
|
||||
int *r_totgroup,
|
||||
bool use_bitflags);
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
|
|||
const struct MLoop *mloop,
|
||||
const struct MLoopTri *looptri,
|
||||
uint looptri_len,
|
||||
const bool *sharp_faces,
|
||||
|
||||
struct CustomData *loopdata,
|
||||
bool calc_active_tangent,
|
||||
|
|
|
@ -76,6 +76,7 @@ typedef struct ShrinkwrapTreeData {
|
|||
const struct MPoly *polys;
|
||||
const float (*vert_normals)[3];
|
||||
const float (*poly_normals)[3];
|
||||
const bool *sharp_faces;
|
||||
const float (*clnors)[3];
|
||||
ShrinkwrapBoundaryData *boundary;
|
||||
} ShrinkwrapTreeData;
|
||||
|
|
|
@ -515,7 +515,7 @@ static void armature_deform_coords_impl(const Object *ob_arm,
|
|||
dverts_len = lt->pntsu * lt->pntsv * lt->pntsw;
|
||||
}
|
||||
}
|
||||
else if (ob_target->type == OB_GPENCIL) {
|
||||
else if (ob_target->type == OB_GPENCIL_LEGACY) {
|
||||
target_data_id = (const ID *)ob_target->data;
|
||||
dverts = gps_target->dvert;
|
||||
if (dverts) {
|
||||
|
|
|
@ -63,6 +63,9 @@ bool allow_procedural_attribute_access(StringRef attribute_name)
|
|||
if (attribute_name.startswith(".hide")) {
|
||||
return false;
|
||||
}
|
||||
if (attribute_name.startswith(".uv")) {
|
||||
return false;
|
||||
}
|
||||
if (attribute_name.startswith("." UV_VERTSEL_NAME ".")) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -103,7 +103,6 @@ static void fill_mesh_topology(const int vert_offset,
|
|||
MPoly &poly = polys[ring_poly_offset + i_profile];
|
||||
poly.loopstart = ring_segment_loop_offset;
|
||||
poly.totloop = 4;
|
||||
poly.flag = ME_SMOOTH;
|
||||
|
||||
MLoop &loop_a = loops[ring_segment_loop_offset];
|
||||
loop_a.v = ring_vert_offset + i_profile;
|
||||
|
@ -674,6 +673,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
|
|||
MutableSpan<MEdge> edges = mesh->edges_for_write();
|
||||
MutableSpan<MPoly> polys = mesh->polys_for_write();
|
||||
MutableSpan<MLoop> loops = mesh->loops_for_write();
|
||||
MutableAttributeAccessor mesh_attributes = mesh->attributes_for_write();
|
||||
|
||||
foreach_curve_combination(curves_info, offsets, [&](const CombinationInfo &info) {
|
||||
fill_mesh_topology(info.vert_range.start(),
|
||||
|
@ -690,6 +690,23 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
|
|||
polys);
|
||||
});
|
||||
|
||||
if (fill_caps) {
|
||||
/* TODO: This is used to keep the tests passing after refactoring mesh shade smooth flags. It
|
||||
* can be removed if the tests are updated and the final shading results will be the same. */
|
||||
SpanAttributeWriter<bool> sharp_faces = mesh_attributes.lookup_or_add_for_write_span<bool>(
|
||||
"sharp_face", ATTR_DOMAIN_FACE);
|
||||
foreach_curve_combination(curves_info, offsets, [&](const CombinationInfo &info) {
|
||||
const bool has_caps = fill_caps && !info.main_cyclic && info.profile_cyclic;
|
||||
if (has_caps) {
|
||||
const int poly_num = info.main_segment_num * info.profile_segment_num;
|
||||
const int cap_poly_offset = info.poly_range.start() + poly_num;
|
||||
sharp_faces.span[cap_poly_offset] = true;
|
||||
sharp_faces.span[cap_poly_offset + 1] = true;
|
||||
}
|
||||
});
|
||||
sharp_faces.finish();
|
||||
}
|
||||
|
||||
const Span<float3> main_positions = main.evaluated_positions();
|
||||
const Span<float3> tangents = main.evaluated_tangents();
|
||||
const Span<float3> normals = main.evaluated_normals();
|
||||
|
@ -721,8 +738,6 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
|
|||
positions.slice(info.vert_range));
|
||||
});
|
||||
|
||||
MutableAttributeAccessor mesh_attributes = mesh->attributes_for_write();
|
||||
|
||||
SpanAttributeWriter<bool> sharp_edges;
|
||||
write_sharp_bezier_edges(curves_info, offsets, mesh_attributes, sharp_edges);
|
||||
if (fill_caps) {
|
||||
|
|
|
@ -382,6 +382,8 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
|
|||
if (dirty_nors_dst || do_loop_nors_dst) {
|
||||
const bool *sharp_edges = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&me_dst->edata, CD_PROP_BOOL, "sharp_edge"));
|
||||
const bool *sharp_faces = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&me_dst->pdata, CD_PROP_BOOL, "sharp_face"));
|
||||
BKE_mesh_normals_loop_split(positions_dst,
|
||||
BKE_mesh_vert_normals_ensure(me_dst),
|
||||
num_verts_dst,
|
||||
|
@ -396,6 +398,7 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
|
|||
use_split_nors_dst,
|
||||
split_angle_dst,
|
||||
sharp_edges,
|
||||
sharp_faces,
|
||||
nullptr,
|
||||
nullptr,
|
||||
custom_nors_dst);
|
||||
|
@ -451,6 +454,8 @@ static void data_transfer_dtdata_type_postprocess(Object * /*ob_src*/,
|
|||
loops_dst.size(),
|
||||
polys_dst.data(),
|
||||
poly_nors_dst,
|
||||
static_cast<const bool *>(CustomData_get_layer_named(
|
||||
&me_dst->pdata, CD_PROP_BOOL, "sharp_face")),
|
||||
polys_dst.size(),
|
||||
sharp_edges.span.data(),
|
||||
custom_nors_dst);
|
||||
|
@ -1109,26 +1114,21 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map,
|
|||
return true;
|
||||
}
|
||||
if (r_map && cddata_type == CD_FAKE_SHARP) {
|
||||
const size_t elem_size = sizeof(*((MPoly *)nullptr));
|
||||
const size_t data_size = sizeof(((MPoly *)nullptr)->flag);
|
||||
const size_t data_offset = offsetof(MPoly, flag);
|
||||
const uint64_t data_flag = ME_SMOOTH;
|
||||
|
||||
data_transfer_layersmapping_add_item(r_map,
|
||||
cddata_type,
|
||||
mix_mode,
|
||||
mix_factor,
|
||||
mix_weights,
|
||||
me_src->polys().data(),
|
||||
me_dst->polys_for_write().data(),
|
||||
me_src->totpoly,
|
||||
me_dst->totpoly,
|
||||
elem_size,
|
||||
data_size,
|
||||
data_offset,
|
||||
data_flag,
|
||||
nullptr,
|
||||
interp_data);
|
||||
if (!CustomData_get_layer_named(&me_dst->pdata, CD_PROP_BOOL, "sharp_face")) {
|
||||
CustomData_add_layer_named(
|
||||
&me_dst->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, me_dst->totpoly, "sharp_face");
|
||||
}
|
||||
data_transfer_layersmapping_add_item_cd(
|
||||
r_map,
|
||||
CD_PROP_BOOL,
|
||||
mix_mode,
|
||||
mix_factor,
|
||||
mix_weights,
|
||||
CustomData_get_layer_named(&me_src->pdata, CD_PROP_BOOL, "sharp_face"),
|
||||
CustomData_get_layer_named_for_write(
|
||||
&me_dst->pdata, CD_PROP_BOOL, "sharp_face", num_elem_dst),
|
||||
interp,
|
||||
interp_data);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -440,7 +440,7 @@ bool BKE_object_supports_vertex_groups(const Object *ob)
|
|||
return false;
|
||||
}
|
||||
|
||||
return ELEM(GS(id->name), ID_ME, ID_LT, ID_GD);
|
||||
return ELEM(GS(id->name), ID_ME, ID_LT, ID_GD_LEGACY);
|
||||
}
|
||||
|
||||
const ListBase *BKE_id_defgroup_list_get(const ID *id)
|
||||
|
@ -454,7 +454,7 @@ const ListBase *BKE_id_defgroup_list_get(const ID *id)
|
|||
const Lattice *lt = (const Lattice *)id;
|
||||
return <->vertex_group_names;
|
||||
}
|
||||
case ID_GD: {
|
||||
case ID_GD_LEGACY: {
|
||||
const bGPdata *gpd = (const bGPdata *)id;
|
||||
return &gpd->vertex_group_names;
|
||||
}
|
||||
|
@ -477,7 +477,7 @@ static const int *object_defgroup_active_index_get_p(const Object *ob)
|
|||
const Lattice *lattice = (const Lattice *)ob->data;
|
||||
return &lattice->vertex_group_active_index;
|
||||
}
|
||||
case OB_GPENCIL: {
|
||||
case OB_GPENCIL_LEGACY: {
|
||||
const bGPdata *gpd = (const bGPdata *)ob->data;
|
||||
return &gpd->vertex_group_active_index;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "DNA_object_types.h"
|
||||
#include "DNA_rigidbody_types.h"
|
||||
|
||||
#include "BKE_attribute.h"
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_effect.h"
|
||||
#include "BKE_fluid.h"
|
||||
#include "BKE_global.h"
|
||||
|
@ -3213,16 +3213,8 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds,
|
|||
float size[3];
|
||||
float cell_size_scaled[3];
|
||||
|
||||
/* Assign material + flags to new mesh.
|
||||
* If there are no faces in original mesh, keep materials and flags unchanged. */
|
||||
MPoly mp_example = {0};
|
||||
if (MPoly *polys = BKE_mesh_polys_for_write(orgmesh)) {
|
||||
mp_example = *polys;
|
||||
}
|
||||
|
||||
const int *orig_material_indices = BKE_mesh_material_indices(orgmesh);
|
||||
const short mp_mat_nr = orig_material_indices ? orig_material_indices[0] : 0;
|
||||
const char mp_flag = mp_example.flag;
|
||||
|
||||
int i;
|
||||
int num_verts, num_faces;
|
||||
|
@ -3251,6 +3243,10 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds,
|
|||
blender::MutableSpan<MPoly> polys = me->polys_for_write();
|
||||
blender::MutableSpan<MLoop> loops = me->loops_for_write();
|
||||
|
||||
const bool is_sharp = orgmesh->attributes().lookup_or_default<bool>(
|
||||
"sharp_face", ATTR_DOMAIN_FACE, false)[0];
|
||||
BKE_mesh_smooth_flag_set(me, !is_sharp);
|
||||
|
||||
/* Get size (dimension) but considering scaling. */
|
||||
copy_v3_v3(cell_size_scaled, fds->cell_size);
|
||||
mul_v3_v3(cell_size_scaled, ob->scale);
|
||||
|
@ -3338,7 +3334,6 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds,
|
|||
for (const int i : polys.index_range()) {
|
||||
/* Initialize from existing face. */
|
||||
material_indices[i] = mp_mat_nr;
|
||||
polys[i].flag = mp_flag;
|
||||
|
||||
polys[i].loopstart = i * 3;
|
||||
polys[i].totloop = 3;
|
||||
|
|
|
@ -913,16 +913,6 @@ static void tag_component_positions_changed(void *owner)
|
|||
}
|
||||
}
|
||||
|
||||
static bool get_shade_smooth(const MPoly &poly)
|
||||
{
|
||||
return poly.flag & ME_SMOOTH;
|
||||
}
|
||||
|
||||
static void set_shade_smooth(MPoly &poly, bool value)
|
||||
{
|
||||
SET_FLAG_FROM_TEST(poly.flag, value, ME_SMOOTH);
|
||||
}
|
||||
|
||||
static float get_crease(const float &crease)
|
||||
{
|
||||
return crease;
|
||||
|
@ -1217,17 +1207,16 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
|
|||
nullptr,
|
||||
AttributeValidator{&material_index_clamp});
|
||||
|
||||
static BuiltinCustomDataLayerProvider shade_smooth(
|
||||
"shade_smooth",
|
||||
ATTR_DOMAIN_FACE,
|
||||
CD_PROP_BOOL,
|
||||
CD_MPOLY,
|
||||
BuiltinAttributeProvider::NonCreatable,
|
||||
BuiltinAttributeProvider::NonDeletable,
|
||||
face_access,
|
||||
make_derived_read_attribute<MPoly, bool, get_shade_smooth>,
|
||||
make_derived_write_attribute<MPoly, bool, get_shade_smooth, set_shade_smooth>,
|
||||
nullptr);
|
||||
static BuiltinCustomDataLayerProvider sharp_face("sharp_face",
|
||||
ATTR_DOMAIN_FACE,
|
||||
CD_PROP_BOOL,
|
||||
CD_PROP_BOOL,
|
||||
BuiltinAttributeProvider::Creatable,
|
||||
BuiltinAttributeProvider::Deletable,
|
||||
face_access,
|
||||
make_array_read_attribute<bool>,
|
||||
make_array_write_attribute<bool>,
|
||||
nullptr);
|
||||
|
||||
static BuiltinCustomDataLayerProvider sharp_edge("sharp_edge",
|
||||
ATTR_DOMAIN_EDGE,
|
||||
|
@ -1259,7 +1248,7 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
|
|||
static CustomDataAttributeProvider face_custom_data(ATTR_DOMAIN_FACE, face_access);
|
||||
|
||||
return ComponentAttributeProviders(
|
||||
{&position, &id, &material_index, &shade_smooth, &sharp_edge, &crease},
|
||||
{&position, &id, &material_index, &sharp_face, &sharp_edge, &crease},
|
||||
{&corner_custom_data,
|
||||
&vertex_groups,
|
||||
&point_custom_data,
|
||||
|
|
|
@ -296,10 +296,10 @@ static void greasepencil_blend_read_expand(BlendExpander *expander, ID *id)
|
|||
}
|
||||
}
|
||||
|
||||
IDTypeInfo IDType_ID_GD = {
|
||||
.id_code = ID_GD,
|
||||
.id_filter = FILTER_ID_GD,
|
||||
.main_listbase_index = INDEX_ID_GD,
|
||||
IDTypeInfo IDType_ID_GD_LEGACY = {
|
||||
.id_code = ID_GD_LEGACY,
|
||||
.id_filter = FILTER_ID_GD_LEGACY,
|
||||
.main_listbase_index = INDEX_ID_GD_LEGACY,
|
||||
.struct_size = sizeof(bGPdata),
|
||||
.name = "GPencil",
|
||||
.name_plural = "grease_pencils",
|
||||
|
@ -707,7 +707,7 @@ bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[])
|
|||
bGPdata *gpd;
|
||||
|
||||
/* allocate memory for a new block */
|
||||
gpd = BKE_libblock_alloc(bmain, ID_GD, name, 0);
|
||||
gpd = BKE_libblock_alloc(bmain, ID_GD_LEGACY, name, 0);
|
||||
|
||||
/* initial settings */
|
||||
gpd->flag = (GP_DATA_DISPINFO | GP_DATA_EXPAND);
|
||||
|
@ -2710,7 +2710,7 @@ void BKE_gpencil_layer_transform_matrix_get(const Depsgraph *depsgraph,
|
|||
|
||||
/* if not layer parented, try with object parented */
|
||||
if (obparent_eval == NULL) {
|
||||
if ((ob_eval != NULL) && (ob_eval->type == OB_GPENCIL)) {
|
||||
if ((ob_eval != NULL) && (ob_eval->type == OB_GPENCIL_LEGACY)) {
|
||||
copy_m4_m4(diff_mat, ob_eval->object_to_world);
|
||||
mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat);
|
||||
return;
|
||||
|
@ -2748,7 +2748,7 @@ void BKE_gpencil_layer_transform_matrix_get(const Depsgraph *depsgraph,
|
|||
|
||||
void BKE_gpencil_update_layer_transforms(const Depsgraph *depsgraph, Object *ob)
|
||||
{
|
||||
if (ob->type != OB_GPENCIL) {
|
||||
if (ob->type != OB_GPENCIL_LEGACY) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -468,7 +468,7 @@ void BKE_gpencil_convert_curve(Main *bmain,
|
|||
const float scale_thickness,
|
||||
const float sample)
|
||||
{
|
||||
if (ELEM(NULL, ob_gp, ob_cu) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == NULL)) {
|
||||
if (ELEM(NULL, ob_gp, ob_cu) || (ob_gp->type != OB_GPENCIL_LEGACY) || (ob_gp->data == NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -2703,7 +2703,8 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
|
|||
{
|
||||
using namespace blender;
|
||||
using namespace blender::bke;
|
||||
if (ELEM(nullptr, ob_gp, ob_mesh) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == nullptr)) {
|
||||
if (ELEM(nullptr, ob_gp, ob_mesh) || (ob_gp->type != OB_GPENCIL_LEGACY) ||
|
||||
(ob_gp->data == nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ static void id_type_init(void)
|
|||
INIT_TYPE(ID_NT);
|
||||
INIT_TYPE(ID_BR);
|
||||
INIT_TYPE(ID_PA);
|
||||
INIT_TYPE(ID_GD);
|
||||
INIT_TYPE(ID_GD_LEGACY);
|
||||
INIT_TYPE(ID_WM);
|
||||
INIT_TYPE(ID_MC);
|
||||
INIT_TYPE(ID_MSK);
|
||||
|
@ -220,7 +220,7 @@ uint64_t BKE_idtype_idcode_to_idfilter(const short idcode)
|
|||
CASE_IDFILTER(CA);
|
||||
CASE_IDFILTER(CF);
|
||||
CASE_IDFILTER(CU_LEGACY);
|
||||
CASE_IDFILTER(GD);
|
||||
CASE_IDFILTER(GD_LEGACY);
|
||||
CASE_IDFILTER(GR);
|
||||
CASE_IDFILTER(CV);
|
||||
CASE_IDFILTER(IM);
|
||||
|
@ -278,7 +278,7 @@ short BKE_idtype_idcode_from_idfilter(const uint64_t idfilter)
|
|||
CASE_IDFILTER(CA);
|
||||
CASE_IDFILTER(CF);
|
||||
CASE_IDFILTER(CU_LEGACY);
|
||||
CASE_IDFILTER(GD);
|
||||
CASE_IDFILTER(GD_LEGACY);
|
||||
CASE_IDFILTER(GR);
|
||||
CASE_IDFILTER(CV);
|
||||
CASE_IDFILTER(IM);
|
||||
|
@ -334,7 +334,7 @@ int BKE_idtype_idcode_to_index(const short idcode)
|
|||
CASE_IDINDEX(CA);
|
||||
CASE_IDINDEX(CF);
|
||||
CASE_IDINDEX(CU_LEGACY);
|
||||
CASE_IDINDEX(GD);
|
||||
CASE_IDINDEX(GD_LEGACY);
|
||||
CASE_IDINDEX(GR);
|
||||
CASE_IDINDEX(CV);
|
||||
CASE_IDINDEX(IM);
|
||||
|
@ -393,7 +393,7 @@ short BKE_idtype_idcode_from_index(const int index)
|
|||
CASE_IDCODE(CA);
|
||||
CASE_IDCODE(CF);
|
||||
CASE_IDCODE(CU_LEGACY);
|
||||
CASE_IDCODE(GD);
|
||||
CASE_IDCODE(GD_LEGACY);
|
||||
CASE_IDCODE(GR);
|
||||
CASE_IDCODE(CV);
|
||||
CASE_IDCODE(IM);
|
||||
|
|
|
@ -2281,6 +2281,8 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
|
|||
&mesh->ldata, CD_CUSTOMLOOPNORMAL, loops.size())); /* May be nullptr. */
|
||||
const bool *sharp_edges = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge"));
|
||||
const bool *sharp_faces = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, "sharp_face"));
|
||||
BKE_mesh_normals_loop_split(positions,
|
||||
vert_normals,
|
||||
mesh->totvert,
|
||||
|
@ -2295,6 +2297,7 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
|
|||
(mesh->flag & ME_AUTOSMOOTH) != 0,
|
||||
mesh->smoothresh,
|
||||
sharp_edges,
|
||||
sharp_faces,
|
||||
nullptr,
|
||||
nullptr,
|
||||
clnors);
|
||||
|
|
|
@ -839,7 +839,7 @@ bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
|
|||
RNA_property_update(C, ptr, prop);
|
||||
|
||||
/* tag grease pencil data-block and disable onion */
|
||||
if (GS(id->name) == ID_GD) {
|
||||
if (GS(id->name) == ID_GD_LEGACY) {
|
||||
DEG_id_tag_update(id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
||||
DEG_id_tag_update(newid, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
||||
bGPdata *gpd = (bGPdata *)newid;
|
||||
|
|
|
@ -396,7 +396,7 @@ uint64_t BKE_library_id_can_use_filter_id(const ID *id_owner)
|
|||
case ID_SCE:
|
||||
return FILTER_ID_OB | FILTER_ID_WO | FILTER_ID_SCE | FILTER_ID_MC | FILTER_ID_MA |
|
||||
FILTER_ID_GR | FILTER_ID_TXT | FILTER_ID_LS | FILTER_ID_MSK | FILTER_ID_SO |
|
||||
FILTER_ID_GD | FILTER_ID_BR | FILTER_ID_PAL | FILTER_ID_IM | FILTER_ID_NT;
|
||||
FILTER_ID_GD_LEGACY | FILTER_ID_BR | FILTER_ID_PAL | FILTER_ID_IM | FILTER_ID_NT;
|
||||
case ID_OB:
|
||||
/* Could be more specific, but simpler to just always say 'yes' here. */
|
||||
return FILTER_ID_ALL;
|
||||
|
@ -435,7 +435,7 @@ uint64_t BKE_library_id_can_use_filter_id(const ID *id_owner)
|
|||
case ID_PA:
|
||||
return FILTER_ID_OB | FILTER_ID_GR | FILTER_ID_TE;
|
||||
case ID_MC:
|
||||
return FILTER_ID_GD | FILTER_ID_IM;
|
||||
return FILTER_ID_GD_LEGACY | FILTER_ID_IM;
|
||||
case ID_MSK:
|
||||
/* WARNING! mask->parent.id, not typed. */
|
||||
return FILTER_ID_MC;
|
||||
|
@ -443,7 +443,7 @@ uint64_t BKE_library_id_can_use_filter_id(const ID *id_owner)
|
|||
return FILTER_ID_TE | FILTER_ID_OB;
|
||||
case ID_LP:
|
||||
return FILTER_ID_IM;
|
||||
case ID_GD:
|
||||
case ID_GD_LEGACY:
|
||||
return FILTER_ID_MA;
|
||||
case ID_WS:
|
||||
return FILTER_ID_SCE;
|
||||
|
|
|
@ -625,7 +625,7 @@ ListBase *which_libbase(Main *bmain, short type)
|
|||
return &(bmain->particles);
|
||||
case ID_WM:
|
||||
return &(bmain->wm);
|
||||
case ID_GD:
|
||||
case ID_GD_LEGACY:
|
||||
return &(bmain->gpencils);
|
||||
case ID_MC:
|
||||
return &(bmain->movieclips);
|
||||
|
@ -669,7 +669,7 @@ int set_listbasepointers(Main *bmain, ListBase *lb[/*INDEX_ID_MAX*/])
|
|||
lb[INDEX_ID_PAL] = &(bmain->palettes);
|
||||
|
||||
/* Referenced by nodes, objects, view, scene etc, before to free after. */
|
||||
lb[INDEX_ID_GD] = &(bmain->gpencils);
|
||||
lb[INDEX_ID_GD_LEGACY] = &(bmain->gpencils);
|
||||
|
||||
lb[INDEX_ID_NT] = &(bmain->nodetrees);
|
||||
lb[INDEX_ID_IM] = &(bmain->images);
|
||||
|
|
|
@ -328,7 +328,7 @@ Material ***BKE_object_material_array_p(Object *ob)
|
|||
MetaBall *mb = static_cast<MetaBall *>(ob->data);
|
||||
return &(mb->mat);
|
||||
}
|
||||
if (ob->type == OB_GPENCIL) {
|
||||
if (ob->type == OB_GPENCIL_LEGACY) {
|
||||
bGPdata *gpd = static_cast<bGPdata *>(ob->data);
|
||||
return &(gpd->mat);
|
||||
}
|
||||
|
@ -361,7 +361,7 @@ short *BKE_object_material_len_p(Object *ob)
|
|||
MetaBall *mb = static_cast<MetaBall *>(ob->data);
|
||||
return &(mb->totcol);
|
||||
}
|
||||
if (ob->type == OB_GPENCIL) {
|
||||
if (ob->type == OB_GPENCIL_LEGACY) {
|
||||
bGPdata *gpd = static_cast<bGPdata *>(ob->data);
|
||||
return &(gpd->totcol);
|
||||
}
|
||||
|
@ -392,7 +392,7 @@ Material ***BKE_id_material_array_p(ID *id)
|
|||
return &(((Curve *)id)->mat);
|
||||
case ID_MB:
|
||||
return &(((MetaBall *)id)->mat);
|
||||
case ID_GD:
|
||||
case ID_GD_LEGACY:
|
||||
return &(((bGPdata *)id)->mat);
|
||||
case ID_CV:
|
||||
return &(((Curves *)id)->mat);
|
||||
|
@ -418,7 +418,7 @@ short *BKE_id_material_len_p(ID *id)
|
|||
return &(((Curve *)id)->totcol);
|
||||
case ID_MB:
|
||||
return &(((MetaBall *)id)->totcol);
|
||||
case ID_GD:
|
||||
case ID_GD_LEGACY:
|
||||
return &(((bGPdata *)id)->totcol);
|
||||
case ID_CV:
|
||||
return &(((Curves *)id)->totcol);
|
||||
|
@ -480,7 +480,7 @@ bool BKE_object_material_slot_used(Object *object, short actcol)
|
|||
case ID_MB:
|
||||
/* Meta-elements don't support materials at the moment. */
|
||||
return false;
|
||||
case ID_GD:
|
||||
case ID_GD_LEGACY:
|
||||
return BKE_gpencil_material_index_used((bGPdata *)ob_data, actcol - 1);
|
||||
default:
|
||||
return false;
|
||||
|
@ -1090,7 +1090,7 @@ void BKE_object_material_remap(Object *ob, const uint *remap)
|
|||
else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF, OB_FONT)) {
|
||||
BKE_curve_material_remap(static_cast<Curve *>(ob->data), remap, ob->totcol);
|
||||
}
|
||||
else if (ob->type == OB_GPENCIL) {
|
||||
else if (ob->type == OB_GPENCIL_LEGACY) {
|
||||
BKE_gpencil_material_remap(static_cast<bGPdata *>(ob->data), remap, ob->totcol);
|
||||
}
|
||||
else {
|
||||
|
@ -1347,7 +1347,7 @@ bool BKE_object_material_slot_remove(Main *bmain, Object *ob)
|
|||
}
|
||||
}
|
||||
/* check indices from gpencil */
|
||||
else if (ob->type == OB_GPENCIL) {
|
||||
else if (ob->type == OB_GPENCIL_LEGACY) {
|
||||
BKE_gpencil_material_index_reassign((bGPdata *)ob->data, ob->totcol, actcol - 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -1480,7 +1480,6 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob)
|
|||
const int count = indices[2] != indices[3] ? 4 : 3;
|
||||
polys[i].loopstart = loop_offset;
|
||||
polys[i].totloop = count;
|
||||
polys[i].flag = ME_SMOOTH;
|
||||
|
||||
mloop[loop_offset].v = uint32_t(indices[0]);
|
||||
mloop[loop_offset + 1].v = uint32_t(indices[1]);
|
||||
|
|
|
@ -255,20 +255,24 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
|
|||
Set<std::string> names_to_skip;
|
||||
if (!BLO_write_is_undo(writer)) {
|
||||
/* When converting to the old mesh format, don't save redundant attributes. */
|
||||
names_to_skip.add_multiple_new({".hide_vert",
|
||||
names_to_skip.add_multiple_new({"position",
|
||||
".hide_vert",
|
||||
".hide_edge",
|
||||
".hide_poly",
|
||||
"position",
|
||||
"material_index",
|
||||
".uv_seam",
|
||||
".select_vert",
|
||||
".select_edge",
|
||||
".select_poly"});
|
||||
".select_poly",
|
||||
"material_index",
|
||||
"sharp_face",
|
||||
"sharp_edge"});
|
||||
|
||||
mesh->mvert = BKE_mesh_legacy_convert_positions_to_verts(
|
||||
mesh, temp_arrays_for_legacy_format, vert_layers);
|
||||
BKE_mesh_legacy_convert_hide_layers_to_flags(mesh);
|
||||
BKE_mesh_legacy_convert_selection_layers_to_flags(mesh);
|
||||
BKE_mesh_legacy_convert_material_indices_to_mpoly(mesh);
|
||||
BKE_mesh_legacy_sharp_faces_to_flags(mesh);
|
||||
BKE_mesh_legacy_bevel_weight_from_layers(mesh);
|
||||
BKE_mesh_legacy_edge_crease_from_layers(mesh);
|
||||
BKE_mesh_legacy_sharp_edges_to_flags(mesh);
|
||||
|
@ -1485,16 +1489,17 @@ void BKE_mesh_material_remap(Mesh *me, const uint *remap, uint remap_len)
|
|||
|
||||
void BKE_mesh_smooth_flag_set(Mesh *me, const bool use_smooth)
|
||||
{
|
||||
MutableSpan<MPoly> polys = me->polys_for_write();
|
||||
using namespace blender;
|
||||
using namespace blender::bke;
|
||||
MutableAttributeAccessor attributes = me->attributes_for_write();
|
||||
if (use_smooth) {
|
||||
for (MPoly &poly : polys) {
|
||||
poly.flag |= ME_SMOOTH;
|
||||
}
|
||||
attributes.remove("sharp_face");
|
||||
}
|
||||
else {
|
||||
for (MPoly &poly : polys) {
|
||||
poly.flag &= ~ME_SMOOTH;
|
||||
}
|
||||
SpanAttributeWriter<bool> sharp_faces = attributes.lookup_or_add_for_write_only_span<bool>(
|
||||
"sharp_face", ATTR_DOMAIN_FACE);
|
||||
sharp_faces.span.fill(true);
|
||||
sharp_faces.finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1842,7 +1847,8 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh,
|
|||
&mesh->ldata, CD_CUSTOMLOOPNORMAL, mesh->totloop);
|
||||
const bool *sharp_edges = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge"));
|
||||
|
||||
const bool *sharp_faces = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, "sharp_face"));
|
||||
const Span<float3> positions = mesh->vert_positions();
|
||||
const Span<MEdge> edges = mesh->edges();
|
||||
const Span<MPoly> polys = mesh->polys();
|
||||
|
@ -1862,6 +1868,7 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh,
|
|||
use_split_normals,
|
||||
split_angle,
|
||||
sharp_edges,
|
||||
sharp_faces,
|
||||
nullptr,
|
||||
r_lnors_spacearr,
|
||||
clnors);
|
||||
|
|
|
@ -391,15 +391,12 @@ static void copy_vert_attributes(Mesh *dest_mesh,
|
|||
|
||||
/* Similar to copy_vert_attributes but for poly attributes. */
|
||||
static void copy_poly_attributes(Mesh *dest_mesh,
|
||||
MPoly *poly,
|
||||
const MPoly *orig_poly,
|
||||
const Mesh *orig_me,
|
||||
int poly_index,
|
||||
int index_in_orig_me,
|
||||
Span<short> material_remap,
|
||||
MutableSpan<int> dst_material_indices)
|
||||
{
|
||||
poly->flag = orig_poly->flag;
|
||||
CustomData *target_cd = &dest_mesh->pdata;
|
||||
const CustomData *source_cd = &orig_me->pdata;
|
||||
for (int source_layer_i = 0; source_layer_i < source_cd->totlayer; ++source_layer_i) {
|
||||
|
@ -751,8 +748,6 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim)
|
|||
}
|
||||
|
||||
copy_poly_attributes(result,
|
||||
poly,
|
||||
orig_poly,
|
||||
orig_me,
|
||||
fi,
|
||||
index_in_orig_me,
|
||||
|
|
|
@ -195,6 +195,9 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
|
|||
MutableAttributeAccessor attributes = mesh->attributes_for_write();
|
||||
SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_only_span<int>(
|
||||
"material_index", ATTR_DOMAIN_FACE);
|
||||
SpanAttributeWriter<bool> sharp_faces = attributes.lookup_or_add_for_write_span<bool>(
|
||||
"sharp_face", ATTR_DOMAIN_FACE);
|
||||
|
||||
blender::float2 *mloopuv = static_cast<blender::float2 *>(CustomData_add_layer_named(
|
||||
&mesh->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, nullptr, mesh->totloop, DATA_("UVMap")));
|
||||
|
||||
|
@ -278,9 +281,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
|
|||
}
|
||||
}
|
||||
|
||||
if (is_smooth) {
|
||||
polys[dst_poly].flag |= ME_SMOOTH;
|
||||
}
|
||||
sharp_faces.span[dst_poly] = !is_smooth;
|
||||
dst_poly++;
|
||||
dst_loop += 3;
|
||||
index += 3;
|
||||
|
@ -363,9 +364,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
|
|||
}
|
||||
}
|
||||
|
||||
if (is_smooth) {
|
||||
polys[dst_poly].flag |= ME_SMOOTH;
|
||||
}
|
||||
sharp_faces.span[dst_poly] = !is_smooth;
|
||||
dst_poly++;
|
||||
dst_loop += 4;
|
||||
|
||||
|
@ -383,6 +382,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
|
|||
}
|
||||
|
||||
material_indices.finish();
|
||||
sharp_faces.finish();
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
|
|
@ -447,6 +447,12 @@ static void convert_mfaces_to_mpolys(ID *id,
|
|||
material_indices = static_cast<int *>(CustomData_add_layer_named(
|
||||
pdata, CD_PROP_INT32, CD_SET_DEFAULT, nullptr, totpoly, "material_index"));
|
||||
}
|
||||
bool *sharp_faces = static_cast<bool *>(
|
||||
CustomData_get_layer_named_for_write(pdata, CD_PROP_BOOL, "sharp_face", totpoly));
|
||||
if (!sharp_faces) {
|
||||
sharp_faces = static_cast<bool *>(CustomData_add_layer_named(
|
||||
pdata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, totpoly, "sharp_face"));
|
||||
}
|
||||
|
||||
numTex = CustomData_number_of_layers(fdata, CD_MTFACE);
|
||||
numCol = CustomData_number_of_layers(fdata, CD_MCOL);
|
||||
|
@ -491,7 +497,7 @@ static void convert_mfaces_to_mpolys(ID *id,
|
|||
poly->totloop = mf->v4 ? 4 : 3;
|
||||
|
||||
material_indices[i] = mf->mat_nr;
|
||||
poly->flag = mf->flag;
|
||||
sharp_faces[i] = (mf->flag & ME_SMOOTH) == 0;
|
||||
|
||||
#define ML(v1, v2) \
|
||||
{ \
|
||||
|
@ -975,6 +981,8 @@ static int mesh_tessface_calc(Mesh &mesh,
|
|||
mloop = (const MLoop *)CustomData_get_layer(ldata, CD_MLOOP);
|
||||
const int *material_indices = static_cast<const int *>(
|
||||
CustomData_get_layer_named(pdata, CD_PROP_INT32, "material_index"));
|
||||
const bool *sharp_faces = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(pdata, CD_PROP_BOOL, "sharp_face"));
|
||||
|
||||
/* Allocate the length of `totfaces`, avoid many small reallocation's,
|
||||
* if all faces are triangles it will be correct, `quads == 2x` allocations. */
|
||||
|
@ -1014,7 +1022,7 @@ static int mesh_tessface_calc(Mesh &mesh,
|
|||
lidx[2] = l3; \
|
||||
lidx[3] = 0; \
|
||||
mf->mat_nr = material_indices ? material_indices[poly_index] : 0; \
|
||||
mf->flag = poly->flag; \
|
||||
mf->flag = (sharp_faces && sharp_faces[poly_index]) ? 0 : ME_SMOOTH; \
|
||||
mf->edcode = 0; \
|
||||
(void)0
|
||||
|
||||
|
@ -1037,7 +1045,7 @@ static int mesh_tessface_calc(Mesh &mesh,
|
|||
lidx[2] = l3; \
|
||||
lidx[3] = l4; \
|
||||
mf->mat_nr = material_indices ? material_indices[poly_index] : 0; \
|
||||
mf->flag = poly->flag; \
|
||||
mf->flag = (sharp_faces && sharp_faces[poly_index]) ? 0 : ME_SMOOTH; \
|
||||
mf->edcode = TESSFACE_IS_QUAD; \
|
||||
(void)0
|
||||
|
||||
|
@ -1123,7 +1131,6 @@ static int mesh_tessface_calc(Mesh &mesh,
|
|||
lidx[3] = 0;
|
||||
|
||||
mf->mat_nr = material_indices ? material_indices[poly_index] : 0;
|
||||
mf->flag = poly->flag;
|
||||
mf->edcode = 0;
|
||||
|
||||
mface_index++;
|
||||
|
@ -1214,6 +1221,57 @@ void BKE_mesh_tessface_ensure(struct Mesh *mesh)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Sharp Edge Conversion
|
||||
* \{ */
|
||||
|
||||
void BKE_mesh_legacy_sharp_faces_to_flags(Mesh *mesh)
|
||||
{
|
||||
using namespace blender;
|
||||
MutableSpan<MPoly> polys = mesh->polys_for_write();
|
||||
if (const bool *sharp_faces = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, "sharp_face"))) {
|
||||
threading::parallel_for(polys.index_range(), 4096, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
SET_FLAG_FROM_TEST(polys[i].flag_legacy, !sharp_faces[i], ME_SMOOTH);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
for (const int i : polys.index_range()) {
|
||||
polys[i].flag_legacy |= ME_SMOOTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_mesh_legacy_sharp_faces_from_flags(Mesh *mesh)
|
||||
{
|
||||
using namespace blender;
|
||||
using namespace blender::bke;
|
||||
const Span<MPoly> polys = mesh->polys();
|
||||
MutableAttributeAccessor attributes = mesh->attributes_for_write();
|
||||
if (attributes.contains("sharp_face")) {
|
||||
return;
|
||||
}
|
||||
if (std::any_of(polys.begin(), polys.end(), [](const MPoly &poly) {
|
||||
return !(poly.flag_legacy & ME_SMOOTH);
|
||||
})) {
|
||||
SpanAttributeWriter<bool> sharp_faces = attributes.lookup_or_add_for_write_only_span<bool>(
|
||||
"sharp_face", ATTR_DOMAIN_FACE);
|
||||
threading::parallel_for(polys.index_range(), 4096, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
sharp_faces.span[i] = !(polys[i].flag_legacy & ME_SMOOTH);
|
||||
}
|
||||
});
|
||||
sharp_faces.finish();
|
||||
}
|
||||
else {
|
||||
attributes.remove("sharp_face");
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Face Set Conversion
|
||||
* \{ */
|
||||
|
@ -1496,7 +1554,7 @@ void BKE_mesh_legacy_convert_hide_layers_to_flags(Mesh *mesh)
|
|||
".hide_poly", ATTR_DOMAIN_FACE, false);
|
||||
threading::parallel_for(polys.index_range(), 4096, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
SET_FLAG_FROM_TEST(polys[i].flag, hide_poly[i], ME_HIDE);
|
||||
SET_FLAG_FROM_TEST(polys[i].flag_legacy, hide_poly[i], ME_HIDE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1539,13 +1597,14 @@ void BKE_mesh_legacy_convert_flags_to_hide_layers(Mesh *mesh)
|
|||
}
|
||||
|
||||
const Span<MPoly> polys = mesh->polys();
|
||||
if (std::any_of(
|
||||
polys.begin(), polys.end(), [](const MPoly &poly) { return poly.flag & ME_HIDE; })) {
|
||||
if (std::any_of(polys.begin(), polys.end(), [](const MPoly &poly) {
|
||||
return poly.flag_legacy & ME_HIDE;
|
||||
})) {
|
||||
SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_only_span<bool>(
|
||||
".hide_poly", ATTR_DOMAIN_FACE);
|
||||
threading::parallel_for(polys.index_range(), 4096, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
hide_poly.span[i] = polys[i].flag & ME_HIDE;
|
||||
hide_poly.span[i] = polys[i].flag_legacy & ME_HIDE;
|
||||
}
|
||||
});
|
||||
hide_poly.finish();
|
||||
|
@ -1814,7 +1873,7 @@ void BKE_mesh_legacy_convert_selection_layers_to_flags(Mesh *mesh)
|
|||
".select_poly", ATTR_DOMAIN_FACE, false);
|
||||
threading::parallel_for(polys.index_range(), 4096, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
SET_FLAG_FROM_TEST(polys[i].flag, select_poly[i], ME_FACE_SEL);
|
||||
SET_FLAG_FROM_TEST(polys[i].flag_legacy, select_poly[i], ME_FACE_SEL);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1858,13 +1917,14 @@ void BKE_mesh_legacy_convert_flags_to_selection_layers(Mesh *mesh)
|
|||
}
|
||||
|
||||
const Span<MPoly> polys = mesh->polys();
|
||||
if (std::any_of(
|
||||
polys.begin(), polys.end(), [](const MPoly &poly) { return poly.flag & ME_FACE_SEL; })) {
|
||||
if (std::any_of(polys.begin(), polys.end(), [](const MPoly &poly) {
|
||||
return poly.flag_legacy & ME_FACE_SEL;
|
||||
})) {
|
||||
SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_only_span<bool>(
|
||||
".select_poly", ATTR_DOMAIN_FACE);
|
||||
threading::parallel_for(polys.index_range(), 4096, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
select_poly.span[i] = polys[i].flag & ME_FACE_SEL;
|
||||
select_poly.span[i] = polys[i].flag_legacy & ME_FACE_SEL;
|
||||
}
|
||||
});
|
||||
select_poly.finish();
|
||||
|
|
|
@ -845,11 +845,14 @@ int *BKE_mesh_calc_smoothgroups(const int totedge,
|
|||
const MLoop *mloop,
|
||||
const int totloop,
|
||||
const bool *sharp_edges,
|
||||
const bool *sharp_faces,
|
||||
int *r_totgroup,
|
||||
const bool use_bitflags)
|
||||
{
|
||||
int *poly_groups = nullptr;
|
||||
|
||||
auto poly_is_smooth = [&](const int i) { return !(sharp_faces && sharp_faces[i]); };
|
||||
|
||||
auto poly_is_island_boundary_smooth = [&](const int poly_index,
|
||||
const int /*loop_index*/,
|
||||
const int edge_index,
|
||||
|
@ -857,13 +860,13 @@ int *BKE_mesh_calc_smoothgroups(const int totedge,
|
|||
const MeshElemMap &edge_poly_map_elem) {
|
||||
/* Edge is sharp if one of its polys is flat, or edge itself is sharp,
|
||||
* or edge is not used by exactly two polygons. */
|
||||
if ((polys[poly_index].flag & ME_SMOOTH) && !(sharp_edges && sharp_edges[edge_index]) &&
|
||||
if ((poly_is_smooth(poly_index)) && !(sharp_edges && sharp_edges[edge_index]) &&
|
||||
(edge_user_count == 2)) {
|
||||
/* In that case, edge appears to be smooth, but we need to check its other poly too. */
|
||||
const int other_poly_index = (poly_index == edge_poly_map_elem.indices[0]) ?
|
||||
edge_poly_map_elem.indices[1] :
|
||||
edge_poly_map_elem.indices[0];
|
||||
return (polys[other_poly_index].flag & ME_SMOOTH) == 0;
|
||||
return !poly_is_smooth(other_poly_index);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
|
|
@ -389,6 +389,8 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
|||
|
||||
const bool *sharp_edges = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&result->edata, CD_PROP_BOOL, "sharp_edge"));
|
||||
const bool *sharp_faces = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&result->pdata, CD_PROP_BOOL, "sharp_face"));
|
||||
BKE_mesh_normals_loop_split(BKE_mesh_vert_positions(result),
|
||||
BKE_mesh_vert_normals_ensure(result),
|
||||
result->totvert,
|
||||
|
@ -403,6 +405,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
|||
true,
|
||||
result->smoothresh,
|
||||
sharp_edges,
|
||||
sharp_faces,
|
||||
nullptr,
|
||||
&lnors_spacearr,
|
||||
clnors);
|
||||
|
|
|
@ -786,6 +786,7 @@ static void mesh_edges_sharp_tag(const Span<MPoly> polys,
|
|||
const Span<MLoop> loops,
|
||||
const Span<int> loop_to_poly_map,
|
||||
const Span<float3> poly_normals,
|
||||
const Span<bool> sharp_faces,
|
||||
const Span<bool> sharp_edges,
|
||||
const bool check_angle,
|
||||
const float split_angle,
|
||||
|
@ -794,6 +795,9 @@ static void mesh_edges_sharp_tag(const Span<MPoly> polys,
|
|||
{
|
||||
using namespace blender;
|
||||
const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f;
|
||||
auto poly_is_smooth = [&](const int poly_i) {
|
||||
return sharp_faces.is_empty() || !sharp_faces[poly_i];
|
||||
};
|
||||
|
||||
for (const int poly_i : polys.index_range()) {
|
||||
const MPoly &poly = polys[poly_i];
|
||||
|
@ -808,7 +812,7 @@ static void mesh_edges_sharp_tag(const Span<MPoly> polys,
|
|||
/* 'Empty' edge until now, set e2l[0] (and e2l[1] to INDEX_UNSET to tag it as unset). */
|
||||
e2l[0] = loop_index;
|
||||
/* We have to check this here too, else we might miss some flat faces!!! */
|
||||
e2l[1] = (poly.flag & ME_SMOOTH) ? INDEX_UNSET : INDEX_INVALID;
|
||||
e2l[1] = (poly_is_smooth(poly_i)) ? INDEX_UNSET : INDEX_INVALID;
|
||||
}
|
||||
else if (e2l[1] == INDEX_UNSET) {
|
||||
const bool is_angle_sharp = (check_angle &&
|
||||
|
@ -820,7 +824,7 @@ static void mesh_edges_sharp_tag(const Span<MPoly> polys,
|
|||
* or both poly have opposed (flipped) normals, i.e. both loops on the same edge share the
|
||||
* same vertex, or angle between both its polys' normals is above split_angle value.
|
||||
*/
|
||||
if (!(poly.flag & ME_SMOOTH) || (!sharp_edges.is_empty() && sharp_edges[edge_i]) ||
|
||||
if (!poly_is_smooth(poly_i) || (!sharp_edges.is_empty() && sharp_edges[edge_i]) ||
|
||||
vert_i == loops[e2l[0]].v || is_angle_sharp) {
|
||||
/* NOTE: we are sure that loop != 0 here ;). */
|
||||
e2l[1] = INDEX_INVALID;
|
||||
|
@ -855,6 +859,7 @@ void BKE_edges_sharp_from_angle_set(const int numEdges,
|
|||
const int numLoops,
|
||||
const MPoly *polys,
|
||||
const float (*poly_normals)[3],
|
||||
const bool *sharp_faces,
|
||||
const int numPolys,
|
||||
const float split_angle,
|
||||
bool *sharp_edges)
|
||||
|
@ -877,6 +882,7 @@ void BKE_edges_sharp_from_angle_set(const int numEdges,
|
|||
{mloops, numLoops},
|
||||
loop_to_poly,
|
||||
{reinterpret_cast<const float3 *>(poly_normals), numPolys},
|
||||
Span<bool>(sharp_faces, sharp_faces ? numPolys : 0),
|
||||
Span<bool>(sharp_edges, numEdges),
|
||||
true,
|
||||
split_angle,
|
||||
|
@ -1442,6 +1448,7 @@ void BKE_mesh_normals_loop_split(const float (*vert_positions)[3],
|
|||
const bool use_split_normals,
|
||||
const float split_angle,
|
||||
const bool *sharp_edges,
|
||||
const bool *sharp_faces,
|
||||
const int *loop_to_poly_map,
|
||||
MLoopNorSpaceArray *r_lnors_spacearr,
|
||||
short (*clnors_data)[2])
|
||||
|
@ -1465,7 +1472,7 @@ void BKE_mesh_normals_loop_split(const float (*vert_positions)[3],
|
|||
const MPoly &poly = polys[poly_index];
|
||||
int ml_index = poly.loopstart;
|
||||
const int ml_index_end = ml_index + poly.totloop;
|
||||
const bool is_poly_flat = ((poly.flag & ME_SMOOTH) == 0);
|
||||
const bool is_poly_flat = sharp_faces && sharp_faces[poly_index];
|
||||
|
||||
for (; ml_index < ml_index_end; ml_index++) {
|
||||
if (is_poly_flat) {
|
||||
|
@ -1555,6 +1562,7 @@ void BKE_mesh_normals_loop_split(const float (*vert_positions)[3],
|
|||
loops,
|
||||
loop_to_poly,
|
||||
{reinterpret_cast<const float3 *>(poly_normals), numPolys},
|
||||
Span<bool>(sharp_faces, sharp_faces ? numPolys : 0),
|
||||
Span<bool>(sharp_edges, sharp_edges ? numEdges : 0),
|
||||
check_angle,
|
||||
split_angle,
|
||||
|
@ -1605,6 +1613,7 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
|
|||
const int numLoops,
|
||||
const MPoly *polys,
|
||||
const float (*poly_normals)[3],
|
||||
const bool *sharp_faces,
|
||||
const int numPolys,
|
||||
MutableSpan<bool> sharp_edges,
|
||||
short (*r_clnors_data)[2],
|
||||
|
@ -1646,6 +1655,7 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
|
|||
use_split_normals,
|
||||
split_angle,
|
||||
sharp_edges.data(),
|
||||
sharp_faces,
|
||||
loop_to_poly.data(),
|
||||
&lnors_spacearr,
|
||||
nullptr);
|
||||
|
@ -1774,6 +1784,7 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
|
|||
use_split_normals,
|
||||
split_angle,
|
||||
sharp_edges.data(),
|
||||
sharp_faces,
|
||||
loop_to_poly.data(),
|
||||
&lnors_spacearr,
|
||||
nullptr);
|
||||
|
@ -1848,6 +1859,7 @@ void BKE_mesh_normals_loop_custom_set(const float (*vert_positions)[3],
|
|||
const int numLoops,
|
||||
const MPoly *polys,
|
||||
const float (*poly_normals)[3],
|
||||
const bool *sharp_faces,
|
||||
const int numPolys,
|
||||
bool *sharp_edges,
|
||||
short (*r_clnors_data)[2])
|
||||
|
@ -1862,6 +1874,7 @@ void BKE_mesh_normals_loop_custom_set(const float (*vert_positions)[3],
|
|||
numLoops,
|
||||
polys,
|
||||
poly_normals,
|
||||
sharp_faces,
|
||||
numPolys,
|
||||
{sharp_edges, numEdges},
|
||||
r_clnors_data,
|
||||
|
@ -1878,6 +1891,7 @@ void BKE_mesh_normals_loop_custom_from_verts_set(const float (*vert_positions)[3
|
|||
const int numLoops,
|
||||
const MPoly *polys,
|
||||
const float (*poly_normals)[3],
|
||||
const bool *sharp_faces,
|
||||
const int numPolys,
|
||||
bool *sharp_edges,
|
||||
short (*r_clnors_data)[2])
|
||||
|
@ -1892,6 +1906,7 @@ void BKE_mesh_normals_loop_custom_from_verts_set(const float (*vert_positions)[3
|
|||
numLoops,
|
||||
polys,
|
||||
poly_normals,
|
||||
sharp_faces,
|
||||
numPolys,
|
||||
{sharp_edges, numEdges},
|
||||
r_clnors_data,
|
||||
|
@ -1921,7 +1936,8 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
|
|||
MutableAttributeAccessor attributes = mesh->attributes_for_write();
|
||||
SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_span<bool>(
|
||||
"sharp_edge", ATTR_DOMAIN_EDGE);
|
||||
|
||||
const bool *sharp_faces = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, "sharp_face"));
|
||||
mesh_normals_loop_custom_set(reinterpret_cast<const float(*)[3]>(positions.data()),
|
||||
BKE_mesh_vert_normals_ensure(mesh),
|
||||
positions.size(),
|
||||
|
@ -1932,6 +1948,7 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
|
|||
loops.size(),
|
||||
polys.data(),
|
||||
BKE_mesh_poly_normals_ensure(mesh),
|
||||
sharp_faces,
|
||||
polys.size(),
|
||||
sharp_edges.span,
|
||||
clnors,
|
||||
|
|
|
@ -1361,6 +1361,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
|||
if (dirty_nors_dst || do_loop_nors_dst) {
|
||||
const bool *sharp_edges = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&mesh_dst->edata, CD_PROP_BOOL, "sharp_edge"));
|
||||
const bool *sharp_faces = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&mesh_dst->pdata, CD_PROP_BOOL, "sharp_face"));
|
||||
BKE_mesh_normals_loop_split(vert_positions_dst,
|
||||
BKE_mesh_vert_normals_ensure(mesh_dst),
|
||||
numverts_dst,
|
||||
|
@ -1375,6 +1377,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
|||
use_split_nors_dst,
|
||||
split_angle_dst,
|
||||
sharp_edges,
|
||||
sharp_faces,
|
||||
nullptr,
|
||||
nullptr,
|
||||
custom_nors_dst);
|
||||
|
|
|
@ -240,7 +240,7 @@ struct SGLSLMeshToTangent {
|
|||
if (precomputedLoopNormals) {
|
||||
return mikk::float3(precomputedLoopNormals[loop_index]);
|
||||
}
|
||||
if ((polys[lt->poly].flag & ME_SMOOTH) == 0) { /* flat */
|
||||
if (sharp_faces && sharp_faces[lt->poly]) { /* flat */
|
||||
if (precomputedFaceNormals) {
|
||||
return mikk::float3(precomputedFaceNormals[lt->poly]);
|
||||
}
|
||||
|
@ -285,6 +285,7 @@ struct SGLSLMeshToTangent {
|
|||
const float (*vert_normals)[3];
|
||||
const float (*orco)[3];
|
||||
float (*tangent)[4]; /* destination */
|
||||
const bool *sharp_faces;
|
||||
int numTessFaces;
|
||||
|
||||
#ifdef USE_LOOPTRI_DETECT_QUADS
|
||||
|
@ -394,6 +395,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
|
|||
const MLoop *mloop,
|
||||
const MLoopTri *looptri,
|
||||
const uint looptri_len,
|
||||
const bool *sharp_faces,
|
||||
|
||||
CustomData *loopdata,
|
||||
bool calc_active_tangent,
|
||||
|
@ -498,6 +500,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
|
|||
mesh2tangent->polys = polys;
|
||||
mesh2tangent->mloop = mloop;
|
||||
mesh2tangent->looptri = looptri;
|
||||
mesh2tangent->sharp_faces = sharp_faces;
|
||||
/* NOTE: we assume we do have tessellated loop normals at this point
|
||||
* (in case it is object-enabled), have to check this is valid. */
|
||||
mesh2tangent->precomputedLoopNormals = loop_normals;
|
||||
|
@ -583,6 +586,8 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
|
|||
me_eval->loops().data(),
|
||||
looptris.data(),
|
||||
uint(looptris.size()),
|
||||
static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&me_eval->pdata, CD_PROP_BOOL, "sharp_face")),
|
||||
&me_eval->ldata,
|
||||
calc_active_tangent,
|
||||
tangent_names,
|
||||
|
|
|
@ -735,7 +735,7 @@ ModifierData *BKE_modifiers_get_virtual_modifierlist(const Object *ob,
|
|||
|
||||
Object *BKE_modifiers_is_deformed_by_armature(Object *ob)
|
||||
{
|
||||
if (ob->type == OB_GPENCIL) {
|
||||
if (ob->type == OB_GPENCIL_LEGACY) {
|
||||
GpencilVirtualModifierData gpencilvirtualModifierData;
|
||||
ArmatureGpencilModifierData *agmd = nullptr;
|
||||
GpencilModifierData *gmd = BKE_gpencil_modifiers_get_virtual_modifierlist(
|
||||
|
|
|
@ -23,6 +23,11 @@ static const aal::RelationsInNode &get_relations_in_node(const bNode &node, Reso
|
|||
{
|
||||
if (node.is_group()) {
|
||||
if (const bNodeTree *group = reinterpret_cast<const bNodeTree *>(node.id)) {
|
||||
/* Undefined tree types have no relations. */
|
||||
if (!ntreeIsRegistered(group)) {
|
||||
return scope.construct<aal::RelationsInNode>();
|
||||
}
|
||||
|
||||
BLI_assert(group->runtime->anonymous_attribute_relations);
|
||||
return *group->runtime->anonymous_attribute_relations;
|
||||
}
|
||||
|
|
|
@ -233,7 +233,7 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in
|
|||
BKE_object_facemap_copy_list(&ob_dst->fmaps, &ob_src->fmaps);
|
||||
BKE_constraints_copy_ex(&ob_dst->constraints, &ob_src->constraints, flag_subdata, true);
|
||||
|
||||
ob_dst->mode = ob_dst->type != OB_GPENCIL ? OB_MODE_OBJECT : ob_dst->mode;
|
||||
ob_dst->mode = ob_dst->type != OB_GPENCIL_LEGACY ? OB_MODE_OBJECT : ob_dst->mode;
|
||||
ob_dst->sculpt = nullptr;
|
||||
|
||||
if (ob_src->pd) {
|
||||
|
@ -1489,7 +1489,7 @@ static ParticleSystem *object_copy_modifier_particle_system_ensure(Main *bmain,
|
|||
bool BKE_object_copy_modifier(
|
||||
Main *bmain, Scene *scene, Object *ob_dst, const Object *ob_src, ModifierData *md_src)
|
||||
{
|
||||
BLI_assert(ob_dst->type != OB_GPENCIL);
|
||||
BLI_assert(ob_dst->type != OB_GPENCIL_LEGACY);
|
||||
|
||||
const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md_src->type);
|
||||
if (!object_modifier_type_copy_check((ModifierType)md_src->type)) {
|
||||
|
@ -1587,7 +1587,7 @@ bool BKE_object_copy_modifier(
|
|||
|
||||
bool BKE_object_copy_gpencil_modifier(struct Object *ob_dst, GpencilModifierData *gmd_src)
|
||||
{
|
||||
BLI_assert(ob_dst->type == OB_GPENCIL);
|
||||
BLI_assert(ob_dst->type == OB_GPENCIL_LEGACY);
|
||||
|
||||
GpencilModifierData *gmd_dst = BKE_gpencil_modifier_new(gmd_src->type);
|
||||
BLI_strncpy(gmd_dst->name, gmd_src->name, sizeof(gmd_dst->name));
|
||||
|
@ -1607,7 +1607,7 @@ bool BKE_object_modifier_stack_copy(Object *ob_dst,
|
|||
const bool do_copy_all,
|
||||
const int flag_subdata)
|
||||
{
|
||||
if ((ob_dst->type == OB_GPENCIL) != (ob_src->type == OB_GPENCIL)) {
|
||||
if ((ob_dst->type == OB_GPENCIL_LEGACY) != (ob_src->type == OB_GPENCIL_LEGACY)) {
|
||||
BLI_assert_msg(0,
|
||||
"Trying to copy a modifier stack between a GPencil object and another type.");
|
||||
return false;
|
||||
|
@ -1904,7 +1904,7 @@ bool BKE_object_is_in_editmode(const Object *ob)
|
|||
case OB_SURF:
|
||||
case OB_CURVES_LEGACY:
|
||||
return ((Curve *)ob->data)->editnurb != nullptr;
|
||||
case OB_GPENCIL:
|
||||
case OB_GPENCIL_LEGACY:
|
||||
/* Grease Pencil object has no edit mode data. */
|
||||
return GPENCIL_EDIT_MODE((bGPdata *)ob->data);
|
||||
case OB_CURVES:
|
||||
|
@ -2131,7 +2131,7 @@ static const char *get_obdata_defname(int type)
|
|||
return DATA_("Volume");
|
||||
case OB_EMPTY:
|
||||
return DATA_("Empty");
|
||||
case OB_GPENCIL:
|
||||
case OB_GPENCIL_LEGACY:
|
||||
return DATA_("GPencil");
|
||||
case OB_LIGHTPROBE:
|
||||
return DATA_("LightProbe");
|
||||
|
@ -2156,7 +2156,7 @@ static void object_init(Object *ob, const short ob_type)
|
|||
ob->upflag = OB_POSY;
|
||||
}
|
||||
|
||||
if (ob->type == OB_GPENCIL) {
|
||||
if (ob->type == OB_GPENCIL_LEGACY) {
|
||||
ob->dtx |= OB_USE_GPENCIL_LIGHTS;
|
||||
}
|
||||
|
||||
|
@ -2196,7 +2196,7 @@ void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
|
|||
return BKE_speaker_add(bmain, name);
|
||||
case OB_LIGHTPROBE:
|
||||
return BKE_lightprobe_add(bmain, name);
|
||||
case OB_GPENCIL:
|
||||
case OB_GPENCIL_LEGACY:
|
||||
return BKE_gpencil_data_addnew(bmain, name);
|
||||
case OB_CURVES:
|
||||
return BKE_curves_add(bmain, name);
|
||||
|
@ -2230,8 +2230,8 @@ int BKE_object_obdata_to_type(const ID *id)
|
|||
return OB_CAMERA;
|
||||
case ID_LT:
|
||||
return OB_LATTICE;
|
||||
case ID_GD:
|
||||
return OB_GPENCIL;
|
||||
case ID_GD_LEGACY:
|
||||
return OB_GPENCIL_LEGACY;
|
||||
case ID_AR:
|
||||
return OB_ARMATURE;
|
||||
case ID_LP:
|
||||
|
@ -2558,7 +2558,7 @@ Object *BKE_object_pose_armature_get_with_wpaint_check(Object *ob)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case OB_GPENCIL: {
|
||||
case OB_GPENCIL_LEGACY: {
|
||||
if ((ob->mode & OB_MODE_WEIGHT_GPENCIL) == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -2794,7 +2794,7 @@ Object *BKE_object_duplicate(Main *bmain, Object *ob, uint dupflag, uint duplica
|
|||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
||||
}
|
||||
break;
|
||||
case OB_GPENCIL:
|
||||
case OB_GPENCIL_LEGACY:
|
||||
if (dupflag & USER_DUP_GPENCIL) {
|
||||
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
|
||||
}
|
||||
|
@ -3737,7 +3737,7 @@ const BoundBox *BKE_object_boundbox_get(Object *ob)
|
|||
case OB_ARMATURE:
|
||||
bb = BKE_armature_boundbox_get(ob);
|
||||
break;
|
||||
case OB_GPENCIL:
|
||||
case OB_GPENCIL_LEGACY:
|
||||
bb = BKE_gpencil_boundbox_get(ob);
|
||||
break;
|
||||
case OB_CURVES:
|
||||
|
@ -3889,7 +3889,7 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us
|
|||
changed = true;
|
||||
break;
|
||||
}
|
||||
case OB_GPENCIL: {
|
||||
case OB_GPENCIL_LEGACY: {
|
||||
const BoundBox bb = *BKE_gpencil_boundbox_get(ob);
|
||||
BKE_boundbox_minmax(&bb, ob->object_to_world, r_min, r_max);
|
||||
changed = true;
|
||||
|
@ -4190,7 +4190,7 @@ void BKE_object_foreach_display_point(Object *ob,
|
|||
func_cb(co, user_data);
|
||||
}
|
||||
}
|
||||
else if (ob->type == OB_GPENCIL) {
|
||||
else if (ob->type == OB_GPENCIL_LEGACY) {
|
||||
GPencilStrokePointIterData iter_data{};
|
||||
iter_data.obmat = obmat;
|
||||
iter_data.point_func_cb = func_cb;
|
||||
|
@ -5118,7 +5118,7 @@ bool BKE_object_supports_material_slots(struct Object *ob)
|
|||
OB_CURVES,
|
||||
OB_POINTCLOUD,
|
||||
OB_VOLUME,
|
||||
OB_GPENCIL);
|
||||
OB_GPENCIL_LEGACY);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -366,7 +366,7 @@ static void object_defgroup_remove_edit_mode(Object *ob, bDeformGroup *dg)
|
|||
|
||||
void BKE_object_defgroup_remove(Object *ob, bDeformGroup *defgroup)
|
||||
{
|
||||
if (ob->type == OB_GPENCIL) {
|
||||
if (ob->type == OB_GPENCIL_LEGACY) {
|
||||
BKE_gpencil_vgroup_remove(ob, defgroup);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -181,7 +181,7 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
|
|||
case OB_LATTICE:
|
||||
BKE_lattice_modifiers_calc(depsgraph, scene, ob);
|
||||
break;
|
||||
case OB_GPENCIL: {
|
||||
case OB_GPENCIL_LEGACY: {
|
||||
BKE_gpencil_prepare_eval_data(depsgraph, scene, ob);
|
||||
BKE_gpencil_modifiers_calc(depsgraph, scene, ob);
|
||||
BKE_gpencil_update_layer_transforms(depsgraph, ob);
|
||||
|
@ -303,7 +303,7 @@ void BKE_object_batch_cache_dirty_tag(Object *ob)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case OB_GPENCIL:
|
||||
case OB_GPENCIL_LEGACY:
|
||||
BKE_gpencil_batch_cache_dirty_tag((struct bGPdata *)ob->data);
|
||||
break;
|
||||
case OB_CURVES:
|
||||
|
|
|
@ -151,19 +151,27 @@ static void update_node_vb(PBVH *pbvh, PBVHNode *node)
|
|||
// BB_expand(&node->vb, co);
|
||||
//}
|
||||
|
||||
static bool face_materials_match(const PBVH *pbvh, const int a, const int b)
|
||||
static bool face_materials_match(const PBVH *pbvh,
|
||||
const bool *sharp_faces,
|
||||
const int a,
|
||||
const int b)
|
||||
{
|
||||
if (pbvh->material_indices) {
|
||||
if (pbvh->material_indices[a] != pbvh->material_indices[b]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return (pbvh->polys[a].flag & ME_SMOOTH) == (pbvh->polys[b].flag & ME_SMOOTH);
|
||||
if (sharp_faces) {
|
||||
if (sharp_faces[a] != sharp_faces[b]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool grid_materials_match(const DMFlagMat *f1, const DMFlagMat *f2)
|
||||
{
|
||||
return ((f1->flag & ME_SMOOTH) == (f2->flag & ME_SMOOTH) && (f1->mat_nr == f2->mat_nr));
|
||||
return (f1->sharp == f2->sharp) && (f1->mat_nr == f2->mat_nr);
|
||||
}
|
||||
|
||||
/* Adapted from BLI_kdopbvh.c */
|
||||
|
@ -229,7 +237,7 @@ static int partition_indices_grids(int *prim_indices,
|
|||
}
|
||||
|
||||
/* Returns the index of the first element on the right of the partition */
|
||||
static int partition_indices_material(PBVH *pbvh, int lo, int hi)
|
||||
static int partition_indices_material(PBVH *pbvh, const bool *sharp_faces, int lo, int hi)
|
||||
{
|
||||
const MLoopTri *looptri = pbvh->looptri;
|
||||
const DMFlagMat *flagmats = pbvh->grid_flag_mats;
|
||||
|
@ -239,10 +247,10 @@ static int partition_indices_material(PBVH *pbvh, int lo, int hi)
|
|||
for (;;) {
|
||||
if (pbvh->looptri) {
|
||||
const int first = looptri[pbvh->prim_indices[lo]].poly;
|
||||
for (; face_materials_match(pbvh, first, looptri[indices[i]].poly); i++) {
|
||||
for (; face_materials_match(pbvh, sharp_faces, first, looptri[indices[i]].poly); i++) {
|
||||
/* pass */
|
||||
}
|
||||
for (; !face_materials_match(pbvh, first, looptri[indices[j]].poly); j--) {
|
||||
for (; !face_materials_match(pbvh, sharp_faces, first, looptri[indices[j]].poly); j--) {
|
||||
/* pass */
|
||||
}
|
||||
}
|
||||
|
@ -450,7 +458,7 @@ static void build_leaf(PBVH *pbvh, int node_index, BBC *prim_bbc, int offset, in
|
|||
|
||||
/* Return zero if all primitives in the node can be drawn with the
|
||||
* same material (including flat/smooth shading), non-zero otherwise */
|
||||
static bool leaf_needs_material_split(PBVH *pbvh, int offset, int count)
|
||||
static bool leaf_needs_material_split(PBVH *pbvh, const bool *sharp_faces, int offset, int count)
|
||||
{
|
||||
if (count <= 1) {
|
||||
return false;
|
||||
|
@ -460,7 +468,7 @@ static bool leaf_needs_material_split(PBVH *pbvh, int offset, int count)
|
|||
const MLoopTri *first = &pbvh->looptri[pbvh->prim_indices[offset]];
|
||||
for (int i = offset + count - 1; i > offset; i--) {
|
||||
int prim = pbvh->prim_indices[i];
|
||||
if (!face_materials_match(pbvh, first->poly, pbvh->looptri[prim].poly)) {
|
||||
if (!face_materials_match(pbvh, sharp_faces, first->poly, pbvh->looptri[prim].poly)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -539,6 +547,7 @@ static void test_face_boundaries(PBVH *pbvh)
|
|||
*/
|
||||
|
||||
static void build_sub(PBVH *pbvh,
|
||||
const bool *sharp_faces,
|
||||
int node_index,
|
||||
BB *cb,
|
||||
BBC *prim_bbc,
|
||||
|
@ -557,7 +566,7 @@ static void build_sub(PBVH *pbvh,
|
|||
/* Decide whether this is a leaf or not */
|
||||
const bool below_leaf_limit = count <= pbvh->leaf_limit || depth >= STACK_FIXED_DEPTH - 1;
|
||||
if (below_leaf_limit) {
|
||||
if (!leaf_needs_material_split(pbvh, offset, count)) {
|
||||
if (!leaf_needs_material_split(pbvh, sharp_faces, offset, count)) {
|
||||
build_leaf(pbvh, node_index, prim_bbc, offset, count);
|
||||
|
||||
if (node_index == 0) {
|
||||
|
@ -610,11 +619,12 @@ static void build_sub(PBVH *pbvh,
|
|||
}
|
||||
else {
|
||||
/* Partition primitives by material */
|
||||
end = partition_indices_material(pbvh, offset, offset + count - 1);
|
||||
end = partition_indices_material(pbvh, sharp_faces, offset, offset + count - 1);
|
||||
}
|
||||
|
||||
/* Build children */
|
||||
build_sub(pbvh,
|
||||
sharp_faces,
|
||||
pbvh->nodes[node_index].children_offset,
|
||||
nullptr,
|
||||
prim_bbc,
|
||||
|
@ -623,6 +633,7 @@ static void build_sub(PBVH *pbvh,
|
|||
prim_scratch,
|
||||
depth + 1);
|
||||
build_sub(pbvh,
|
||||
sharp_faces,
|
||||
pbvh->nodes[node_index].children_offset + 1,
|
||||
nullptr,
|
||||
prim_bbc,
|
||||
|
@ -636,7 +647,7 @@ static void build_sub(PBVH *pbvh,
|
|||
}
|
||||
}
|
||||
|
||||
static void pbvh_build(PBVH *pbvh, BB *cb, BBC *prim_bbc, int totprim)
|
||||
static void pbvh_build(PBVH *pbvh, const bool *sharp_faces, BB *cb, BBC *prim_bbc, int totprim)
|
||||
{
|
||||
if (totprim != pbvh->totprim) {
|
||||
pbvh->totprim = totprim;
|
||||
|
@ -659,7 +670,7 @@ static void pbvh_build(PBVH *pbvh, BB *cb, BBC *prim_bbc, int totprim)
|
|||
}
|
||||
|
||||
pbvh->totnode = 1;
|
||||
build_sub(pbvh, 0, cb, prim_bbc, 0, totprim, nullptr, 0);
|
||||
build_sub(pbvh, sharp_faces, 0, cb, prim_bbc, 0, totprim, nullptr, 0);
|
||||
}
|
||||
|
||||
static void pbvh_draw_args_init(PBVH *pbvh, PBVH_GPU_Args *args, PBVHNode *node)
|
||||
|
@ -881,7 +892,9 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
|
|||
}
|
||||
|
||||
if (looptri_num) {
|
||||
pbvh_build(pbvh, &cb, prim_bbc, looptri_num);
|
||||
const bool *sharp_faces = (const bool *)CustomData_get_layer_named(
|
||||
&mesh->pdata, CD_PROP_BOOL, "sharp_face");
|
||||
pbvh_build(pbvh, sharp_faces, &cb, prim_bbc, looptri_num);
|
||||
|
||||
#ifdef TEST_PBVH_FACE_SPLIT
|
||||
test_face_boundaries(pbvh);
|
||||
|
@ -968,7 +981,9 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
|
|||
}
|
||||
|
||||
if (totgrid) {
|
||||
pbvh_build(pbvh, &cb, prim_bbc, totgrid);
|
||||
const bool *sharp_faces = (const bool *)CustomData_get_layer_named(
|
||||
&me->pdata, CD_PROP_BOOL, "sharp_face");
|
||||
pbvh_build(pbvh, sharp_faces, &cb, prim_bbc, totgrid);
|
||||
|
||||
#ifdef TEST_PBVH_FACE_SPLIT
|
||||
test_face_boundaries(pbvh);
|
||||
|
|
|
@ -116,6 +116,8 @@ bool BKE_shrinkwrap_init_tree(
|
|||
data->mesh = mesh;
|
||||
data->polys = mesh->polys().data();
|
||||
data->vert_normals = BKE_mesh_vert_normals_ensure(mesh);
|
||||
data->sharp_faces = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_face"));
|
||||
|
||||
if (shrinkType == MOD_SHRINKWRAP_NEAREST_VERTEX) {
|
||||
data->bvh = BKE_bvhtree_from_mesh_get(&data->treeData, mesh, BVHTREE_FROM_VERTS, 2);
|
||||
|
@ -1175,7 +1177,7 @@ void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree,
|
|||
const float(*vert_normals)[3] = tree->vert_normals;
|
||||
|
||||
/* Interpolate smooth normals if enabled. */
|
||||
if ((tree->polys[tri->poly].flag & ME_SMOOTH) != 0) {
|
||||
if (!(tree->sharp_faces && tree->sharp_faces[tri->poly])) {
|
||||
const uint32_t vert_indices[3] = {treeData->loop[tri->tri[0]].v,
|
||||
treeData->loop[tri->tri[1]].v,
|
||||
treeData->loop[tri->tri[2]].v};
|
||||
|
|
|
@ -48,9 +48,9 @@ static int last_studiolight_id = 0;
|
|||
*/
|
||||
#define STUDIOLIGHT_LOAD_CACHED_FILES
|
||||
|
||||
static const char *STUDIOLIGHT_LIGHTS_FOLDER = "studiolights/studio/";
|
||||
static const char *STUDIOLIGHT_WORLD_FOLDER = "studiolights/world/";
|
||||
static const char *STUDIOLIGHT_MATCAP_FOLDER = "studiolights/matcap/";
|
||||
static const char *STUDIOLIGHT_LIGHTS_FOLDER = "studiolights" SEP_STR "studio" SEP_STR;
|
||||
static const char *STUDIOLIGHT_WORLD_FOLDER = "studiolights" SEP_STR "world" SEP_STR;
|
||||
static const char *STUDIOLIGHT_MATCAP_FOLDER = "studiolights" SEP_STR "matcap" SEP_STR;
|
||||
|
||||
static const char *STUDIOLIGHT_WORLD_DEFAULT = "forest.exr";
|
||||
static const char *STUDIOLIGHT_MATCAP_DEFAULT = "basic_1.exr";
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
struct CCGMaterialFromMeshData {
|
||||
const Mesh *mesh;
|
||||
blender::Span<MPoly> polys;
|
||||
const bool *sharp_faces;
|
||||
const int *material_indices;
|
||||
};
|
||||
|
||||
|
@ -24,9 +24,8 @@ static DMFlagMat subdiv_ccg_material_flags_eval(
|
|||
{
|
||||
CCGMaterialFromMeshData *data = (CCGMaterialFromMeshData *)material_flags_evaluator->user_data;
|
||||
BLI_assert(coarse_face_index < data->mesh->totpoly);
|
||||
const MPoly &poly = data->polys[coarse_face_index];
|
||||
DMFlagMat material_flags;
|
||||
material_flags.flag = poly.flag;
|
||||
material_flags.sharp = data->sharp_faces && data->sharp_faces[coarse_face_index];
|
||||
material_flags.mat_nr = data->material_indices ? data->material_indices[coarse_face_index] : 0;
|
||||
return material_flags;
|
||||
}
|
||||
|
@ -45,7 +44,8 @@ void BKE_subdiv_ccg_material_flags_init_from_mesh(
|
|||
data->mesh = mesh;
|
||||
data->material_indices = (const int *)CustomData_get_layer_named(
|
||||
&mesh->pdata, CD_PROP_INT32, "material_index");
|
||||
data->polys = mesh->polys();
|
||||
data->sharp_faces = (const bool *)CustomData_get_layer_named(
|
||||
&mesh->pdata, CD_PROP_BOOL, "sharp_face");
|
||||
material_flags_evaluator->eval_material_flags = subdiv_ccg_material_flags_eval;
|
||||
material_flags_evaluator->free = subdiv_ccg_material_flags_free;
|
||||
material_flags_evaluator->user_data = data;
|
||||
|
|
|
@ -1068,20 +1068,17 @@ static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, MPoly *polys)
|
|||
int gridSize = ccgSubSurf_getGridSize(ss);
|
||||
/* int edgeSize = ccgSubSurf_getEdgeSize(ss); */ /* UNUSED */
|
||||
int i = 0, k = 0;
|
||||
DMFlagMat *faceFlags = ccgdm->faceFlags;
|
||||
|
||||
totface = ccgSubSurf_getNumFaces(ss);
|
||||
for (index = 0; index < totface; index++) {
|
||||
CCGFace *f = ccgdm->faceMap[index].face;
|
||||
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
||||
char flag = (faceFlags) ? faceFlags[index].flag : char(ME_SMOOTH);
|
||||
|
||||
for (S = 0; S < numVerts; S++) {
|
||||
for (y = 0; y < gridSize - 1; y++) {
|
||||
for (x = 0; x < gridSize - 1; x++) {
|
||||
polys[i].loopstart = k;
|
||||
polys[i].totloop = 4;
|
||||
polys[i].flag = flag;
|
||||
|
||||
k += 4;
|
||||
i++;
|
||||
|
@ -1541,9 +1538,11 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
|
|||
gridSideEdges = gridSize - 1;
|
||||
gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
|
||||
|
||||
const MPoly *polys = static_cast<const MPoly *>(CustomData_get_layer(&dm->polyData, CD_MPOLY));
|
||||
const int *material_indices = static_cast<const int *>(
|
||||
CustomData_get_layer_named(&dm->polyData, CD_MPOLY, "material_index"));
|
||||
const bool *sharp_faces = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&dm->polyData, CD_PROP_BOOL, "sharp_face"));
|
||||
|
||||
const int *base_polyOrigIndex = static_cast<const int *>(
|
||||
CustomData_get_layer(&dm->polyData, CD_ORIGINDEX));
|
||||
|
||||
|
@ -1569,7 +1568,7 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
|
|||
ccgdm->faceMap[index].startEdge = edgeNum;
|
||||
ccgdm->faceMap[index].startFace = faceNum;
|
||||
|
||||
faceFlags->flag = polys ? polys[origIndex].flag : 0;
|
||||
faceFlags->sharp = sharp_faces ? sharp_faces[origIndex] : false;
|
||||
faceFlags->mat_nr = material_indices ? material_indices[origIndex] : 0;
|
||||
faceFlags++;
|
||||
|
||||
|
|
|
@ -180,6 +180,7 @@ Mesh *volume_to_mesh(const openvdb::GridBase &grid,
|
|||
mesh->loops_for_write());
|
||||
|
||||
BKE_mesh_calc_edges(mesh, false, false);
|
||||
BKE_mesh_smooth_flag_set(mesh, false);
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
|
|
@ -79,6 +79,9 @@ template<typename T> uint64_t vector_hash(const T &vec)
|
|||
|
||||
template<typename T, int Size> struct VecBase : public vec_struct_base<T, Size> {
|
||||
|
||||
BLI_STATIC_ASSERT(alignof(T) <= sizeof(T),
|
||||
"VecBase is not compatible with aligned type for now.");
|
||||
|
||||
static constexpr int type_length = Size;
|
||||
|
||||
using base_type = T;
|
||||
|
@ -176,16 +179,36 @@ template<typename T, int Size> struct VecBase : public vec_struct_base<T, Size>
|
|||
|
||||
/** Swizzling. */
|
||||
|
||||
template<BLI_ENABLE_IF_VEC(Size, >= 3)> VecBase<T, 2> xy() const
|
||||
template<BLI_ENABLE_IF_VEC(Size, >= 2)> VecBase<T, 2> xy() const
|
||||
{
|
||||
return *reinterpret_cast<const VecBase<T, 2> *>(this);
|
||||
}
|
||||
|
||||
template<BLI_ENABLE_IF_VEC(Size, >= 4)> VecBase<T, 3> xyz() const
|
||||
template<BLI_ENABLE_IF_VEC(Size, >= 3)> VecBase<T, 2> yz() const
|
||||
{
|
||||
return *reinterpret_cast<const VecBase<T, 2> *>(&((*this)[1]));
|
||||
}
|
||||
|
||||
template<BLI_ENABLE_IF_VEC(Size, >= 4)> VecBase<T, 2> zw() const
|
||||
{
|
||||
return *reinterpret_cast<const VecBase<T, 2> *>(&((*this)[2]));
|
||||
}
|
||||
|
||||
template<BLI_ENABLE_IF_VEC(Size, >= 3)> VecBase<T, 3> xyz() const
|
||||
{
|
||||
return *reinterpret_cast<const VecBase<T, 3> *>(this);
|
||||
}
|
||||
|
||||
template<BLI_ENABLE_IF_VEC(Size, >= 4)> VecBase<T, 3> yzw() const
|
||||
{
|
||||
return *reinterpret_cast<const VecBase<T, 3> *>(&((*this)[1]));
|
||||
}
|
||||
|
||||
template<BLI_ENABLE_IF_VEC(Size, >= 4)> VecBase<T, 4> xyzw() const
|
||||
{
|
||||
return *reinterpret_cast<const VecBase<T, 4> *>(this);
|
||||
}
|
||||
|
||||
#undef BLI_ENABLE_IF_VEC
|
||||
|
||||
/** Conversion from pointers (from C-style vectors). */
|
||||
|
|
|
@ -272,6 +272,7 @@ void BLI_filelist_entry_mode_to_string(const struct stat *st,
|
|||
const char *types[8] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"};
|
||||
|
||||
#ifdef WIN32
|
||||
UNUSED_VARS(st);
|
||||
BLI_strncpy(r_mode1, types[0], sizeof(*r_mode1) * FILELIST_DIRENTRY_MODE_LEN);
|
||||
BLI_strncpy(r_mode2, types[0], sizeof(*r_mode2) * FILELIST_DIRENTRY_MODE_LEN);
|
||||
BLI_strncpy(r_mode3, types[0], sizeof(*r_mode3) * FILELIST_DIRENTRY_MODE_LEN);
|
||||
|
@ -315,6 +316,7 @@ void BLI_filelist_entry_owner_to_string(const struct stat *st,
|
|||
char r_owner[FILELIST_DIRENTRY_OWNER_LEN])
|
||||
{
|
||||
#ifdef WIN32
|
||||
UNUSED_VARS(st);
|
||||
strcpy(r_owner, "unknown");
|
||||
#else
|
||||
struct passwd *pwuser = getpwuid(st->st_uid);
|
||||
|
|
|
@ -259,4 +259,25 @@ TEST(math_vec_types, DivideFloatByVectorSmall)
|
|||
EXPECT_FLOAT_EQ(result.y, 1.0f);
|
||||
}
|
||||
|
||||
TEST(math_vec_types, SwizzleReinterpret)
|
||||
{
|
||||
const float2 v01(0, 1);
|
||||
const float2 v12(1, 2);
|
||||
const float2 v23(2, 3);
|
||||
const float3 v012(0, 1, 2);
|
||||
const float3 v123(1, 2, 3);
|
||||
const float4 v0123(0, 1, 2, 3);
|
||||
/* Identity. */
|
||||
EXPECT_EQ(v01.xy(), v01);
|
||||
EXPECT_EQ(v012.xyz(), v012);
|
||||
EXPECT_EQ(v0123.xyzw(), v0123);
|
||||
/* Masking. */
|
||||
EXPECT_EQ(v012.xy(), v01);
|
||||
EXPECT_EQ(v0123.xyz(), v012);
|
||||
/* Offset. */
|
||||
EXPECT_EQ(v0123.yz(), v12);
|
||||
EXPECT_EQ(v0123.zw(), v23);
|
||||
EXPECT_EQ(v0123.yzw(), v123);
|
||||
}
|
||||
|
||||
} // namespace blender::tests
|
||||
|
|
|
@ -2963,7 +2963,7 @@ static const char *dataname(short id_code)
|
|||
return "Data from PAL";
|
||||
case ID_PC:
|
||||
return "Data from PCRV";
|
||||
case ID_GD:
|
||||
case ID_GD_LEGACY:
|
||||
return "Data from GD";
|
||||
case ID_WM:
|
||||
return "Data from WM";
|
||||
|
|
|
@ -431,7 +431,7 @@ static void versions_gpencil_add_main(Main *bmain, ListBase *lb, ID *id, const c
|
|||
BLI_addtail(lb, id);
|
||||
id->us = 1;
|
||||
id->flag = LIB_FAKEUSER;
|
||||
*((short *)id->name) = ID_GD;
|
||||
*((short *)id->name) = ID_GD_LEGACY;
|
||||
|
||||
BKE_id_new_name_validate(bmain, lb, id, name, false);
|
||||
/* alphabetic insertion: is in BKE_id_new_name_validate */
|
||||
|
|
|
@ -4665,7 +4665,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
|
||||
/* Fix Grease Pencil VFX and modifiers. */
|
||||
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
|
||||
if (ob->type != OB_GPENCIL) {
|
||||
if (ob->type != OB_GPENCIL_LEGACY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -553,7 +553,7 @@ void do_versions_after_linking_290(FileData * /*fd*/, Main *bmain)
|
|||
Scene *scene = static_cast<Scene *>(bmain->scenes.first);
|
||||
if (scene != nullptr) {
|
||||
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
|
||||
if (ob->type != OB_GPENCIL) {
|
||||
if (ob->type != OB_GPENCIL_LEGACY) {
|
||||
continue;
|
||||
}
|
||||
bGPdata *gpd = static_cast<bGPdata *>(ob->data);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_multi_value_map.hh"
|
||||
#include "BLI_path_util.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_utils.h"
|
||||
|
@ -385,7 +386,7 @@ static void assert_sorted_ids(Main *bmain)
|
|||
static void move_vertex_group_names_to_object_data(Main *bmain)
|
||||
{
|
||||
LISTBASE_FOREACH (Object *, object, &bmain->objects) {
|
||||
if (ELEM(object->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) {
|
||||
if (ELEM(object->type, OB_MESH, OB_LATTICE, OB_GPENCIL_LEGACY)) {
|
||||
ListBase *new_defbase = BKE_object_defgroup_list_mutable(object);
|
||||
|
||||
/* Choose the longest vertex group name list among all linked duplicates. */
|
||||
|
@ -940,6 +941,139 @@ static void version_geometry_nodes_primitive_uv_maps(bNodeTree &ntree)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When extruding from loose edges, the extrude geometry node used to create flat faces due to the
|
||||
* default of the old "shade_smooth" attribute. Since the "false" value has changed with the
|
||||
* "sharp_face" attribute, add nodes to propagate the new attribute in its inverted "smooth" form.
|
||||
*/
|
||||
static void version_geometry_nodes_extrude_smooth_propagation(bNodeTree &ntree)
|
||||
{
|
||||
using namespace blender;
|
||||
Vector<bNode *> new_nodes;
|
||||
LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree.nodes) {
|
||||
if (node->idname != StringRef("GeometryNodeExtrudeMesh")) {
|
||||
continue;
|
||||
}
|
||||
if (static_cast<const NodeGeometryExtrudeMesh *>(node->storage)->mode !=
|
||||
GEO_NODE_EXTRUDE_MESH_EDGES) {
|
||||
continue;
|
||||
}
|
||||
bNodeSocket *geometry_in_socket = nodeFindSocket(node, SOCK_IN, "Mesh");
|
||||
bNodeSocket *geometry_out_socket = nodeFindSocket(node, SOCK_OUT, "Mesh");
|
||||
|
||||
Map<bNodeSocket *, bNodeLink *> in_links_per_socket;
|
||||
MultiValueMap<bNodeSocket *, bNodeLink *> out_links_per_socket;
|
||||
LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) {
|
||||
in_links_per_socket.add(link->tosock, link);
|
||||
out_links_per_socket.add(link->fromsock, link);
|
||||
}
|
||||
|
||||
bNodeLink *geometry_in_link = in_links_per_socket.lookup_default(geometry_in_socket, nullptr);
|
||||
Span<bNodeLink *> geometry_out_links = out_links_per_socket.lookup(geometry_out_socket);
|
||||
if (!geometry_in_link || geometry_out_links.is_empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool versioning_already_done = [&]() {
|
||||
if (geometry_in_link->fromnode->idname != StringRef("GeometryNodeCaptureAttribute")) {
|
||||
return false;
|
||||
}
|
||||
bNode *capture_node = geometry_in_link->fromnode;
|
||||
const NodeGeometryAttributeCapture &capture_storage =
|
||||
*static_cast<const NodeGeometryAttributeCapture *>(capture_node->storage);
|
||||
if (capture_storage.data_type != CD_PROP_BOOL ||
|
||||
capture_storage.domain != ATTR_DOMAIN_FACE) {
|
||||
return false;
|
||||
}
|
||||
bNodeSocket *capture_in_socket = nodeFindSocket(capture_node, SOCK_IN, "Value_003");
|
||||
bNodeLink *capture_in_link = in_links_per_socket.lookup_default(capture_in_socket, nullptr);
|
||||
if (!capture_in_link) {
|
||||
return false;
|
||||
}
|
||||
if (capture_in_link->fromnode->idname != StringRef("GeometryNodeInputShadeSmooth")) {
|
||||
return false;
|
||||
}
|
||||
if (geometry_out_links.size() != 1) {
|
||||
return false;
|
||||
}
|
||||
bNodeLink *geometry_out_link = geometry_out_links.first();
|
||||
if (geometry_out_link->tonode->idname != StringRef("GeometryNodeSetShadeSmooth")) {
|
||||
return false;
|
||||
}
|
||||
bNode *set_smooth_node = geometry_out_link->tonode;
|
||||
bNodeSocket *smooth_in_socket = nodeFindSocket(set_smooth_node, SOCK_IN, "Shade Smooth");
|
||||
bNodeLink *connecting_link = in_links_per_socket.lookup_default(smooth_in_socket, nullptr);
|
||||
if (!connecting_link) {
|
||||
return false;
|
||||
}
|
||||
if (connecting_link->fromnode != capture_node) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}();
|
||||
if (versioning_already_done) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bNode *capture_node = nodeAddNode(nullptr, &ntree, "GeometryNodeCaptureAttribute");
|
||||
capture_node->parent = node->parent;
|
||||
capture_node->locx = node->locx - 25;
|
||||
capture_node->locy = node->locy;
|
||||
new_nodes.append(capture_node);
|
||||
static_cast<NodeGeometryAttributeCapture *>(capture_node->storage)->data_type = CD_PROP_BOOL;
|
||||
static_cast<NodeGeometryAttributeCapture *>(capture_node->storage)->domain = ATTR_DOMAIN_FACE;
|
||||
|
||||
bNode *is_smooth_node = nodeAddNode(nullptr, &ntree, "GeometryNodeInputShadeSmooth");
|
||||
is_smooth_node->parent = node->parent;
|
||||
is_smooth_node->locx = capture_node->locx - 25;
|
||||
is_smooth_node->locy = capture_node->locy;
|
||||
new_nodes.append(is_smooth_node);
|
||||
nodeAddLink(&ntree,
|
||||
is_smooth_node,
|
||||
nodeFindSocket(is_smooth_node, SOCK_OUT, "Smooth"),
|
||||
capture_node,
|
||||
nodeFindSocket(capture_node, SOCK_IN, "Value_003"));
|
||||
nodeAddLink(&ntree,
|
||||
capture_node,
|
||||
nodeFindSocket(capture_node, SOCK_OUT, "Geometry"),
|
||||
capture_node,
|
||||
geometry_in_socket);
|
||||
geometry_in_link->tonode = capture_node;
|
||||
geometry_in_link->tosock = nodeFindSocket(capture_node, SOCK_IN, "Geometry");
|
||||
|
||||
bNode *set_smooth_node = nodeAddNode(nullptr, &ntree, "GeometryNodeSetShadeSmooth");
|
||||
set_smooth_node->parent = node->parent;
|
||||
set_smooth_node->locx = node->locx + 25;
|
||||
set_smooth_node->locy = node->locy;
|
||||
new_nodes.append(set_smooth_node);
|
||||
nodeAddLink(&ntree,
|
||||
node,
|
||||
geometry_out_socket,
|
||||
set_smooth_node,
|
||||
nodeFindSocket(set_smooth_node, SOCK_IN, "Geometry"));
|
||||
|
||||
bNodeSocket *smooth_geometry_out = nodeFindSocket(set_smooth_node, SOCK_OUT, "Geometry");
|
||||
for (bNodeLink *link : geometry_out_links) {
|
||||
link->fromnode = set_smooth_node;
|
||||
link->fromsock = smooth_geometry_out;
|
||||
}
|
||||
nodeAddLink(&ntree,
|
||||
capture_node,
|
||||
nodeFindSocket(capture_node, SOCK_OUT, "Attribute_003"),
|
||||
set_smooth_node,
|
||||
nodeFindSocket(set_smooth_node, SOCK_IN, "Shade Smooth"));
|
||||
}
|
||||
|
||||
/* Move nodes to the front so that they are drawn behind existing nodes. */
|
||||
for (bNode *node : new_nodes) {
|
||||
BLI_remlink(&ntree.nodes, node);
|
||||
BLI_addhead(&ntree.nodes, node);
|
||||
}
|
||||
if (!new_nodes.is_empty()) {
|
||||
nodeRebuildIDVector(&ntree);
|
||||
}
|
||||
}
|
||||
|
||||
void do_versions_after_linking_300(FileData * /*fd*/, Main *bmain)
|
||||
{
|
||||
if (MAIN_VERSION_ATLEAST(bmain, 300, 0) && !MAIN_VERSION_ATLEAST(bmain, 300, 1)) {
|
||||
|
@ -1044,7 +1178,7 @@ void do_versions_after_linking_300(FileData * /*fd*/, Main *bmain)
|
|||
if (!MAIN_VERSION_ATLEAST(bmain, 300, 33)) {
|
||||
/* This was missing from #move_vertex_group_names_to_object_data. */
|
||||
LISTBASE_FOREACH (Object *, object, &bmain->objects) {
|
||||
if (ELEM(object->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) {
|
||||
if (ELEM(object->type, OB_MESH, OB_LATTICE, OB_GPENCIL_LEGACY)) {
|
||||
/* This uses the fact that the active vertex group index starts counting at 1. */
|
||||
if (BKE_object_defgroup_active_index_get(object) == 0) {
|
||||
BKE_object_defgroup_active_index_set(object, object->actdef);
|
||||
|
@ -2347,7 +2481,7 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (ob->type == OB_GPENCIL) {
|
||||
if (ob->type == OB_GPENCIL_LEGACY) {
|
||||
LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
|
||||
if (md->type == eGpencilModifierType_Lineart) {
|
||||
LineartGpencilModifierData *lmd = (LineartGpencilModifierData *)md;
|
||||
|
@ -2542,7 +2676,7 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
if (!DNA_struct_elem_find(
|
||||
fd->filesdna, "LineartGpencilModifierData", "bool", "use_crease_on_smooth")) {
|
||||
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
|
||||
if (ob->type == OB_GPENCIL) {
|
||||
if (ob->type == OB_GPENCIL_LEGACY) {
|
||||
LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
|
||||
if (md->type == eGpencilModifierType_Lineart) {
|
||||
LineartGpencilModifierData *lmd = (LineartGpencilModifierData *)md;
|
||||
|
@ -4047,5 +4181,10 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
}
|
||||
}
|
||||
/* Keep this block, even when empty. */
|
||||
LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
|
||||
if (ntree->type == NTREE_GEOMETRY) {
|
||||
version_geometry_nodes_extrude_smooth_propagation(*ntree);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ static void version_mesh_legacy_to_struct_of_array_format(Mesh &mesh)
|
|||
BKE_mesh_legacy_convert_flags_to_hide_layers(&mesh);
|
||||
BKE_mesh_legacy_convert_uvs_to_generic(&mesh);
|
||||
BKE_mesh_legacy_convert_mpoly_to_material_indices(&mesh);
|
||||
BKE_mesh_legacy_sharp_faces_from_flags(&mesh);
|
||||
BKE_mesh_legacy_bevel_weight_to_layers(&mesh);
|
||||
BKE_mesh_legacy_sharp_edges_from_flags(&mesh);
|
||||
BKE_mesh_legacy_face_set_to_generic(&mesh);
|
||||
|
|
|
@ -464,7 +464,7 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
|
|||
|
||||
Object *ob = static_cast<Object *>(
|
||||
BLI_findstring(&bmain->objects, "Stroke", offsetof(ID, name) + 2));
|
||||
if (ob && ob->type == OB_GPENCIL) {
|
||||
if (ob && ob->type == OB_GPENCIL_LEGACY) {
|
||||
ob->dtx |= OB_USE_GPENCIL_LIGHTS;
|
||||
}
|
||||
}
|
||||
|
@ -550,7 +550,7 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
|
|||
|
||||
if (app_template && STREQ(app_template, "2D_Animation")) {
|
||||
LISTBASE_FOREACH (Object *, object, &bmain->objects) {
|
||||
if (object->type == OB_GPENCIL) {
|
||||
if (object->type == OB_GPENCIL_LEGACY) {
|
||||
/* Set grease pencil object in drawing mode */
|
||||
bGPdata *gpd = (bGPdata *)object->data;
|
||||
object->mode = OB_MODE_PAINT_GPENCIL;
|
||||
|
|
|
@ -113,18 +113,6 @@ using blender::Span;
|
|||
using blender::StringRef;
|
||||
using blender::Vector;
|
||||
|
||||
static char bm_face_flag_from_mflag(const char mflag)
|
||||
{
|
||||
return ((mflag & ME_SMOOTH) ? BM_ELEM_SMOOTH : 0);
|
||||
}
|
||||
|
||||
static char bm_face_flag_to_mflag(const BMFace *f)
|
||||
{
|
||||
const char hflag = f->head.hflag;
|
||||
|
||||
return ((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH : 0);
|
||||
}
|
||||
|
||||
bool BM_attribute_stored_in_bmesh_builtin(const StringRef name)
|
||||
{
|
||||
return ELEM(name,
|
||||
|
@ -137,6 +125,7 @@ bool BM_attribute_stored_in_bmesh_builtin(const StringRef name)
|
|||
".select_edge",
|
||||
".select_poly",
|
||||
"material_index",
|
||||
"sharp_face",
|
||||
"sharp_edge");
|
||||
}
|
||||
|
||||
|
@ -426,6 +415,8 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
|
|||
&me->pdata, CD_PROP_BOOL, ".hide_poly");
|
||||
const int *material_indices = (const int *)CustomData_get_layer_named(
|
||||
&me->pdata, CD_PROP_INT32, "material_index");
|
||||
const bool *sharp_faces = (const bool *)CustomData_get_layer_named(
|
||||
&me->pdata, CD_PROP_BOOL, "sharp_face");
|
||||
const bool *sharp_edges = (const bool *)CustomData_get_layer_named(
|
||||
&me->edata, CD_PROP_BOOL, "sharp_edge");
|
||||
const bool *uv_seams = (const bool *)CustomData_get_layer_named(
|
||||
|
@ -527,7 +518,9 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
|
|||
BM_elem_index_set(f, bm->totface - 1); /* set_ok */
|
||||
|
||||
/* Transfer flag. */
|
||||
f->head.hflag = bm_face_flag_from_mflag(polys[i].flag);
|
||||
if (!(sharp_faces && sharp_faces[i])) {
|
||||
BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
|
||||
}
|
||||
if (hide_poly && hide_poly[i]) {
|
||||
BM_elem_flag_enable(f, BM_ELEM_HIDDEN);
|
||||
}
|
||||
|
@ -1252,6 +1245,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
|
|||
bool need_hide_edge = false;
|
||||
bool need_hide_poly = false;
|
||||
bool need_material_index = false;
|
||||
bool need_sharp_face = false;
|
||||
bool need_sharp_edge = false;
|
||||
bool need_uv_seam = false;
|
||||
|
||||
|
@ -1312,7 +1306,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
|
|||
if (f->mat_nr != 0) {
|
||||
need_material_index = true;
|
||||
}
|
||||
polys[i].flag = bm_face_flag_to_mflag(f);
|
||||
if (!BM_elem_flag_test(f, BM_ELEM_SMOOTH)) {
|
||||
need_sharp_face = true;
|
||||
}
|
||||
if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
need_hide_poly = true;
|
||||
}
|
||||
|
@ -1357,6 +1353,13 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
|
|||
return !BM_elem_flag_test(BM_edge_at_index(bm, i), BM_ELEM_SMOOTH);
|
||||
});
|
||||
}
|
||||
if (need_sharp_face) {
|
||||
BM_mesh_elem_table_ensure(bm, BM_FACE);
|
||||
write_fn_to_attribute<bool>(
|
||||
me->attributes_for_write(), "sharp_face", ATTR_DOMAIN_FACE, [&](const int i) {
|
||||
return !BM_elem_flag_test(BM_face_at_index(bm, i), BM_ELEM_SMOOTH);
|
||||
});
|
||||
}
|
||||
if (need_uv_seam) {
|
||||
BM_mesh_elem_table_ensure(bm, BM_EDGE);
|
||||
write_fn_to_attribute<bool>(
|
||||
|
@ -1524,6 +1527,7 @@ static void bm_face_loop_table_build(BMesh &bm,
|
|||
MutableSpan<const BMLoop *> loop_table,
|
||||
bool &need_select_poly,
|
||||
bool &need_hide_poly,
|
||||
bool &need_sharp_face,
|
||||
bool &need_material_index)
|
||||
{
|
||||
char hflag = 0;
|
||||
|
@ -1535,6 +1539,7 @@ static void bm_face_loop_table_build(BMesh &bm,
|
|||
BM_elem_index_set(face, face_i); /* set_inline */
|
||||
face_table[face_i] = face;
|
||||
hflag |= face->head.hflag;
|
||||
need_sharp_face |= (face->head.hflag & BM_ELEM_SMOOTH) == 0;
|
||||
need_material_index |= face->mat_nr != 0;
|
||||
|
||||
BMLoop *loop = BM_FACE_FIRST_LOOP(face);
|
||||
|
@ -1622,6 +1627,7 @@ static void bm_to_mesh_faces(const BMesh &bm,
|
|||
Mesh &mesh,
|
||||
MutableSpan<bool> select_poly,
|
||||
MutableSpan<bool> hide_poly,
|
||||
MutableSpan<bool> sharp_faces,
|
||||
MutableSpan<int> material_indices)
|
||||
{
|
||||
const Vector<BMeshToMeshLayerInfo> info = bm_to_mesh_copy_info_calc(bm.pdata, mesh.pdata);
|
||||
|
@ -1632,7 +1638,6 @@ static void bm_to_mesh_faces(const BMesh &bm,
|
|||
MPoly &dst_poly = dst_polys[face_i];
|
||||
dst_poly.totloop = src_face.len;
|
||||
dst_poly.loopstart = BM_elem_index_get(BM_FACE_FIRST_LOOP(&src_face));
|
||||
dst_poly.flag = bm_face_flag_to_mflag(&src_face);
|
||||
bmesh_block_copy_to_mesh_attributes(info, face_i, src_face.head.data);
|
||||
}
|
||||
if (!select_poly.is_empty()) {
|
||||
|
@ -1650,6 +1655,11 @@ static void bm_to_mesh_faces(const BMesh &bm,
|
|||
material_indices[face_i] = bm_faces[face_i]->mat_nr;
|
||||
}
|
||||
}
|
||||
if (!sharp_faces.is_empty()) {
|
||||
for (const int face_i : range) {
|
||||
sharp_faces[face_i] = !BM_elem_flag_test(bm_faces[face_i], BM_ELEM_SMOOTH);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1721,6 +1731,7 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
|
|||
bool need_hide_poly = false;
|
||||
bool need_material_index = false;
|
||||
bool need_sharp_edge = false;
|
||||
bool need_sharp_face = false;
|
||||
bool need_uv_seams = false;
|
||||
Array<const BMVert *> vert_table;
|
||||
Array<const BMEdge *> edge_table;
|
||||
|
@ -1740,8 +1751,13 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
|
|||
[&]() {
|
||||
face_table.reinitialize(bm->totface);
|
||||
loop_table.reinitialize(bm->totloop);
|
||||
bm_face_loop_table_build(
|
||||
*bm, face_table, loop_table, need_select_poly, need_hide_poly, need_material_index);
|
||||
bm_face_loop_table_build(*bm,
|
||||
face_table,
|
||||
loop_table,
|
||||
need_select_poly,
|
||||
need_hide_poly,
|
||||
need_sharp_face,
|
||||
need_material_index);
|
||||
});
|
||||
bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE | BM_LOOP);
|
||||
|
||||
|
@ -1756,6 +1772,7 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
|
|||
bke::SpanAttributeWriter<bool> uv_seams;
|
||||
bke::SpanAttributeWriter<bool> select_poly;
|
||||
bke::SpanAttributeWriter<bool> hide_poly;
|
||||
bke::SpanAttributeWriter<bool> sharp_face;
|
||||
bke::SpanAttributeWriter<int> material_index;
|
||||
if (need_select_vert) {
|
||||
select_vert = attrs.lookup_or_add_for_write_only_span<bool>(".select_vert", ATTR_DOMAIN_POINT);
|
||||
|
@ -1781,6 +1798,9 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
|
|||
if (need_hide_poly) {
|
||||
hide_poly = attrs.lookup_or_add_for_write_only_span<bool>(".hide_poly", ATTR_DOMAIN_FACE);
|
||||
}
|
||||
if (need_sharp_face) {
|
||||
sharp_face = attrs.lookup_or_add_for_write_only_span<bool>("sharp_face", ATTR_DOMAIN_FACE);
|
||||
}
|
||||
if (need_material_index) {
|
||||
material_index = attrs.lookup_or_add_for_write_only_span<int>("material_index",
|
||||
ATTR_DOMAIN_FACE);
|
||||
|
@ -1800,8 +1820,13 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
|
|||
uv_seams.span);
|
||||
},
|
||||
[&]() {
|
||||
bm_to_mesh_faces(
|
||||
*bm, face_table, *me, select_poly.span, hide_poly.span, material_index.span);
|
||||
bm_to_mesh_faces(*bm,
|
||||
face_table,
|
||||
*me,
|
||||
select_poly.span,
|
||||
hide_poly.span,
|
||||
sharp_face.span,
|
||||
material_index.span);
|
||||
},
|
||||
[&]() { bm_to_mesh_loops(*bm, loop_table, *me); });
|
||||
|
||||
|
@ -1813,5 +1838,6 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
|
|||
uv_seams.finish();
|
||||
select_poly.finish();
|
||||
hide_poly.finish();
|
||||
sharp_face.finish();
|
||||
material_index.finish();
|
||||
}
|
||||
|
|
|
@ -261,6 +261,8 @@ static bool bm_face_split_edgenet_find_loop_walk(BMVert *v_init,
|
|||
const uint edge_order_len,
|
||||
BMEdge *e_pair[2])
|
||||
{
|
||||
UNUSED_VARS_NDEBUG(edge_order_len);
|
||||
|
||||
/* fast-path for the common case (avoid push-pop).
|
||||
* Also avoids tagging as visited since we know we
|
||||
* can't reach these verts some other way */
|
||||
|
|
|
@ -604,7 +604,7 @@ void DepsgraphNodeBuilder::build_id(ID *id)
|
|||
case ID_MB:
|
||||
case ID_CU_LEGACY:
|
||||
case ID_LT:
|
||||
case ID_GD:
|
||||
case ID_GD_LEGACY:
|
||||
case ID_CV:
|
||||
case ID_PT:
|
||||
case ID_VO:
|
||||
|
@ -933,7 +933,7 @@ void DepsgraphNodeBuilder::build_object_data(Object *object)
|
|||
case OB_SURF:
|
||||
case OB_MBALL:
|
||||
case OB_LATTICE:
|
||||
case OB_GPENCIL:
|
||||
case OB_GPENCIL_LEGACY:
|
||||
case OB_CURVES:
|
||||
case OB_POINTCLOUD:
|
||||
case OB_VOLUME:
|
||||
|
@ -1616,7 +1616,7 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata)
|
|||
break;
|
||||
}
|
||||
|
||||
case ID_GD: {
|
||||
case ID_GD_LEGACY: {
|
||||
/* GPencil evaluation operations. */
|
||||
op_node = add_operation_node(obdata,
|
||||
NodeType::GEOMETRY,
|
||||
|
|
|
@ -224,8 +224,14 @@ OperationCode bone_target_opcode(ID *target,
|
|||
|
||||
bool object_have_geometry_component(const Object *object)
|
||||
{
|
||||
return ELEM(
|
||||
object->type, OB_MESH, OB_CURVES_LEGACY, OB_FONT, OB_SURF, OB_MBALL, OB_LATTICE, OB_GPENCIL);
|
||||
return ELEM(object->type,
|
||||
OB_MESH,
|
||||
OB_CURVES_LEGACY,
|
||||
OB_FONT,
|
||||
OB_SURF,
|
||||
OB_MBALL,
|
||||
OB_LATTICE,
|
||||
OB_GPENCIL_LEGACY);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -542,7 +548,7 @@ void DepsgraphRelationBuilder::build_id(ID *id)
|
|||
case ID_CV:
|
||||
case ID_PT:
|
||||
case ID_VO:
|
||||
case ID_GD:
|
||||
case ID_GD_LEGACY:
|
||||
build_object_data_geometry_datablock(id);
|
||||
break;
|
||||
case ID_SPK:
|
||||
|
@ -942,7 +948,7 @@ void DepsgraphRelationBuilder::build_object_data(Object *object)
|
|||
case OB_SURF:
|
||||
case OB_MBALL:
|
||||
case OB_LATTICE:
|
||||
case OB_GPENCIL:
|
||||
case OB_GPENCIL_LEGACY:
|
||||
case OB_CURVES:
|
||||
case OB_POINTCLOUD:
|
||||
case OB_VOLUME: {
|
||||
|
@ -2435,7 +2441,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata)
|
|||
}
|
||||
case ID_LT:
|
||||
break;
|
||||
case ID_GD: /* Grease Pencil */
|
||||
case ID_GD_LEGACY: /* Grease Pencil */
|
||||
{
|
||||
bGPdata *gpd = (bGPdata *)obdata;
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ void depsgraph_geometry_tag_to_component(const ID *id, NodeType *component_type)
|
|||
|
||||
bool is_selectable_data_id_type(const ID_Type id_type)
|
||||
{
|
||||
return ELEM(id_type, ID_ME, ID_CU_LEGACY, ID_MB, ID_LT, ID_GD, ID_CV, ID_PT, ID_VO);
|
||||
return ELEM(id_type, ID_ME, ID_CU_LEGACY, ID_MB, ID_LT, ID_GD_LEGACY, ID_CV, ID_PT, ID_VO);
|
||||
}
|
||||
|
||||
void depsgraph_select_tag_to_component_opcode(const ID *id,
|
||||
|
@ -585,7 +585,7 @@ NodeType geometry_tag_to_component(const ID *id)
|
|||
case OB_FONT:
|
||||
case OB_LATTICE:
|
||||
case OB_MBALL:
|
||||
case OB_GPENCIL:
|
||||
case OB_GPENCIL_LEGACY:
|
||||
case OB_CURVES:
|
||||
case OB_POINTCLOUD:
|
||||
case OB_VOLUME:
|
||||
|
@ -609,7 +609,7 @@ NodeType geometry_tag_to_component(const ID *id)
|
|||
return NodeType::UNDEFINED;
|
||||
case ID_LP:
|
||||
return NodeType::PARAMETERS;
|
||||
case ID_GD:
|
||||
case ID_GD_LEGACY:
|
||||
return NodeType::GEOMETRY;
|
||||
case ID_PAL: /* Palettes */
|
||||
return NodeType::PARAMETERS;
|
||||
|
|
|
@ -739,7 +739,7 @@ void update_id_after_copy(const Depsgraph *depsgraph,
|
|||
}
|
||||
/* FIXME: This is a temporary fix to update the runtime pointers properly, see #96216. Should
|
||||
* be removed at some point. */
|
||||
case ID_GD: {
|
||||
case ID_GD_LEGACY: {
|
||||
bGPdata *gpd_cow = (bGPdata *)id_cow;
|
||||
bGPDlayer *gpl = (bGPDlayer *)(gpd_cow->layers.first);
|
||||
if (gpl != nullptr && gpl->runtime.gpl_orig == nullptr) {
|
||||
|
@ -892,8 +892,8 @@ ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, const IDNode
|
|||
}
|
||||
/* In case we don't need to do a copy-on-write, we can use the update cache of the grease
|
||||
* pencil data to do an update-on-write. */
|
||||
if (id_type == ID_GD && BKE_gpencil_can_avoid_full_copy_on_write(
|
||||
(const ::Depsgraph *)depsgraph, (bGPdata *)id_orig)) {
|
||||
if (id_type == ID_GD_LEGACY && BKE_gpencil_can_avoid_full_copy_on_write(
|
||||
(const ::Depsgraph *)depsgraph, (bGPdata *)id_orig)) {
|
||||
BKE_gpencil_update_on_write((bGPdata *)id_orig, (bGPdata *)id_cow);
|
||||
return id_cow;
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ void RuntimeBackup::init_from_id(ID *id)
|
|||
case ID_VO:
|
||||
volume_backup.init_from_volume(reinterpret_cast<Volume *>(id));
|
||||
break;
|
||||
case ID_GD:
|
||||
case ID_GD_LEGACY:
|
||||
gpencil_backup.init_from_gpencil(reinterpret_cast<bGPdata *>(id));
|
||||
break;
|
||||
default:
|
||||
|
@ -103,7 +103,7 @@ void RuntimeBackup::restore_to_id(ID *id)
|
|||
case ID_VO:
|
||||
volume_backup.restore_to_volume(reinterpret_cast<Volume *>(id));
|
||||
break;
|
||||
case ID_GD:
|
||||
case ID_GD_LEGACY:
|
||||
gpencil_backup.restore_to_gpencil(reinterpret_cast<bGPdata *>(id));
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -136,7 +136,7 @@ void Instance::scene_sync()
|
|||
|
||||
void Instance::object_sync(Object *ob)
|
||||
{
|
||||
const bool is_renderable_type = ELEM(ob->type, OB_CURVES, OB_GPENCIL, OB_MESH, OB_LAMP);
|
||||
const bool is_renderable_type = ELEM(ob->type, OB_CURVES, OB_GPENCIL_LEGACY, OB_MESH, OB_LAMP);
|
||||
const int ob_visibility = DRW_object_visibility_in_active_context(ob);
|
||||
const bool partsys_is_visible = (ob_visibility & OB_VISIBLE_PARTICLES) != 0 &&
|
||||
(ob->type == OB_MESH);
|
||||
|
@ -174,7 +174,7 @@ void Instance::object_sync(Object *ob)
|
|||
case OB_CURVES:
|
||||
sync.sync_curves(ob, ob_handle, res_handle);
|
||||
break;
|
||||
case OB_GPENCIL:
|
||||
case OB_GPENCIL_LEGACY:
|
||||
sync.sync_gpencil(ob, ob_handle, res_handle);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -99,7 +99,7 @@ static inline eMaterialGeometry to_material_geometry(const Object *ob)
|
|||
return MAT_GEOM_CURVES;
|
||||
case OB_VOLUME:
|
||||
return MAT_GEOM_VOLUME;
|
||||
case OB_GPENCIL:
|
||||
case OB_GPENCIL_LEGACY:
|
||||
return MAT_GEOM_GPENCIL;
|
||||
default:
|
||||
return MAT_GEOM_MESH;
|
||||
|
|
|
@ -722,7 +722,7 @@ void ShadowModule::begin_sync()
|
|||
PassMain::Sub &sub = pass.sub("Transparent");
|
||||
/* WORKAROUND: The DRW_STATE_WRITE_STENCIL is here only to avoid enabling the rasterizer
|
||||
* discard inside draw manager. */
|
||||
sub.state_set(DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WRITE_STENCIL);
|
||||
sub.state_set(DRW_STATE_CULL_FRONT | DRW_STATE_WRITE_STENCIL);
|
||||
sub.state_stencil(0, 0, 0);
|
||||
sub.framebuffer_set(&usage_tag_fb);
|
||||
sub.shader_set(inst_.shaders.static_shader_get(SHADOW_TILEMAP_TAG_USAGE_TRANSPARENT));
|
||||
|
@ -730,6 +730,10 @@ void ShadowModule::begin_sync()
|
|||
sub.bind_ssbo("tiles_buf", &tilemap_pool.tiles_data);
|
||||
sub.bind_ssbo("bounds_buf", &manager.bounds_buf.current());
|
||||
sub.push_constant("tilemap_projection_ratio", &tilemap_projection_ratio_);
|
||||
sub.push_constant("pixel_world_radius", &pixel_world_radius_);
|
||||
sub.push_constant("fb_resolution", &usage_tag_fb_resolution_);
|
||||
sub.push_constant("fb_lod", &usage_tag_fb_lod_);
|
||||
inst_.hiz_buffer.bind_resources(&sub);
|
||||
inst_.lights.bind_resources(&sub);
|
||||
|
||||
box_batch_ = DRW_cache_cube_get();
|
||||
|
@ -1092,12 +1096,17 @@ void ShadowModule::set_view(View &view)
|
|||
int3 target_size = inst_.render_buffers.depth_tx.size();
|
||||
dispatch_depth_scan_size_ = math::divide_ceil(target_size, int3(SHADOW_DEPTH_SCAN_GROUP_SIZE));
|
||||
|
||||
tilemap_projection_ratio_ = tilemap_pixel_radius() /
|
||||
screen_pixel_radius(view, int2(target_size));
|
||||
pixel_world_radius_ = screen_pixel_radius(view, int2(target_size));
|
||||
tilemap_projection_ratio_ = tilemap_pixel_radius() / pixel_world_radius_;
|
||||
|
||||
usage_tag_fb_resolution_ = math::divide_ceil(int2(target_size),
|
||||
int2(std::exp2(usage_tag_fb_lod_)));
|
||||
usage_tag_fb.ensure(usage_tag_fb_resolution_);
|
||||
|
||||
usage_tag_fb.ensure(int2(target_size));
|
||||
render_fb_.ensure(int2(SHADOW_TILEMAP_RES * shadow_page_size_));
|
||||
|
||||
inst_.hiz_buffer.update();
|
||||
|
||||
bool tile_update_remains = true;
|
||||
while (tile_update_remains) {
|
||||
DRW_stats_group_start("Shadow");
|
||||
|
|
|
@ -216,6 +216,9 @@ class ShadowModule {
|
|||
int3 dispatch_depth_scan_size_;
|
||||
/* Ratio between tile-map pixel world "radius" and film pixel world "radius". */
|
||||
float tilemap_projection_ratio_;
|
||||
float pixel_world_radius_;
|
||||
int2 usage_tag_fb_resolution_;
|
||||
int usage_tag_fb_lod_ = 5;
|
||||
|
||||
/* Statistics that are read back to CPU after a few frame (to avoid stall). */
|
||||
SwapChain<ShadowStatisticsBuf, 5> statistics_buf_;
|
||||
|
|
|
@ -3,13 +3,120 @@
|
|||
* Virtual shadowmapping: Usage tagging
|
||||
*
|
||||
* Shadow pages are only allocated if they are visible.
|
||||
* This pass scan the depth buffer and tag all tiles that are needed for light shadowing as
|
||||
* needed.
|
||||
* This ray-marches the current fragment along the bounds depth and tags all the intersected shadow
|
||||
* tiles.
|
||||
*/
|
||||
|
||||
#pragma BLENDER_REQUIRE(eevee_shadow_tag_usage_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
|
||||
#pragma BLENDER_REQUIRE(common_debug_shape_lib.glsl)
|
||||
|
||||
float ray_aabb(vec3 ray_origin, vec3 ray_direction, vec3 aabb_min, vec3 aabb_max)
|
||||
{
|
||||
/* https://gdbooks.gitbooks.io/3dcollisions/content/Chapter3/raycast_aabb.html */
|
||||
vec3 t_mins = (aabb_min - ray_origin) / ray_direction;
|
||||
vec3 t_maxs = (aabb_max - ray_origin) / ray_direction;
|
||||
|
||||
float t_min = max_v3(min(t_mins, t_maxs));
|
||||
float t_max = min_v3(max(t_mins, t_maxs));
|
||||
|
||||
/* AABB is in the opposite direction. */
|
||||
if (t_max < 0.0) {
|
||||
return -1.0;
|
||||
}
|
||||
/* No intersection. */
|
||||
if (t_min > t_max) {
|
||||
return -1.0;
|
||||
}
|
||||
/* The ray origin is inside the aabb. */
|
||||
if (t_min < 0.0) {
|
||||
/* For regular ray casting we would return t_max here,
|
||||
* but we want to ray cast against the box volume, not just the surface. */
|
||||
return 0.0;
|
||||
}
|
||||
return t_min;
|
||||
}
|
||||
|
||||
float pixel_size_at(float linear_depth)
|
||||
{
|
||||
float pixel_size = pixel_world_radius;
|
||||
bool is_persp = (ProjectionMatrix[3][3] == 0.0);
|
||||
if (is_persp) {
|
||||
pixel_size *= max(0.01, linear_depth);
|
||||
}
|
||||
return pixel_size * exp2(fb_lod);
|
||||
}
|
||||
|
||||
void step_bounding_sphere(vec3 vs_near_plane,
|
||||
vec3 vs_view_direction,
|
||||
float near_t,
|
||||
float far_t,
|
||||
out vec3 sphere_center,
|
||||
out float sphere_radius)
|
||||
{
|
||||
float near_pixel_size = pixel_size_at(near_t);
|
||||
vec3 near_center = vs_near_plane + vs_view_direction * near_t;
|
||||
|
||||
float far_pixel_size = pixel_size_at(far_t);
|
||||
vec3 far_center = vs_near_plane + vs_view_direction * far_t;
|
||||
|
||||
sphere_center = mix(near_center, far_center, 0.5);
|
||||
sphere_radius = 0;
|
||||
|
||||
for (int x = -1; x <= 1; x += 2) {
|
||||
for (int y = -1; y <= 1; y += 2) {
|
||||
vec3 near_corner = near_center + (near_pixel_size * 0.5 * vec3(x, y, 0));
|
||||
sphere_radius = max(sphere_radius, len_squared(near_corner - sphere_center));
|
||||
|
||||
vec3 far_corner = far_center + (far_pixel_size * 0.5 * vec3(x, y, 0));
|
||||
sphere_radius = max(sphere_radius, len_squared(far_corner - sphere_center));
|
||||
}
|
||||
}
|
||||
|
||||
sphere_center = point_view_to_world(sphere_center);
|
||||
sphere_radius = sqrt(sphere_radius);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
shadow_tag_usage(interp.vP, interp.P, gl_FragCoord.xy);
|
||||
vec2 screen_uv = gl_FragCoord.xy / vec2(fb_resolution);
|
||||
|
||||
float opaque_depth = texelFetch(hiz_tx, int2(gl_FragCoord.xy), fb_lod).r;
|
||||
vec3 ws_opaque = get_world_space_from_depth(screen_uv, opaque_depth);
|
||||
|
||||
vec3 ws_near_plane = get_world_space_from_depth(screen_uv, 0);
|
||||
vec3 ws_view_direction = normalize(interp.P - ws_near_plane);
|
||||
vec3 vs_near_plane = get_view_space_from_depth(screen_uv, 0);
|
||||
vec3 vs_view_direction = normalize(interp.vP - vs_near_plane);
|
||||
vec3 ls_near_plane = point_world_to_object(ws_near_plane);
|
||||
vec3 ls_view_direction = normalize(point_world_to_object(interp.P) - ls_near_plane);
|
||||
|
||||
/* TODO (Miguel Pozo): We could try to ray-cast against the non-inflated bounds first,
|
||||
* and fallback to the inflated ones if theres no hit.
|
||||
* The inflated bounds can cause unnecesary extra steps. */
|
||||
float ls_near_box_t = ray_aabb(
|
||||
ls_near_plane, ls_view_direction, interp.ls_aabb_min, interp.ls_aabb_max);
|
||||
vec3 ls_near_box = ls_near_plane + ls_view_direction * ls_near_box_t;
|
||||
vec3 ws_near_box = point_object_to_world(ls_near_box);
|
||||
|
||||
float near_box_t = distance(ws_near_plane, ws_near_box);
|
||||
float far_box_t = distance(ws_near_plane, interp.P);
|
||||
/* Depth test. */
|
||||
far_box_t = min(far_box_t, distance(ws_near_plane, ws_opaque));
|
||||
|
||||
/* Ray march from the front to the back of the bbox, and tag shadow usage along the way. */
|
||||
float step_size;
|
||||
for (float t = near_box_t; t <= far_box_t; t += step_size) {
|
||||
/* Ensure we don't get past far_box_t. */
|
||||
t = min(t, far_box_t);
|
||||
step_size = pixel_size_at(t);
|
||||
|
||||
vec3 P = ws_near_plane + (ws_view_direction * t);
|
||||
float step_radius;
|
||||
step_bounding_sphere(vs_near_plane, vs_view_direction, t, t + step_size, P, step_radius);
|
||||
vec3 vP = point_world_to_view(P);
|
||||
|
||||
shadow_tag_usage(vP, P, ws_view_direction, step_radius, t, gl_FragCoord.xy * exp2(fb_lod));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
* Virtual shadowmapping: Usage tagging
|
||||
*
|
||||
* Shadow pages are only allocated if they are visible.
|
||||
* This pass scan the depth buffer and tag all tiles that are needed for light shadowing as
|
||||
* needed.
|
||||
* This contains the common logic used for tagging shadows for opaque and transparent receivers.
|
||||
*/
|
||||
|
||||
#pragma BLENDER_REQUIRE(common_intersect_lib.glsl)
|
||||
|
@ -14,7 +13,18 @@
|
|||
#pragma BLENDER_REQUIRE(eevee_light_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_shadow_lib.glsl)
|
||||
|
||||
void shadow_tag_usage_tilemap(uint l_idx, vec3 P, float dist_to_cam, const bool is_directional)
|
||||
void shadow_tag_usage_tile(LightData light, ivec2 tile_co, int lod, int tilemap_index)
|
||||
{
|
||||
if (tilemap_index > light_tilemap_max_get(light)) {
|
||||
return;
|
||||
}
|
||||
|
||||
tile_co >>= lod;
|
||||
int tile_index = shadow_tile_offset(tile_co, tilemaps_buf[tilemap_index].tiles_index, lod);
|
||||
atomicOr(tiles_buf[tile_index], SHADOW_IS_USED);
|
||||
}
|
||||
|
||||
void shadow_tag_usage_tilemap_directional(uint l_idx, vec3 P, vec3 V, float radius)
|
||||
{
|
||||
LightData light = light_buf[l_idx];
|
||||
|
||||
|
@ -22,83 +32,141 @@ void shadow_tag_usage_tilemap(uint l_idx, vec3 P, float dist_to_cam, const bool
|
|||
return;
|
||||
}
|
||||
|
||||
int lod = 0;
|
||||
ivec2 tile_co;
|
||||
int tilemap_index = light.tilemap_index;
|
||||
if (is_directional) {
|
||||
vec3 lP = shadow_world_to_local(light, P);
|
||||
vec3 lP = shadow_world_to_local(light, P);
|
||||
|
||||
if (radius == 0) {
|
||||
ShadowCoordinates coord = shadow_directional_coordinates(light, lP);
|
||||
|
||||
tile_co = coord.tile_coord;
|
||||
tilemap_index = coord.tilemap_index;
|
||||
shadow_tag_usage_tile(light, coord.tile_coord, 0, coord.tilemap_index);
|
||||
}
|
||||
else {
|
||||
vec3 lP = light_world_to_local(light, P - light._position);
|
||||
float dist_to_light = length(lP);
|
||||
if (dist_to_light > light.influence_radius_max) {
|
||||
return;
|
||||
}
|
||||
if (light.type == LIGHT_SPOT) {
|
||||
/* Early out if out of cone. */
|
||||
float angle_tan = length(lP.xy / dist_to_light);
|
||||
if (angle_tan > light.spot_tan) {
|
||||
return;
|
||||
vec3 start_lP = shadow_world_to_local(light, P - V * radius);
|
||||
vec3 end_lP = shadow_world_to_local(light, P + V * radius);
|
||||
int min_level = shadow_directional_level(light, start_lP - light._position);
|
||||
int max_level = shadow_directional_level(light, end_lP - light._position);
|
||||
|
||||
for (int level = min_level; level <= max_level; level++) {
|
||||
ShadowCoordinates coord_min = shadow_directional_coordinates_at_level(
|
||||
light, lP - vec3(radius, radius, 0), level);
|
||||
ShadowCoordinates coord_max = shadow_directional_coordinates_at_level(
|
||||
light, lP + vec3(radius, radius, 0), level);
|
||||
|
||||
for (int x = coord_min.tile_coord.x; x <= coord_max.tile_coord.x; x++) {
|
||||
for (int y = coord_min.tile_coord.y; y <= coord_max.tile_coord.y; y++) {
|
||||
shadow_tag_usage_tile(light, ivec2(x, y), 0, coord_min.tilemap_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (is_area_light(light.type)) {
|
||||
/* Early out if on the wrong side. */
|
||||
if (lP.z > 0.0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* How much a shadow map pixel covers a final image pixel.
|
||||
* We project a shadow map pixel (as a sphere for simplicity) to the receiver plane.
|
||||
* We then reproject this sphere onto the camera screen and compare it to the film pixel size.
|
||||
* This gives a good approximation of what LOD to select to get a somewhat uniform shadow map
|
||||
* resolution in screen space. */
|
||||
float footprint_ratio = dist_to_light;
|
||||
/* Project the radius to the screen. 1 unit away from the camera the same way
|
||||
* pixel_world_radius_inv was computed. Not needed in orthographic mode. */
|
||||
bool is_persp = (ProjectionMatrix[3][3] == 0.0);
|
||||
if (is_persp) {
|
||||
footprint_ratio /= dist_to_cam;
|
||||
}
|
||||
/* Apply resolution ratio. */
|
||||
footprint_ratio *= tilemap_projection_ratio;
|
||||
|
||||
int face_id = shadow_punctual_face_index_get(lP);
|
||||
lP = shadow_punctual_local_position_to_face_local(face_id, lP);
|
||||
|
||||
ShadowCoordinates coord = shadow_punctual_coordinates(light, lP, face_id);
|
||||
tile_co = coord.tile_coord;
|
||||
tilemap_index = coord.tilemap_index;
|
||||
|
||||
lod = int(ceil(-log2(footprint_ratio) + tilemaps_buf[tilemap_index].lod_bias));
|
||||
lod = clamp(lod, 0, SHADOW_TILEMAP_LOD);
|
||||
}
|
||||
tile_co >>= lod;
|
||||
}
|
||||
|
||||
if (tilemap_index > light_tilemap_max_get(light)) {
|
||||
void shadow_tag_usage_tilemap_punctual(uint l_idx, vec3 P, vec3 V, float dist_to_cam, float radius)
|
||||
{
|
||||
LightData light = light_buf[l_idx];
|
||||
|
||||
if (light.tilemap_index == LIGHT_NO_SHADOW) {
|
||||
return;
|
||||
}
|
||||
|
||||
int tile_index = shadow_tile_offset(tile_co, tilemaps_buf[tilemap_index].tiles_index, lod);
|
||||
atomicOr(tiles_buf[tile_index], SHADOW_IS_USED);
|
||||
vec3 lP = light_world_to_local(light, P - light._position);
|
||||
float dist_to_light = length(lP) - radius;
|
||||
if (dist_to_light > light.influence_radius_max) {
|
||||
return;
|
||||
}
|
||||
if (light.type == LIGHT_SPOT) {
|
||||
/* Early out if out of cone. */
|
||||
float angle_tan = length(lP.xy / dist_to_light);
|
||||
if (angle_tan > light.spot_tan) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (is_area_light(light.type)) {
|
||||
/* Early out if on the wrong side. */
|
||||
if (lP.z - radius > 0.0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* How much a shadow map pixel covers a final image pixel.
|
||||
* We project a shadow map pixel (as a sphere for simplicity) to the receiver plane.
|
||||
* We then reproject this sphere onto the camera screen and compare it to the film pixel size.
|
||||
* This gives a good approximation of what LOD to select to get a somewhat uniform shadow map
|
||||
* resolution in screen space. */
|
||||
float footprint_ratio = dist_to_light;
|
||||
/* Project the radius to the screen. 1 unit away from the camera the same way
|
||||
* pixel_world_radius_inv was computed. Not needed in orthographic mode. */
|
||||
bool is_persp = (ProjectionMatrix[3][3] == 0.0);
|
||||
if (is_persp) {
|
||||
footprint_ratio /= dist_to_cam;
|
||||
}
|
||||
/* Apply resolution ratio. */
|
||||
footprint_ratio *= tilemap_projection_ratio;
|
||||
|
||||
if (radius == 0) {
|
||||
int face_id = shadow_punctual_face_index_get(lP);
|
||||
lP = shadow_punctual_local_position_to_face_local(face_id, lP);
|
||||
ShadowCoordinates coord = shadow_punctual_coordinates(light, lP, face_id);
|
||||
|
||||
int lod = int(ceil(-log2(footprint_ratio) + tilemaps_buf[coord.tilemap_index].lod_bias));
|
||||
lod = clamp(lod, 0, SHADOW_TILEMAP_LOD);
|
||||
|
||||
shadow_tag_usage_tile(light, coord.tile_coord, lod, coord.tilemap_index);
|
||||
}
|
||||
else {
|
||||
uint faces = 0u;
|
||||
for (int x = -1; x <= 1; x += 2) {
|
||||
for (int y = -1; y <= 1; y += 2) {
|
||||
for (int z = -1; z <= 1; z += 2) {
|
||||
vec3 _lP = lP + vec3(x, y, z) * radius;
|
||||
faces |= 1u << shadow_punctual_face_index_get(_lP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int face_id = 0; face_id < 6; face_id++) {
|
||||
if ((faces & (1u << uint(face_id))) == 0u) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int tilemap_index = light.tilemap_index + face_id;
|
||||
int lod = int(ceil(-log2(footprint_ratio) + tilemaps_buf[tilemap_index].lod_bias));
|
||||
lod = clamp(lod, 0, SHADOW_TILEMAP_LOD);
|
||||
|
||||
vec3 _lP = shadow_punctual_local_position_to_face_local(face_id, lP);
|
||||
|
||||
vec3 offset = vec3(radius, radius, 0);
|
||||
ShadowCoordinates coord_min = shadow_punctual_coordinates(light, _lP - offset, face_id);
|
||||
ShadowCoordinates coord_max = shadow_punctual_coordinates(light, _lP + offset, face_id);
|
||||
|
||||
for (int x = coord_min.tile_coord.x; x <= coord_max.tile_coord.x; x++) {
|
||||
for (int y = coord_min.tile_coord.y; y <= coord_max.tile_coord.y; y++) {
|
||||
shadow_tag_usage_tile(light, ivec2(x, y), lod, tilemap_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \a radius Radius of the tagging area in world space.
|
||||
* Used for downsampled/ray-marched tagging, so all the shadowmap texels covered get correctly
|
||||
* tagged.
|
||||
*/
|
||||
void shadow_tag_usage(vec3 vP, vec3 P, vec3 V, float radius, float dist_to_cam, vec2 pixel)
|
||||
{
|
||||
LIGHT_FOREACH_BEGIN_DIRECTIONAL (light_cull_buf, l_idx) {
|
||||
shadow_tag_usage_tilemap_directional(l_idx, P, V, radius);
|
||||
}
|
||||
LIGHT_FOREACH_END
|
||||
|
||||
LIGHT_FOREACH_BEGIN_LOCAL (light_cull_buf, light_zbin_buf, light_tile_buf, pixel, vP.z, l_idx) {
|
||||
shadow_tag_usage_tilemap_punctual(l_idx, P, V, dist_to_cam, radius);
|
||||
}
|
||||
LIGHT_FOREACH_END
|
||||
}
|
||||
|
||||
void shadow_tag_usage(vec3 vP, vec3 P, vec2 pixel)
|
||||
{
|
||||
float dist_to_cam = length(vP);
|
||||
|
||||
LIGHT_FOREACH_BEGIN_DIRECTIONAL (light_cull_buf, l_idx) {
|
||||
shadow_tag_usage_tilemap(l_idx, P, dist_to_cam, true);
|
||||
}
|
||||
LIGHT_FOREACH_END
|
||||
|
||||
LIGHT_FOREACH_BEGIN_LOCAL (light_cull_buf, light_zbin_buf, light_tile_buf, pixel, vP.z, l_idx) {
|
||||
shadow_tag_usage_tilemap(l_idx, P, dist_to_cam, false);
|
||||
}
|
||||
LIGHT_FOREACH_END
|
||||
shadow_tag_usage(vP, P, vec3(0), 0, dist_to_cam, pixel);
|
||||
}
|
||||
|
|
|
@ -3,20 +3,89 @@
|
|||
* Virtual shadowmapping: Usage tagging
|
||||
*
|
||||
* Shadow pages are only allocated if they are visible.
|
||||
* This renders bounding boxes for transparent objects in order to tag the correct shadows.
|
||||
* This renders the bounding boxes for transparent objects in order to tag the correct shadows.
|
||||
*/
|
||||
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_shape_lib.glsl)
|
||||
|
||||
#pragma BLENDER_REQUIRE(common_debug_shape_lib.glsl)
|
||||
|
||||
/* Inflate bounds by half a pixel as a conservative rasterization alternative,
|
||||
* to ensure the tiles needed by all LOD0 pixels get tagged */
|
||||
void inflate_bounds(vec3 ls_center, inout vec3 P, inout vec3 lP)
|
||||
{
|
||||
vec3 vP = point_world_to_view(P);
|
||||
|
||||
float inflate_scale = pixel_world_radius * exp2(fb_lod);
|
||||
bool is_persp = (ProjectionMatrix[3][3] == 0.0);
|
||||
if (is_persp) {
|
||||
inflate_scale *= -vP.z;
|
||||
}
|
||||
/* Half-pixel. */
|
||||
inflate_scale *= 0.5;
|
||||
|
||||
vec3 vs_inflate_vector = normal_object_to_view(sign(lP - ls_center));
|
||||
vs_inflate_vector.z = 0;
|
||||
/* Scale the vector so the largest axis length is 1 */
|
||||
vs_inflate_vector /= max_v2(abs(vs_inflate_vector.xy));
|
||||
vs_inflate_vector *= inflate_scale;
|
||||
|
||||
vP += vs_inflate_vector;
|
||||
P = point_view_to_world(vP);
|
||||
lP = point_world_to_object(P);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ObjectBounds bounds = bounds_buf[drw_ResourceID];
|
||||
PASS_RESOURCE_ID
|
||||
|
||||
interp.P = bounds.bounding_corners[0].xyz;
|
||||
interp.P += bounds.bounding_corners[1].xyz * pos.x;
|
||||
interp.P += bounds.bounding_corners[2].xyz * pos.y;
|
||||
interp.P += bounds.bounding_corners[3].xyz * pos.z;
|
||||
const ObjectBounds bounds = bounds_buf[resource_id];
|
||||
|
||||
Box box = shape_box(bounds.bounding_corners[0].xyz,
|
||||
bounds.bounding_corners[0].xyz + bounds.bounding_corners[1].xyz,
|
||||
bounds.bounding_corners[0].xyz + bounds.bounding_corners[2].xyz,
|
||||
bounds.bounding_corners[0].xyz + bounds.bounding_corners[3].xyz);
|
||||
|
||||
vec3 ws_aabb_min = bounds.bounding_corners[0].xyz;
|
||||
vec3 ws_aabb_max = bounds.bounding_corners[0].xyz + bounds.bounding_corners[1].xyz +
|
||||
bounds.bounding_corners[2].xyz + bounds.bounding_corners[3].xyz;
|
||||
|
||||
vec3 ls_center = point_world_to_object((ws_aabb_min + ws_aabb_max) / 2.0);
|
||||
|
||||
vec3 ls_conservative_min = vec3(FLT_MAX);
|
||||
vec3 ls_conservative_max = vec3(-FLT_MAX);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
vec3 P = box.corners[i];
|
||||
vec3 lP = point_world_to_object(P);
|
||||
inflate_bounds(ls_center, P, lP);
|
||||
|
||||
ls_conservative_min = min(ls_conservative_min, lP);
|
||||
ls_conservative_max = max(ls_conservative_max, lP);
|
||||
}
|
||||
|
||||
interp.ls_aabb_min = ls_conservative_min;
|
||||
interp.ls_aabb_max = ls_conservative_max;
|
||||
|
||||
vec3 lP = mix(ls_conservative_min, ls_conservative_max, max(vec3(0), pos));
|
||||
|
||||
interp.P = point_object_to_world(lP);
|
||||
interp.vP = point_world_to_view(interp.P);
|
||||
|
||||
gl_Position = point_world_to_ndc(interp.P);
|
||||
|
||||
#if 0
|
||||
if (gl_VertexID == 0) {
|
||||
Box debug_box = shape_box(
|
||||
ls_conservative_min,
|
||||
ls_conservative_min + (ls_conservative_max - ls_conservative_min) * vec3(1, 0, 0),
|
||||
ls_conservative_min + (ls_conservative_max - ls_conservative_min) * vec3(0, 1, 0),
|
||||
ls_conservative_min + (ls_conservative_max - ls_conservative_min) * vec3(0, 0, 1));
|
||||
for (int i = 0; i < 8; i++) {
|
||||
debug_box.corners[i] = point_object_to_world(debug_box.corners[i]);
|
||||
}
|
||||
drw_debug(debug_box);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -98,7 +98,12 @@ ShadowTileData shadow_tile_load(usampler2D tilemaps_tx, ivec2 tile_co, int tilem
|
|||
return shadow_tile_unpack(tile_data);
|
||||
}
|
||||
|
||||
/* This function should be the inverse of ShadowDirectional::coverage_get(). */
|
||||
/**
|
||||
* This function should be the inverse of ShadowDirectional::coverage_get().
|
||||
*
|
||||
* \a lP shading point position in light space, relative to the to camera position snapped to
|
||||
* the smallest clipmap level (`shadow_world_to_local(light, P) - light._position`).
|
||||
*/
|
||||
int shadow_directional_level(LightData light, vec3 lP)
|
||||
{
|
||||
float lod;
|
||||
|
@ -144,14 +149,11 @@ ivec2 shadow_decompress_grid_offset(eLightType light_type, ivec2 offset, int lev
|
|||
}
|
||||
|
||||
/**
|
||||
* \a lP shading point position in light space (world unit) and translated to camera position
|
||||
* snapped to smallest clipmap level.
|
||||
* \a lP shading point position in light space (`shadow_world_to_local(light, P)`).
|
||||
*/
|
||||
ShadowCoordinates shadow_directional_coordinates(LightData light, vec3 lP)
|
||||
ShadowCoordinates shadow_directional_coordinates_at_level(LightData light, vec3 lP, int level)
|
||||
{
|
||||
ShadowCoordinates ret;
|
||||
|
||||
int level = shadow_directional_level(light, lP - light._position);
|
||||
/* This difference needs to be less than 32 for the later shift to be valid.
|
||||
* This is ensured by ShadowDirectional::clipmap_level_range(). */
|
||||
int level_relative = level - light.clipmap_lod_min;
|
||||
|
@ -173,6 +175,15 @@ ShadowCoordinates shadow_directional_coordinates(LightData light, vec3 lP)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* \a lP shading point position in light space (`shadow_world_to_local(light, P)`).
|
||||
*/
|
||||
ShadowCoordinates shadow_directional_coordinates(LightData light, vec3 lP)
|
||||
{
|
||||
int level = shadow_directional_level(light, lP - light._position);
|
||||
return shadow_directional_coordinates_at_level(light, lP, level);
|
||||
}
|
||||
|
||||
/* Transform vector to face local coordinate. */
|
||||
vec3 shadow_punctual_local_position_to_face_local(int face_id, vec3 lL)
|
||||
{
|
||||
|
|
|
@ -54,7 +54,9 @@ GPU_SHADER_CREATE_INFO(eevee_shadow_tag_usage_opaque)
|
|||
|
||||
GPU_SHADER_INTERFACE_INFO(eevee_shadow_tag_transparent_iface, "interp")
|
||||
.smooth(Type::VEC3, "P")
|
||||
.smooth(Type::VEC3, "vP");
|
||||
.smooth(Type::VEC3, "vP")
|
||||
.flat(Type::VEC3, "ls_aabb_min")
|
||||
.flat(Type::VEC3, "ls_aabb_max");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(eevee_shadow_tag_usage_transparent)
|
||||
.do_static_compilation(true)
|
||||
|
@ -63,9 +65,17 @@ GPU_SHADER_CREATE_INFO(eevee_shadow_tag_usage_transparent)
|
|||
.storage_buf(5, Qualifier::READ_WRITE, "ShadowTileMapData", "tilemaps_buf[]")
|
||||
.storage_buf(6, Qualifier::READ_WRITE, "ShadowTileDataPacked", "tiles_buf[]")
|
||||
.push_constant(Type::FLOAT, "tilemap_projection_ratio")
|
||||
.push_constant(Type::FLOAT, "pixel_world_radius")
|
||||
.push_constant(Type::IVEC2, "fb_resolution")
|
||||
.push_constant(Type::INT, "fb_lod")
|
||||
.vertex_out(eevee_shadow_tag_transparent_iface)
|
||||
.additional_info(
|
||||
"eevee_shared", "draw_view", "draw_view_culling", "draw_modelmat_new", "eevee_light_data")
|
||||
.additional_info("eevee_shared",
|
||||
"draw_resource_id_varying",
|
||||
"draw_view",
|
||||
"draw_view_culling",
|
||||
"draw_modelmat_new",
|
||||
"eevee_hiz_data",
|
||||
"eevee_light_data")
|
||||
.vertex_source("eevee_shadow_tag_usage_vert.glsl")
|
||||
.fragment_source("eevee_shadow_tag_usage_frag.glsl");
|
||||
|
||||
|
|
|
@ -195,7 +195,7 @@ static void external_cache_populate(void *vedata, Object *ob)
|
|||
return;
|
||||
}
|
||||
|
||||
if (ob->type == OB_GPENCIL) {
|
||||
if (ob->type == OB_GPENCIL_LEGACY) {
|
||||
/* Grease Pencil objects need correct depth to do the blending. */
|
||||
stl->g_data->need_depth = true;
|
||||
return;
|
||||
|
|
|
@ -111,7 +111,7 @@ void GPENCIL_engine_init(void *ved)
|
|||
|
||||
stl->pd->v3d_color_type = (v3d->shading.type == OB_SOLID) ? v3d->shading.color_type : -1;
|
||||
/* Special case: If Vertex Paint mode, use always Vertex mode. */
|
||||
if (v3d->shading.type == OB_SOLID && ctx->obact && ctx->obact->type == OB_GPENCIL &&
|
||||
if (v3d->shading.type == OB_SOLID && ctx->obact && ctx->obact->type == OB_GPENCIL_LEGACY &&
|
||||
ctx->obact->mode == OB_MODE_VERTEX_GPENCIL) {
|
||||
stl->pd->v3d_color_type = V3D_SHADING_VERTEX_COLOR;
|
||||
}
|
||||
|
@ -235,7 +235,7 @@ void GPENCIL_cache_init(void *ved)
|
|||
pd->do_fast_drawing = false;
|
||||
|
||||
pd->obact = draw_ctx->obact;
|
||||
if (pd->obact && pd->obact->type == OB_GPENCIL && !(pd->draw_depth_only)) {
|
||||
if (pd->obact && pd->obact->type == OB_GPENCIL_LEGACY && !(pd->draw_depth_only)) {
|
||||
/* Check if active object has a temp stroke data. */
|
||||
bGPdata *gpd = (bGPdata *)pd->obact->data;
|
||||
if (gpd->runtime.sbuffer_used > 0) {
|
||||
|
@ -592,7 +592,7 @@ void GPENCIL_cache_populate(void *ved, Object *ob)
|
|||
return;
|
||||
}
|
||||
|
||||
if (ob->data && (ob->type == OB_GPENCIL) && (ob->dt >= OB_SOLID)) {
|
||||
if (ob->data && (ob->type == OB_GPENCIL_LEGACY) && (ob->dt >= OB_SOLID)) {
|
||||
gpIterPopulateData iter = {0};
|
||||
iter.ob = ob;
|
||||
iter.pd = pd;
|
||||
|
@ -917,7 +917,7 @@ void GPENCIL_draw_scene(void *ved)
|
|||
|
||||
/* Fade 3D objects. */
|
||||
if ((!pd->is_render) && (pd->fade_3d_object_opacity > -1.0f) && (pd->obact != NULL) &&
|
||||
(pd->obact->type == OB_GPENCIL)) {
|
||||
(pd->obact->type == OB_GPENCIL_LEGACY)) {
|
||||
float background_color[3];
|
||||
ED_view3d_background_color_get(pd->scene, pd->v3d, background_color);
|
||||
/* Blend color. */
|
||||
|
|
|
@ -143,7 +143,7 @@ static void GPENCIL_render_cache(void *vedata,
|
|||
struct RenderEngine *UNUSED(engine),
|
||||
Depsgraph *UNUSED(depsgraph))
|
||||
{
|
||||
if (ob && ELEM(ob->type, OB_GPENCIL, OB_LAMP)) {
|
||||
if (ob && ELEM(ob->type, OB_GPENCIL_LEGACY, OB_LAMP)) {
|
||||
if (DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF) {
|
||||
GPENCIL_cache_populate(vedata, ob);
|
||||
}
|
||||
|
|
|
@ -329,7 +329,7 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
|
|||
OB_CURVES_LEGACY,
|
||||
OB_SURF,
|
||||
OB_FONT,
|
||||
OB_GPENCIL,
|
||||
OB_GPENCIL_LEGACY,
|
||||
OB_CURVES,
|
||||
OB_POINTCLOUD,
|
||||
OB_VOLUME);
|
||||
|
@ -467,7 +467,7 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
|
|||
OVERLAY_metaball_cache_populate(data, ob);
|
||||
}
|
||||
break;
|
||||
case OB_GPENCIL:
|
||||
case OB_GPENCIL_LEGACY:
|
||||
OVERLAY_gpencil_cache_populate(data, ob);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1577,7 +1577,7 @@ void OVERLAY_extra_cache_populate(OVERLAY_Data *vedata, Object *ob)
|
|||
const bool from_dupli = (ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI)) != 0;
|
||||
const bool has_bounds = !ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_EMPTY, OB_SPEAKER, OB_LIGHTPROBE);
|
||||
const bool has_texspace = has_bounds &&
|
||||
!ELEM(ob->type, OB_EMPTY, OB_LATTICE, OB_ARMATURE, OB_GPENCIL);
|
||||
!ELEM(ob->type, OB_EMPTY, OB_LATTICE, OB_ARMATURE, OB_GPENCIL_LEGACY);
|
||||
|
||||
const bool draw_relations = ((pd->v3d_flag & V3D_HIDE_HELPLINES) == 0) && !is_select_mode;
|
||||
const bool draw_obcenters = !is_paint_mode &&
|
||||
|
|
|
@ -45,7 +45,7 @@ void OVERLAY_edit_gpencil_cache_init(OVERLAY_Data *vedata)
|
|||
Scene *scene = draw_ctx->scene;
|
||||
ToolSettings *ts = scene->toolsettings;
|
||||
|
||||
if (gpd == nullptr || ob->type != OB_GPENCIL) {
|
||||
if (gpd == nullptr || ob->type != OB_GPENCIL_LEGACY) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -223,7 +223,7 @@ void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata)
|
|||
pd->edit_curve.show_handles = v3d->overlay.handle_display != CURVE_HANDLE_NONE;
|
||||
pd->edit_curve.handle_display = v3d->overlay.handle_display;
|
||||
|
||||
if (gpd == nullptr || ob->type != OB_GPENCIL) {
|
||||
if (gpd == nullptr || ob->type != OB_GPENCIL_LEGACY) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -311,7 +311,7 @@ void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata,
|
|||
return;
|
||||
}
|
||||
|
||||
if (ob->type == OB_GPENCIL) {
|
||||
if (ob->type == OB_GPENCIL_LEGACY) {
|
||||
OVERLAY_outline_gpencil(pd, ob);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -297,7 +297,7 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
|
|||
shgrp = pd->wires_grp[is_xray][use_coloring];
|
||||
}
|
||||
|
||||
if (ob->type == OB_GPENCIL) {
|
||||
if (ob->type == OB_GPENCIL_LEGACY) {
|
||||
/* TODO(fclem): Make GPencil objects have correct bound-box. */
|
||||
DRW_shgroup_call_no_cull(shgrp, geom, ob);
|
||||
}
|
||||
|
|
|
@ -880,7 +880,7 @@ GPUBatch *DRW_cache_object_face_wireframe_get(Object *ob)
|
|||
return DRW_pointcloud_batch_cache_get_dots(ob);
|
||||
case OB_VOLUME:
|
||||
return DRW_cache_volume_face_wireframe_get(ob);
|
||||
case OB_GPENCIL:
|
||||
case OB_GPENCIL_LEGACY:
|
||||
return DRW_cache_gpencil_face_wireframe_get(ob);
|
||||
default:
|
||||
return NULL;
|
||||
|
@ -945,7 +945,7 @@ int DRW_cache_object_material_count_get(struct Object *ob)
|
|||
return DRW_pointcloud_material_count_get(ob->data);
|
||||
case OB_VOLUME:
|
||||
return DRW_volume_material_count_get(ob->data);
|
||||
case OB_GPENCIL:
|
||||
case OB_GPENCIL_LEGACY:
|
||||
return DRW_gpencil_material_count_get(ob->data);
|
||||
default:
|
||||
BLI_assert(0);
|
||||
|
|
|
@ -383,6 +383,7 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
|
|||
is_auto_smooth,
|
||||
split_angle,
|
||||
sharp_edges,
|
||||
mr->sharp_faces,
|
||||
nullptr,
|
||||
nullptr,
|
||||
clnors);
|
||||
|
@ -573,6 +574,9 @@ MeshRenderData *mesh_render_data_create(Object *object,
|
|||
CustomData_get_layer_named(&mr->me->edata, CD_PROP_BOOL, ".select_edge"));
|
||||
mr->select_poly = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&mr->me->pdata, CD_PROP_BOOL, ".select_poly"));
|
||||
|
||||
mr->sharp_faces = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&mr->me->pdata, CD_PROP_BOOL, "sharp_face"));
|
||||
}
|
||||
else {
|
||||
/* #BMesh */
|
||||
|
|
|
@ -603,7 +603,7 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_fill)
|
|||
ARegion *region = draw_ctx->region;
|
||||
Object *ob = draw_ctx->obact;
|
||||
|
||||
BLI_assert(ob && (ob->type == OB_GPENCIL));
|
||||
BLI_assert(ob && (ob->type == OB_GPENCIL_LEGACY));
|
||||
|
||||
/* Get origin to reproject points. */
|
||||
float origin[3];
|
||||
|
|
|
@ -757,7 +757,7 @@ static void draw_subdiv_cache_extra_coarse_face_data_mesh(const MeshRenderData *
|
|||
const Span<MPoly> polys = mesh->polys();
|
||||
for (const int i : polys.index_range()) {
|
||||
uint32_t flag = 0;
|
||||
if ((polys[i].flag & ME_SMOOTH) != 0) {
|
||||
if (!(mr->sharp_faces && mr->sharp_faces[i])) {
|
||||
flag |= SUBDIV_COARSE_FACE_FLAG_SMOOTH;
|
||||
}
|
||||
if (mr->select_poly && mr->select_poly[i]) {
|
||||
|
@ -786,7 +786,7 @@ static void draw_subdiv_cache_extra_coarse_face_data_mapped(Mesh *mesh,
|
|||
/* Selection and hiding from bmesh. */
|
||||
uint32_t flag = (f) ? compute_coarse_face_flag_bm(f, mr->efa_act) : 0;
|
||||
/* Smooth from mesh. */
|
||||
if ((polys[i].flag & ME_SMOOTH) != 0) {
|
||||
if (!(mr->sharp_faces && mr->sharp_faces[i])) {
|
||||
flag |= SUBDIV_COARSE_FACE_FLAG_SMOOTH;
|
||||
}
|
||||
flags_data[i] = uint(polys[i].loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET);
|
||||
|
|
|
@ -1314,9 +1314,9 @@ static void drw_engines_data_validate(void)
|
|||
static bool drw_gpencil_engine_needed(Depsgraph *depsgraph, View3D *v3d)
|
||||
{
|
||||
const bool exclude_gpencil_rendering = v3d ? (v3d->object_type_exclude_viewport &
|
||||
(1 << OB_GPENCIL)) != 0 :
|
||||
(1 << OB_GPENCIL_LEGACY)) != 0 :
|
||||
false;
|
||||
return (!exclude_gpencil_rendering) && DEG_id_type_any_exists(depsgraph, ID_GD);
|
||||
return (!exclude_gpencil_rendering) && DEG_id_type_any_exists(depsgraph, ID_GD_LEGACY);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -1876,7 +1876,7 @@ bool DRW_render_check_grease_pencil(Depsgraph *depsgraph)
|
|||
deg_iter_settings.depsgraph = depsgraph;
|
||||
deg_iter_settings.flags = DEG_OBJECT_ITER_FOR_RENDER_ENGINE_FLAGS;
|
||||
DEG_OBJECT_ITER_BEGIN (°_iter_settings, ob) {
|
||||
if (ob->type == OB_GPENCIL) {
|
||||
if (ob->type == OB_GPENCIL_LEGACY) {
|
||||
if (DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -336,15 +336,17 @@ struct PBVHBatches {
|
|||
float fno[3];
|
||||
short no[3];
|
||||
int last_poly = -1;
|
||||
bool smooth = false;
|
||||
const bool *sharp_faces = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(args->pdata, CD_PROP_BOOL, "sharp_face"));
|
||||
|
||||
foreach_faces([&](int /*buffer_i*/, int /*tri_i*/, int vertex_i, const MLoopTri *tri) {
|
||||
bool smooth = false;
|
||||
if (tri->poly != last_poly) {
|
||||
last_poly = tri->poly;
|
||||
|
||||
const MPoly &poly = args->polys[tri->poly];
|
||||
if (!(poly.flag & ME_SMOOTH)) {
|
||||
if (sharp_faces && sharp_faces[tri->poly]) {
|
||||
smooth = true;
|
||||
const MPoly &poly = args->polys[tri->poly];
|
||||
BKE_mesh_calc_poly_normal(
|
||||
&poly, args->mloop + poly.loopstart, args->vert_positions, fno);
|
||||
normal_float_to_short_v3(no, fno);
|
||||
|
@ -409,7 +411,7 @@ struct PBVHBatches {
|
|||
foreach_grids([&](int /*x*/, int /*y*/, int grid_index, CCGElem *elems[4], int /*i*/) {
|
||||
float3 no(0.0f, 0.0f, 0.0f);
|
||||
|
||||
const bool smooth = args->grid_flag_mats[grid_index].flag & ME_SMOOTH;
|
||||
const bool smooth = !args->grid_flag_mats[grid_index].sharp;
|
||||
|
||||
if (smooth) {
|
||||
no = CCG_elem_no(&args->ccg_key, elems[0]);
|
||||
|
@ -1085,7 +1087,7 @@ struct PBVHBatches {
|
|||
|
||||
for (int i : IndexRange(args->totprim)) {
|
||||
int grid_index = args->grid_indices[i];
|
||||
bool smooth = args->grid_flag_mats[grid_index].flag & ME_SMOOTH;
|
||||
bool smooth = !args->grid_flag_mats[grid_index].sharp;
|
||||
BLI_bitmap *gh = args->grid_hidden[grid_index];
|
||||
|
||||
for (int y = 0; y < gridsize - 1; y += skip) {
|
||||
|
|
|
@ -209,10 +209,6 @@ void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, struct MeshBufferCac
|
|||
|
||||
void DRW_subdiv_cache_free(struct Subdiv *subdiv);
|
||||
|
||||
void draw_subdiv_init_mesh_render_data(DRWSubdivCache *cache,
|
||||
struct MeshRenderData *mr,
|
||||
const struct ToolSettings *toolsettings);
|
||||
|
||||
void draw_subdiv_init_origindex_buffer(struct GPUVertBuf *buffer,
|
||||
int32_t *vert_origindex,
|
||||
uint num_loops,
|
||||
|
|
|
@ -94,6 +94,7 @@ struct MeshRenderData {
|
|||
const bool *select_vert;
|
||||
const bool *select_edge;
|
||||
const bool *select_poly;
|
||||
const bool *sharp_faces;
|
||||
float (*loop_normals)[3];
|
||||
int *lverts, *ledges;
|
||||
|
||||
|
|
|
@ -71,11 +71,11 @@ static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr,
|
|||
if (mr->loop_normals) {
|
||||
*lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[ml_index]);
|
||||
}
|
||||
else if (poly->flag & ME_SMOOTH) {
|
||||
*lnor_data = GPU_normal_convert_i10_v3(mr->vert_normals[ml->v]);
|
||||
else if (mr->sharp_faces && mr->sharp_faces[poly_index]) {
|
||||
*lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[poly_index]);
|
||||
}
|
||||
else {
|
||||
*lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[poly_index]);
|
||||
*lnor_data = GPU_normal_convert_i10_v3(mr->vert_normals[ml->v]);
|
||||
}
|
||||
|
||||
/* Flag for paint mode overlay.
|
||||
|
@ -195,11 +195,11 @@ static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr,
|
|||
if (mr->loop_normals) {
|
||||
normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[ml_index]);
|
||||
}
|
||||
else if (poly->flag & ME_SMOOTH) {
|
||||
normal_float_to_short_v3(&lnor_data->x, mr->vert_normals[ml->v]);
|
||||
else if (mr->sharp_faces && mr->sharp_faces[poly_index]) {
|
||||
normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[poly_index]);
|
||||
}
|
||||
else {
|
||||
normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[poly_index]);
|
||||
normal_float_to_short_v3(&lnor_data->x, mr->vert_normals[ml->v]);
|
||||
}
|
||||
|
||||
/* Flag for paint mode overlay.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue