Anim: Change how Only Insert Needed works #115360
|
@ -599,7 +599,7 @@ doc_dna: .FORCE
|
|||
@echo "docs written into: '$(BLENDER_DIR)/doc/blender_file_format/dna.html'"
|
||||
|
||||
doc_man: .FORCE
|
||||
@$(BLENDER_BIN) --background --python doc/manpage/blender.1.py -- --output=blender.1 --verbose
|
||||
@$(PYTHON) doc/manpage/blender.1.py --blender="$(BLENDER_BIN)" --output=blender.1 --verbose
|
||||
|
||||
help_features: .FORCE
|
||||
@$(PYTHON) "$(BLENDER_DIR)/build_files/cmake/cmake_print_build_options.py" $(BLENDER_DIR)"/CMakeLists.txt"
|
||||
|
|
|
@ -2,13 +2,6 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
# NOTE: Resolved up-stream, quiet noisy compiler warnings for now.
|
||||
add_cxx_flag("-Wno-uninitialized")
|
||||
# Needed as build-type options may be added after the CXX flag added above.
|
||||
remove_cxx_flag("-Wuninitialized")
|
||||
endif()
|
||||
|
||||
set(INC
|
||||
include
|
||||
)
|
||||
|
|
|
@ -94,7 +94,7 @@ class BVHParams {
|
|||
/* Split time range to this number of steps and create leaf node for each
|
||||
* of this time steps.
|
||||
*
|
||||
* Speeds up rendering of motion primitives in the cost of higher memory usage.
|
||||
* Speeds up rendering of motion primitives at the cost of higher memory usage.
|
||||
*/
|
||||
|
||||
/* Same as above, but for triangle primitives. */
|
||||
|
|
|
@ -717,11 +717,11 @@ extern GHOST_TSuccess GHOST_SetSwapInterval(GHOST_WindowHandle windowhandle, int
|
|||
/**
|
||||
* Gets the current swap interval for #swapBuffers.
|
||||
* \param windowhandle: The handle to the window
|
||||
* \param intervalOut: pointer to location to return swap interval
|
||||
* \param r_interval: pointer to location to return swap interval
|
||||
* (left untouched if there is an error)
|
||||
* \return A boolean success indicator of if swap interval was successfully read.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_GetSwapInterval(GHOST_WindowHandle windowhandle, int *intervalOut);
|
||||
extern GHOST_TSuccess GHOST_GetSwapInterval(GHOST_WindowHandle windowhandle, int *r_interval);
|
||||
|
||||
/**
|
||||
* Activates the drawing context of this window.
|
||||
|
|
|
@ -715,11 +715,11 @@ GHOST_TSuccess GHOST_SetSwapInterval(GHOST_WindowHandle windowhandle, int interv
|
|||
return window->setSwapInterval(interval);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_GetSwapInterval(GHOST_WindowHandle windowhandle, int *intervalOut)
|
||||
GHOST_TSuccess GHOST_GetSwapInterval(GHOST_WindowHandle windowhandle, int *r_interval)
|
||||
{
|
||||
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
|
||||
|
||||
return window->getSwapInterval(*intervalOut);
|
||||
return window->getSwapInterval(*r_interval);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandle)
|
||||
|
|
|
@ -420,7 +420,7 @@ void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button,
|
|||
GHOST_ASSERT(button > NDOF_BUTTON_NONE && button < NDOF_BUTTON_NUM,
|
||||
"rogue button trying to escape NDOF manager");
|
||||
|
||||
GHOST_EventNDOFButton *event = new GHOST_EventNDOFButton(time, window);
|
||||
const GHOST_EventNDOFButton *event = new GHOST_EventNDOFButton(time, window);
|
||||
GHOST_TEventNDOFButtonData *data = (GHOST_TEventNDOFButtonData *)event->getData();
|
||||
|
||||
data->action = press ? GHOST_kPress : GHOST_kRelease;
|
||||
|
@ -435,7 +435,7 @@ void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key,
|
|||
GHOST_IWindow *window)
|
||||
{
|
||||
GHOST_TEventType type = press ? GHOST_kEventKeyDown : GHOST_kEventKeyUp;
|
||||
GHOST_EventKey *event = new GHOST_EventKey(time, type, window, key, false);
|
||||
const GHOST_EventKey *event = new GHOST_EventKey(time, type, window, key, false);
|
||||
|
||||
system_.pushEvent(event);
|
||||
}
|
||||
|
@ -561,7 +561,7 @@ bool GHOST_NDOFManager::sendMotionEvent()
|
|||
return false;
|
||||
}
|
||||
|
||||
GHOST_EventNDOFMotion *event = new GHOST_EventNDOFMotion(motion_time_, window);
|
||||
const GHOST_EventNDOFMotion *event = new GHOST_EventNDOFMotion(motion_time_, window);
|
||||
GHOST_TEventNDOFMotionData *data = (GHOST_TEventNDOFMotionData *)event->getData();
|
||||
|
||||
/* Scale axis values here to normalize them to around +/- 1
|
||||
|
|
|
@ -837,6 +837,10 @@ struct GWL_Seat {
|
|||
*/
|
||||
xkb_state *state_empty_with_numlock = nullptr;
|
||||
|
||||
/**
|
||||
* The active layout, where a single #xkb_keymap may have multiple layouts.
|
||||
*/
|
||||
xkb_layout_index_t layout_active = 0;
|
||||
} xkb;
|
||||
|
||||
#ifdef WITH_INPUT_IME
|
||||
|
@ -879,7 +883,15 @@ struct GWL_Seat {
|
|||
* so every time a modifier is accessed a string lookup isn't required.
|
||||
* Be sure to check for #XKB_MOD_INVALID before using.
|
||||
*/
|
||||
xkb_mod_index_t xkb_keymap_mod_index[MOD_INDEX_NUM];
|
||||
xkb_mod_index_t xkb_keymap_mod_index[MOD_INDEX_NUM] = {XKB_MOD_INVALID};
|
||||
|
||||
/* Cache result for other modifiers which aren't stored in `xkb_keymap_mod_index`
|
||||
* since their depressed state isn't tracked. */
|
||||
|
||||
/** Cache result of `xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_NUM)`. */
|
||||
xkb_mod_index_t xkb_keymap_mod_index_mod2 = XKB_MOD_INVALID;
|
||||
/** Cache result of `xkb_keymap_mod_get_index(keymap, "NumLock")`. */
|
||||
xkb_mod_index_t xkb_keymap_mod_index_numlock = XKB_MOD_INVALID;
|
||||
|
||||
struct {
|
||||
/** Key repetition in character per second. */
|
||||
|
@ -941,6 +953,39 @@ static GWL_SeatStatePointer *gwl_seat_state_pointer_from_cursor_surface(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Account for changes to #GWL_Seat::xkb::layout_active by running #xkb_state_update_mask
|
||||
* on static states which are used for lookups.
|
||||
*
|
||||
* This is also used when initializing the states.
|
||||
*/
|
||||
static void gwl_seat_key_layout_active_state_update_mask(GWL_Seat *seat)
|
||||
{
|
||||
const xkb_layout_index_t group = seat->xkb.layout_active;
|
||||
const xkb_mod_index_t mod_shift = seat->xkb_keymap_mod_index[MOD_INDEX_SHIFT];
|
||||
const xkb_mod_index_t mod_mod2 = seat->xkb_keymap_mod_index_mod2;
|
||||
const xkb_mod_index_t mod_numlock = seat->xkb_keymap_mod_index_numlock;
|
||||
|
||||
/* Handle `state_empty`. */
|
||||
xkb_state_update_mask(seat->xkb.state_empty, 0, 0, 0, 0, 0, group);
|
||||
|
||||
/* Handle `state_empty_with_shift`. */
|
||||
GHOST_ASSERT((mod_shift == XKB_MOD_INVALID) == (seat->xkb.state_empty_with_shift == nullptr),
|
||||
"Invalid state for SHIFT");
|
||||
if (seat->xkb.state_empty_with_shift) {
|
||||
xkb_state_update_mask(seat->xkb.state_empty_with_shift, 1 << mod_shift, 0, 0, 0, 0, group);
|
||||
}
|
||||
|
||||
/* Handle `state_empty_with_shift`. */
|
||||
GHOST_ASSERT((mod_mod2 == XKB_MOD_INVALID || mod_numlock == XKB_MOD_INVALID) ==
|
||||
(seat->xkb.state_empty_with_numlock == nullptr),
|
||||
"Invalid state for NUMLOCK");
|
||||
if (seat->xkb.state_empty_with_numlock) {
|
||||
xkb_state_update_mask(
|
||||
seat->xkb.state_empty_with_numlock, 1 << mod_mod2, 0, 1 << mod_numlock, 0, 0, group);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \note Caller must lock `timer_mutex`.
|
||||
*/
|
||||
|
@ -1088,6 +1133,9 @@ struct GWL_Display {
|
|||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
GWL_LibDecor_System *libdecor = nullptr;
|
||||
bool libdecor_required = false;
|
||||
#endif
|
||||
#ifdef USE_XDG_INIT_WINDOW_SIZE_HACK
|
||||
bool xdg_decor_ignore_initial_window_size = false;
|
||||
#endif
|
||||
GWL_XDG_Decor_System *xdg_decor = nullptr;
|
||||
|
||||
|
@ -3595,7 +3643,7 @@ static void tablet_tool_handle_proximity_in(void *data,
|
|||
/* In case pressure isn't supported. */
|
||||
td.Pressure = 1.0f;
|
||||
|
||||
GHOST_WindowWayland *win = ghost_wl_surface_user_data(seat->tablet.wl.surface_window);
|
||||
const GHOST_WindowWayland *win = ghost_wl_surface_user_data(seat->tablet.wl.surface_window);
|
||||
|
||||
seat->system->cursor_shape_set(win->getCursorShape());
|
||||
}
|
||||
|
@ -3922,6 +3970,13 @@ static void keyboard_handle_keymap(void *data,
|
|||
|
||||
CLOG_INFO(LOG, 2, "keymap");
|
||||
|
||||
/* Reset in case there was a previous non-zero active layout for the the last key-map.
|
||||
* Note that this is set later by `wl_keyboard_listener::modifiers`, it's possible that handling
|
||||
* the first modifier will run #xkb_state_update_mask again (if the active layout is non-zero)
|
||||
* however as this is only done when the layout changed, it's harmless.
|
||||
* With a single layout - in practice the active layout will be zero. */
|
||||
seat->xkb.layout_active = 0;
|
||||
|
||||
if (seat->xkb.compose_state) {
|
||||
xkb_compose_state_reset(seat->xkb.compose_state);
|
||||
}
|
||||
|
@ -3941,29 +3996,25 @@ static void keyboard_handle_keymap(void *data,
|
|||
const GWL_ModifierInfo &mod_info = g_modifier_info_table[i];
|
||||
seat->xkb_keymap_mod_index[i] = xkb_keymap_mod_get_index(keymap, mod_info.xkb_id);
|
||||
}
|
||||
seat->xkb_keymap_mod_index_mod2 = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_NUM);
|
||||
seat->xkb_keymap_mod_index_numlock = xkb_keymap_mod_get_index(keymap, "NumLock");
|
||||
|
||||
xkb_state_unref(seat->xkb.state_empty_with_shift);
|
||||
seat->xkb.state_empty_with_shift = nullptr;
|
||||
{
|
||||
const xkb_mod_index_t mod_shift = seat->xkb_keymap_mod_index[MOD_INDEX_SHIFT];
|
||||
if (mod_shift != XKB_MOD_INVALID) {
|
||||
seat->xkb.state_empty_with_shift = xkb_state_new(keymap);
|
||||
xkb_state_update_mask(seat->xkb.state_empty_with_shift, (1 << mod_shift), 0, 0, 0, 0, 0);
|
||||
}
|
||||
if (seat->xkb_keymap_mod_index[MOD_INDEX_SHIFT] != XKB_MOD_INVALID) {
|
||||
seat->xkb.state_empty_with_shift = xkb_state_new(keymap);
|
||||
}
|
||||
|
||||
xkb_state_unref(seat->xkb.state_empty_with_numlock);
|
||||
seat->xkb.state_empty_with_numlock = nullptr;
|
||||
if ((seat->xkb_keymap_mod_index_mod2 != XKB_MOD_INVALID) &&
|
||||
(seat->xkb_keymap_mod_index_numlock != XKB_MOD_INVALID))
|
||||
{
|
||||
const xkb_mod_index_t mod2 = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_NUM);
|
||||
const xkb_mod_index_t num = xkb_keymap_mod_get_index(keymap, "NumLock");
|
||||
if (num != XKB_MOD_INVALID && mod2 != XKB_MOD_INVALID) {
|
||||
seat->xkb.state_empty_with_numlock = xkb_state_new(keymap);
|
||||
xkb_state_update_mask(
|
||||
seat->xkb.state_empty_with_numlock, (1 << mod2), 0, (1 << num), 0, 0, 0);
|
||||
}
|
||||
seat->xkb.state_empty_with_numlock = xkb_state_new(keymap);
|
||||
}
|
||||
|
||||
gwl_seat_key_layout_active_state_update_mask(seat);
|
||||
|
||||
#ifdef USE_NON_LATIN_KB_WORKAROUND
|
||||
seat->xkb_use_non_latin_workaround = false;
|
||||
if (seat->xkb.state_empty_with_shift) {
|
||||
|
@ -4126,6 +4177,8 @@ static bool xkb_compose_state_feed_and_get_utf8(
|
|||
break;
|
||||
}
|
||||
case XKB_COMPOSE_COMPOSING: {
|
||||
r_utf8_buf[0] = '\0';
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
case XKB_COMPOSE_COMPOSED: {
|
||||
|
@ -4139,6 +4192,13 @@ static bool xkb_compose_state_feed_and_get_utf8(
|
|||
break;
|
||||
}
|
||||
case XKB_COMPOSE_CANCELLED: {
|
||||
/* NOTE(@ideasman42): QT & GTK ignore these events as well as not inputting any text
|
||||
* so `<Compose><Backspace>` for e.g. causes a cancel and *not* back-space.
|
||||
* This isn't supported under GHOST at the moment.
|
||||
* The key-event could also be ignored but this means tracking held state of
|
||||
* keys wont work properly, so don't do any input and pass in the key-symbol. */
|
||||
r_utf8_buf[0] = '\0';
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -4358,6 +4418,13 @@ static void keyboard_handle_modifiers(void *data,
|
|||
GWL_Seat *seat = static_cast<GWL_Seat *>(data);
|
||||
xkb_state_update_mask(seat->xkb.state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
|
||||
|
||||
/* Account for the active layout changing within the same key-map,
|
||||
* needed so modifiers are detected from the expected layout, see: #115160. */
|
||||
if (group != seat->xkb.layout_active) {
|
||||
seat->xkb.layout_active = group;
|
||||
gwl_seat_key_layout_active_state_update_mask(seat);
|
||||
}
|
||||
|
||||
/* A modifier changed so reset the timer,
|
||||
* see comment in #keyboard_handle_key regarding this behavior. */
|
||||
{
|
||||
|
@ -4845,7 +4912,7 @@ static void gwl_seat_capability_pointer_disable(GWL_Seat *seat)
|
|||
return;
|
||||
}
|
||||
|
||||
zwp_pointer_gestures_v1 *pointer_gestures = seat->system->wp_pointer_gestures_get();
|
||||
const zwp_pointer_gestures_v1 *pointer_gestures = seat->system->wp_pointer_gestures_get();
|
||||
if (pointer_gestures) {
|
||||
#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE
|
||||
{ /* Hold gesture. */
|
||||
|
@ -5964,11 +6031,18 @@ static void global_handle_add(void *data,
|
|||
else {
|
||||
/* Not found. */
|
||||
#ifdef USE_GNOME_NEEDS_LIBDECOR_HACK
|
||||
if (STRPREFIX(interface, "gtk_shell")) { /* `gtk_shell1` at time of writing. */
|
||||
/* `gtk_shell1` at time of writing. */
|
||||
if (STRPREFIX(interface, "gtk_shell")) {
|
||||
/* Only require `libdecor` when built with X11 support,
|
||||
* otherwise there is nothing to fall back on. */
|
||||
display->libdecor_required = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_XDG_INIT_WINDOW_SIZE_HACK
|
||||
/* `org_kde_plasma_shell` at time of writing. */
|
||||
if (STRPREFIX(interface, "org_kde_plasma_shell")) {
|
||||
display->xdg_decor_ignore_initial_window_size = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -6430,7 +6504,7 @@ GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const
|
|||
if (UNLIKELY(!seat)) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_active(seat);
|
||||
const GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_active(seat);
|
||||
if (!seat_state_pointer) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
@ -7403,7 +7477,7 @@ GHOST_TCapabilityFlag GHOST_SystemWayland::getCapabilities() const
|
|||
bool GHOST_SystemWayland::cursor_grab_use_software_display_get(const GHOST_TGrabCursorMode mode)
|
||||
{
|
||||
/* Caller must lock `server_mutex`. */
|
||||
GWL_Seat *seat = gwl_display_seat_active_get(display_);
|
||||
const GWL_Seat *seat = gwl_display_seat_active_get(display_);
|
||||
if (UNLIKELY(!seat)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -7600,6 +7674,13 @@ zxdg_decoration_manager_v1 *GHOST_SystemWayland::xdg_decor_manager_get()
|
|||
return display_->xdg_decor->manager;
|
||||
}
|
||||
|
||||
#ifdef USE_XDG_INIT_WINDOW_SIZE_HACK
|
||||
bool GHOST_SystemWayland::xdg_decor_needs_window_size_hack() const
|
||||
{
|
||||
return display_->xdg_decor_ignore_initial_window_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* End `xdg_decor`. */
|
||||
|
||||
const std::vector<GWL_Output *> &GHOST_SystemWayland::outputs_get() const
|
||||
|
@ -7607,6 +7688,20 @@ const std::vector<GWL_Output *> &GHOST_SystemWayland::outputs_get() const
|
|||
return display_->outputs;
|
||||
}
|
||||
|
||||
const GWL_Output *GHOST_SystemWayland::outputs_get_max_native_size() const
|
||||
{
|
||||
uint64_t area_best = 0;
|
||||
const GWL_Output *output_best = nullptr;
|
||||
for (const GWL_Output *output : display_->outputs) {
|
||||
const uint64_t area_test = (uint64_t)output->size_native[0] * (uint64_t)output->size_native[1];
|
||||
if (output_best == nullptr || area_best < area_test) {
|
||||
output_best = output;
|
||||
area_best = area_test;
|
||||
}
|
||||
}
|
||||
return output_best;
|
||||
}
|
||||
|
||||
wl_shm *GHOST_SystemWayland::wl_shm_get() const
|
||||
{
|
||||
return display_->wl.shm;
|
||||
|
@ -7748,7 +7843,7 @@ GHOST_WindowWayland *ghost_wl_surface_user_data(wl_surface *wl_surface)
|
|||
* Functionality only used for the WAYLAND implementation.
|
||||
* \{ */
|
||||
|
||||
GHOST_TSuccess GHOST_SystemWayland::pushEvent_maybe_pending(GHOST_IEvent *event)
|
||||
GHOST_TSuccess GHOST_SystemWayland::pushEvent_maybe_pending(const GHOST_IEvent *event)
|
||||
{
|
||||
#ifdef USE_EVENT_BACKGROUND_THREAD
|
||||
if (main_thread_id != std::this_thread::get_id()) {
|
||||
|
|
|
@ -230,9 +230,14 @@ class GHOST_SystemWayland : public GHOST_System {
|
|||
#endif
|
||||
struct xdg_wm_base *xdg_decor_shell_get();
|
||||
struct zxdg_decoration_manager_v1 *xdg_decor_manager_get();
|
||||
#ifdef USE_XDG_INIT_WINDOW_SIZE_HACK
|
||||
bool xdg_decor_needs_window_size_hack() const;
|
||||
#endif
|
||||
/* End `xdg_decor`. */
|
||||
|
||||
const std::vector<GWL_Output *> &outputs_get() const;
|
||||
/** Return the output with the largest pixel-area. */
|
||||
const GWL_Output *outputs_get_max_native_size() const;
|
||||
|
||||
struct wl_shm *wl_shm_get() const;
|
||||
|
||||
|
@ -248,7 +253,7 @@ class GHOST_SystemWayland : public GHOST_System {
|
|||
* Push an event, with support for calling from a thread.
|
||||
* NOTE: only needed for `USE_EVENT_BACKGROUND_THREAD`.
|
||||
*/
|
||||
GHOST_TSuccess pushEvent_maybe_pending(GHOST_IEvent *event);
|
||||
GHOST_TSuccess pushEvent_maybe_pending(const GHOST_IEvent *event);
|
||||
|
||||
/** Set this seat to be active. */
|
||||
void seat_active_set(const struct GWL_Seat *seat);
|
||||
|
|
|
@ -1761,7 +1761,8 @@ bool GHOST_SystemX11::generateWindowExposeEvents()
|
|||
bool anyProcessed = false;
|
||||
|
||||
for (; w_start != w_end; ++w_start) {
|
||||
GHOST_Event *g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, *w_start);
|
||||
const GHOST_Event *g_event = new GHOST_Event(
|
||||
getMilliSeconds(), GHOST_kEventWindowUpdate, *w_start);
|
||||
|
||||
(*w_start)->validate();
|
||||
|
||||
|
|
|
@ -103,6 +103,9 @@ struct WGL_XDG_Decor_Window {
|
|||
|
||||
/** The window has been configured (see #xdg_surface_ack_configure). */
|
||||
bool initial_configure_seen = false;
|
||||
#ifdef USE_XDG_INIT_WINDOW_SIZE_HACK
|
||||
bool initial_configure_seen_with_size = false;
|
||||
#endif
|
||||
};
|
||||
|
||||
static void gwl_xdg_decor_window_destroy(WGL_XDG_Decor_Window *decor)
|
||||
|
@ -988,11 +991,8 @@ static int outputs_uniform_scale_or_default(const std::vector<GWL_Output *> &out
|
|||
static CLG_LogRef LOG_WL_XDG_TOPLEVEL = {"ghost.wl.handle.xdg_toplevel"};
|
||||
#define LOG (&LOG_WL_XDG_TOPLEVEL)
|
||||
|
||||
static void xdg_toplevel_handle_configure(void *data,
|
||||
xdg_toplevel * /*xdg_toplevel*/,
|
||||
const int32_t width,
|
||||
const int32_t height,
|
||||
wl_array *states)
|
||||
static void xdg_toplevel_handle_configure(
|
||||
void *data, xdg_toplevel * /*xdg_toplevel*/, int32_t width, int32_t height, wl_array *states)
|
||||
{
|
||||
/* TODO: log `states`, not urgent. */
|
||||
CLOG_INFO(LOG, 2, "configure (size=[%d, %d])", width, height);
|
||||
|
@ -1003,17 +1003,6 @@ static void xdg_toplevel_handle_configure(void *data,
|
|||
std::lock_guard lock_frame_guard{win->frame_pending_mutex};
|
||||
#endif
|
||||
|
||||
const int32_t size[2] = {width, height};
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (size[i] == 0) {
|
||||
/* Values may be zero, in this case the client should choose. */
|
||||
continue;
|
||||
}
|
||||
win->frame_pending.size[i] = win->frame.fractional_scale ?
|
||||
gwl_window_fractional_to_viewport_round(win->frame, size[i]) :
|
||||
(size[i] * win->frame.buffer_scale);
|
||||
}
|
||||
|
||||
win->frame_pending.is_maximised = false;
|
||||
win->frame_pending.is_fullscreen = false;
|
||||
win->frame_pending.is_active = false;
|
||||
|
@ -1034,6 +1023,46 @@ static void xdg_toplevel_handle_configure(void *data,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_XDG_INIT_WINDOW_SIZE_HACK
|
||||
if (width || height) {
|
||||
WGL_XDG_Decor_Window &decor = *win->xdg_decor;
|
||||
if (decor.initial_configure_seen_with_size == false) {
|
||||
if (win->ghost_system->xdg_decor_needs_window_size_hack() &&
|
||||
(decor.mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE) &&
|
||||
(win->frame_pending.is_maximised == false &&
|
||||
win->frame_pending.is_fullscreen == false) &&
|
||||
/* Account for the initial size being smaller. */
|
||||
((width <= win->frame.size[0]) && (height <= win->frame.size[1])))
|
||||
{
|
||||
/* Fail safe, check the window is *not* larger than all available outputs
|
||||
* as this could cause files saved on other peoples systems to create
|
||||
* unreasonably large windows. */
|
||||
const GWL_Output *output_big = win->ghost_system->outputs_get_max_native_size();
|
||||
if (output_big &&
|
||||
((output_big->size_native[0] < width) || (output_big->size_native[1] < height))) {
|
||||
/* Pass, the window exceeds the size of the largest output, ignore initial size. */
|
||||
}
|
||||
else {
|
||||
width = win->frame.size[0];
|
||||
height = win->frame.size[1];
|
||||
}
|
||||
}
|
||||
decor.initial_configure_seen_with_size = true;
|
||||
}
|
||||
}
|
||||
#endif /* USE_XDG_INIT_WINDOW_SIZE_HACK */
|
||||
|
||||
const int32_t size[2] = {width, height};
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (size[i] == 0) {
|
||||
/* Values may be zero, in this case the client should choose. */
|
||||
continue;
|
||||
}
|
||||
win->frame_pending.size[i] = win->frame.fractional_scale ?
|
||||
gwl_window_fractional_to_viewport_round(win->frame, size[i]) :
|
||||
(size[i] * win->frame.buffer_scale);
|
||||
}
|
||||
}
|
||||
|
||||
static void xdg_toplevel_handle_close(void *data, xdg_toplevel * /*xdg_toplevel*/)
|
||||
|
@ -1141,7 +1170,7 @@ static void libdecor_frame_handle_configure(libdecor_frame *frame,
|
|||
# ifdef USE_EVENT_BACKGROUND_THREAD
|
||||
std::lock_guard lock_frame_guard{static_cast<GWL_Window *>(data)->frame_pending_mutex};
|
||||
const bool is_main_thread = [data] {
|
||||
GWL_Window *win = static_cast<GWL_Window *>(data);
|
||||
const GWL_Window *win = static_cast<GWL_Window *>(data);
|
||||
const GHOST_SystemWayland *system = win->ghost_system;
|
||||
return system->main_thread_id == std::this_thread::get_id();
|
||||
}();
|
||||
|
|
|
@ -54,6 +54,14 @@
|
|||
*/
|
||||
#define USE_EVENT_BACKGROUND_THREAD
|
||||
|
||||
/**
|
||||
* Hack for KDE where the initial window size includes window decorations (title-bar, borders etc),
|
||||
* making the usable region smaller than requested. As the size of decorations is unknown:
|
||||
* account for this by ignoring the initial size and using the size requested from GHOST instead
|
||||
* (with some exceptions & sanity checks for overly large windows), see: #113059.
|
||||
*/
|
||||
#define USE_XDG_INIT_WINDOW_SIZE_HACK
|
||||
|
||||
class GHOST_SystemWayland;
|
||||
|
||||
struct GWL_Output;
|
||||
|
|
|
@ -14,14 +14,44 @@ def keyconfig_update(keyconfig_data, keyconfig_version):
|
|||
|
||||
# Version the key-map.
|
||||
import copy
|
||||
|
||||
# Only copy once.
|
||||
has_copy = False
|
||||
|
||||
def get_transform_modal_map():
|
||||
for km_name, _km_parms, km_items_data in keyconfig_data:
|
||||
for km_name, _km_params, km_items_data in keyconfig_data:
|
||||
if km_name == "Transform Modal Map":
|
||||
return km_items_data
|
||||
print("not found")
|
||||
|
||||
def remove_properties(op_prop_map):
|
||||
nonlocal keyconfig_data
|
||||
nonlocal has_copy
|
||||
|
||||
changed_items = []
|
||||
for kmi_index, (km_name, _km_parms, km_items_data) in enumerate(keyconfig_data):
|
||||
for kmi_item_index, (item_op, item_event, item_prop) in enumerate(km_items_data["items"]):
|
||||
if item_prop and item_op in op_prop_map:
|
||||
properties = item_prop.get("properties", [])
|
||||
filtered_properties = [
|
||||
prop for prop in properties if not any(
|
||||
key in prop for key in op_prop_map[item_op])
|
||||
]
|
||||
|
||||
if not filtered_properties:
|
||||
filtered_properties = None
|
||||
|
||||
if filtered_properties is None or len(filtered_properties) < len(properties):
|
||||
changed_items.append((kmi_index, kmi_item_index, filtered_properties))
|
||||
|
||||
if changed_items:
|
||||
if not has_copy:
|
||||
keyconfig_data = copy.deepcopy(keyconfig_data)
|
||||
has_copy = True
|
||||
|
||||
for kmi_index, kmi_item_index, filtered_properties in changed_items:
|
||||
item_op, item_event, item_prop = keyconfig_data[kmi_index][2]["items"][kmi_item_index]
|
||||
item_prop["properties"] = filtered_properties
|
||||
keyconfig_data[kmi_index][2]["items"][kmi_item_index] = (item_op, item_event, item_prop)
|
||||
|
||||
# Default repeat to false.
|
||||
if keyconfig_version <= (2, 92, 0):
|
||||
|
@ -97,6 +127,20 @@ def keyconfig_update(keyconfig_data, keyconfig_version):
|
|||
km_items_data["items"].append(("EDIT_SNAP_SOURCE_OFF", {"type": 'B', "value": 'PRESS'}, None))
|
||||
|
||||
if keyconfig_version <= (4, 1, 5):
|
||||
remove_properties({
|
||||
"transform.translate": ["alt_navigation"],
|
||||
"transform.rotate": ["alt_navigation"],
|
||||
"transform.resize": ["alt_navigation"],
|
||||
"view3d.edit_mesh_extrude_move_normal": ["alt_navigation"],
|
||||
"armature.extrude_move": ["TRANSFORM_OT_translate"],
|
||||
"curve.extrude_move": ["TRANSFORM_OT_translate"],
|
||||
"gpencil.extrude_move": ["TRANSFORM_OT_translate"],
|
||||
"mesh.rip_edge_move": ["TRANSFORM_OT_translate"],
|
||||
"mesh.duplicate_move": ["TRANSFORM_OT_translate"],
|
||||
"object.duplicate_move": ["TRANSFORM_OT_translate"],
|
||||
"object.duplicate_move_linked": ["TRANSFORM_OT_translate"],
|
||||
})
|
||||
|
||||
if km_items_data := get_transform_modal_map():
|
||||
def use_alt_navigate():
|
||||
km_item = next((i for i in km_items_data["items"] if i[0] ==
|
||||
|
|
|
@ -336,17 +336,14 @@ def draw_filtered(display_keymaps, filter_type, filter_text, layout):
|
|||
if filtered_items:
|
||||
col = layout.column()
|
||||
|
||||
row = col.row()
|
||||
row = col.row(align=True)
|
||||
row.label(text=km.name, icon='DOT',
|
||||
text_ctxt=i18n_contexts.id_windowmanager)
|
||||
|
||||
row.label()
|
||||
row.label()
|
||||
|
||||
if km.is_user_modified:
|
||||
row.operator("preferences.keymap_restore", text="Restore")
|
||||
else:
|
||||
row.label()
|
||||
subrow = row.row()
|
||||
subrow.alignment = 'RIGHT'
|
||||
subrow.operator("preferences.keymap_restore", text="Restore")
|
||||
|
||||
for kmi in filtered_items:
|
||||
draw_kmi(display_keymaps, kc, km, kmi, col, 1)
|
||||
|
|
|
@ -407,8 +407,6 @@ class NODE_MT_geometry_node_GEO_MESH_OPERATIONS(Menu):
|
|||
node_add_menu.add_node_type(layout, "GeometryNodeMeshBoolean")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshToCurve")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshToPoints")
|
||||
if context.preferences.experimental.use_new_volume_nodes:
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshToSDFVolume")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshToVolume")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeScaleElements")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSplitEdges")
|
||||
|
@ -475,8 +473,6 @@ class NODE_MT_category_GEO_POINT(Menu):
|
|||
node_add_menu.add_node_type(layout, "GeometryNodePoints")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodePointsToCurves")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodePointsToVertices")
|
||||
if context.preferences.experimental.use_new_volume_nodes:
|
||||
node_add_menu.add_node_type(layout, "GeometryNodePointsToSDFVolume")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodePointsToVolume")
|
||||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSetPointRadius")
|
||||
|
@ -637,13 +633,6 @@ class NODE_MT_category_GEO_VOLUME(Menu):
|
|||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeVolumeCube")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeVolumeToMesh")
|
||||
if context.preferences.experimental.use_new_volume_nodes:
|
||||
layout.separator()
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeanFilterSDFVolume")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeOffsetSDFVolume")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSampleVolume")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSDFVolumeSphere")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputSignedDistance")
|
||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ class GPENCIL_MT_material_context_menu(Menu):
|
|||
|
||||
layout.operator("grease_pencil.material_lock_all", icon='LOCKED', text="Lock All")
|
||||
layout.operator("grease_pencil.material_unlock_all", icon='UNLOCKED', text="Unlock All")
|
||||
layout.operator("grease_pencil.material_lock_unselected", text="Lock Unselected")
|
||||
layout.operator("grease_pencil.material_lock_unused", text="Lock Unused")
|
||||
else:
|
||||
layout.operator("gpencil.material_reveal", icon='RESTRICT_VIEW_OFF', text="Show All")
|
||||
|
|
|
@ -194,7 +194,8 @@ int insert_key_action(Main *bmain,
|
|||
eInsertKeyFlags insert_key_flag,
|
||||
eBezTriple_KeyframeType key_type);
|
||||
|
||||
/** Insert keys to the ID of the given PointerRNA for the given RNA paths. Tries to create an
|
||||
/**
|
||||
* Insert keys to the ID of the given PointerRNA for the given RNA paths. Tries to create an
|
||||
* action if none exists yet.
|
||||
* \param scene_frame is expected to be not NLA mapped as that happens within the function.
|
||||
*/
|
||||
|
|
|
@ -64,11 +64,13 @@ FCurve *action_fcurve_ensure(Main *bmain,
|
|||
/* For Loc/Rot/Scale and also Color F-Curves, the color of the F-Curve in the Graph Editor,
|
||||
* is determined by the array index for the F-Curve.
|
||||
*/
|
||||
PropertyRNA *prop;
|
||||
PointerRNA r_ptr;
|
||||
const bool resolved = RNA_path_resolve_property(ptr, rna_path, &r_ptr, &prop);
|
||||
PropertyRNA *resolved_prop;
|
||||
PointerRNA resolved_ptr;
|
||||
PointerRNA id_ptr = RNA_id_pointer_create(ptr->owner_id);
|
||||
const bool resolved = RNA_path_resolve_property(
|
||||
&id_ptr, rna_path, &resolved_ptr, &resolved_prop);
|
||||
if (resolved) {
|
||||
PropertySubType prop_subtype = RNA_property_subtype(prop);
|
||||
PropertySubType prop_subtype = RNA_property_subtype(resolved_prop);
|
||||
if (ELEM(prop_subtype, PROP_TRANSLATION, PROP_XYZ, PROP_EULER, PROP_COLOR, PROP_COORDS)) {
|
||||
fcu->color_mode = FCURVE_COLOR_AUTO_RGB;
|
||||
}
|
||||
|
@ -86,7 +88,7 @@ FCurve *action_fcurve_ensure(Main *bmain,
|
|||
|
||||
/* Sync bone group colors if applicable. */
|
||||
if (ptr && (ptr->type == &RNA_PoseBone)) {
|
||||
bPoseChannel *pchan = static_cast<bPoseChannel *>(ptr->data);
|
||||
const bPoseChannel *pchan = static_cast<const bPoseChannel *>(ptr->data);
|
||||
action_group_colors_set_from_posebone(agrp, pchan);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -309,9 +309,11 @@ class AssetCatalogCollection {
|
|||
static OwningAssetCatalogMap copy_catalog_map(const OwningAssetCatalogMap &orig);
|
||||
};
|
||||
|
||||
/** Keeps track of which catalogs are defined in a certain file on disk.
|
||||
/**
|
||||
* Keeps track of which catalogs are defined in a certain file on disk.
|
||||
* Only contains non-owning pointers to the #AssetCatalog instances, so ensure the lifetime of this
|
||||
* class is shorter than that of the #`AssetCatalog`s themselves. */
|
||||
* class is shorter than that of the #`AssetCatalog`s themselves.
|
||||
*/
|
||||
class AssetCatalogDefinitionFile {
|
||||
protected:
|
||||
/* Catalogs stored in this file. They are mapped by ID to make it possible to query whether a
|
||||
|
|
|
@ -42,8 +42,10 @@ void AS_asset_library_refresh_catalog_simplename(struct AssetLibrary *asset_libr
|
|||
/** Return whether any loaded AssetLibrary has unsaved changes to its catalogs. */
|
||||
bool AS_asset_library_has_any_unsaved_catalogs(void);
|
||||
|
||||
/** An asset library can include local IDs (IDs in the current file). Their pointers need to be
|
||||
* remapped on change (or assets removed as IDs gets removed). */
|
||||
/**
|
||||
* An asset library can include local IDs (IDs in the current file). Their pointers need to be
|
||||
* remapped on change (or assets removed as IDs gets removed).
|
||||
*/
|
||||
void AS_asset_library_remap_ids(const struct IDRemapper *mappings);
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,8 +19,10 @@
|
|||
|
||||
namespace blender::asset_system::tests {
|
||||
|
||||
/** Sets up asset library loading so we have a library to load asset representations into (required
|
||||
* for some functionality to perform work). */
|
||||
/**
|
||||
* Sets up asset library loading so we have a library to load asset representations into (required
|
||||
* for some functionality to perform work).
|
||||
*/
|
||||
class AssetRepresentationTest : public AssetLibraryTestBase {
|
||||
public:
|
||||
AssetLibrary *get_builtin_library_from_type(eAssetLibraryType type)
|
||||
|
|
|
@ -29,7 +29,7 @@ extern "C" {
|
|||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 8
|
||||
#define BLENDER_FILE_SUBVERSION 9
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and cancel loading the file, showing a warning to
|
||||
|
|
|
@ -11,9 +11,10 @@
|
|||
|
||||
#include <mutex>
|
||||
|
||||
#include "BLI_bit_vector.hh"
|
||||
#include "BLI_bit_span.hh"
|
||||
#include "BLI_kdopbvh.h"
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_span.hh"
|
||||
|
||||
struct BMEditMesh;
|
||||
struct BVHCache;
|
||||
|
@ -49,11 +50,12 @@ struct BVHTreeFromMesh {
|
|||
BVHTree_RayCastCallback raycast_callback;
|
||||
|
||||
/* Vertex array, so that callbacks have instant access to data. */
|
||||
const float (*vert_positions)[3];
|
||||
const vec2i *edge;
|
||||
blender::Span<blender::float3> vert_positions;
|
||||
blender::Span<blender::int2> edges;
|
||||
blender::Span<int> corner_verts;
|
||||
blender::Span<MLoopTri> looptris;
|
||||
|
||||
const MFace *face;
|
||||
const int *corner_verts;
|
||||
const MLoopTri *looptri;
|
||||
|
||||
/* Private data */
|
||||
bool cached;
|
||||
|
@ -110,8 +112,7 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data,
|
|||
* (else will be computed from mask).
|
||||
*/
|
||||
BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data,
|
||||
const float (*vert_positions)[3],
|
||||
int verts_num,
|
||||
blender::Span<blender::float3> vert_positions,
|
||||
blender::BitSpan verts_mask,
|
||||
int verts_num_active,
|
||||
float epsilon,
|
||||
|
@ -141,9 +142,8 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data,
|
|||
* (else will be computed from mask).
|
||||
*/
|
||||
BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
|
||||
const float (*vert_positions)[3],
|
||||
const blender::int2 *edge,
|
||||
int edges_num,
|
||||
blender::Span<blender::float3> vert_positions,
|
||||
blender::Span<blender::int2> edges,
|
||||
blender::BitSpan edges_mask,
|
||||
int edges_num_active,
|
||||
float epsilon,
|
||||
|
@ -168,10 +168,9 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
|
|||
* Builds a BVH-tree where nodes are the looptri faces of the given mesh.
|
||||
*/
|
||||
BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
|
||||
const float (*vert_positions)[3],
|
||||
const int *corner_verts,
|
||||
const MLoopTri *looptri,
|
||||
int looptri_num,
|
||||
blender::Span<blender::float3> vert_positions,
|
||||
blender::Span<int> corner_verts,
|
||||
blender::Span<MLoopTri> looptris,
|
||||
blender::BitSpan mask,
|
||||
int looptri_num_active,
|
||||
float epsilon,
|
||||
|
|
|
@ -220,8 +220,10 @@ struct ListBase BKE_collection_object_cache_get(struct Collection *collection);
|
|||
ListBase BKE_collection_object_cache_instanced_get(struct Collection *collection);
|
||||
/** Free the object cache of given `collection` and all of its ancestors (recursively). */
|
||||
void BKE_collection_object_cache_free(struct Collection *collection);
|
||||
/** Free the object cache of all collections in given `bmain`, including master collections of
|
||||
* scenes. */
|
||||
/**
|
||||
* Free the object cache of all collections in given `bmain`, including master collections of
|
||||
* scenes.
|
||||
*/
|
||||
void BKE_main_collections_object_cache_free(const struct Main *bmain);
|
||||
|
||||
struct Base *BKE_collection_or_layer_objects(const struct Scene *scene,
|
||||
|
@ -312,8 +314,10 @@ bool BKE_collection_validate(struct Collection *collection);
|
|||
|
||||
/* .blend file I/O */
|
||||
|
||||
/** Perform some pre-writing cleanup on the COllection data itself (_not_ in any sub-data
|
||||
* referenced by pointers). To be called before writing the Collection struct itself. */
|
||||
/**
|
||||
* Perform some pre-writing cleanup on the COllection data itself (_not_ in any sub-data
|
||||
* referenced by pointers). To be called before writing the Collection struct itself.
|
||||
*/
|
||||
void BKE_collection_blend_write_prepare_nolib(struct BlendWriter *writer,
|
||||
struct Collection *collection);
|
||||
void BKE_collection_blend_write_nolib(struct BlendWriter *writer, struct Collection *collection);
|
||||
|
@ -372,10 +376,11 @@ void BKE_scene_objects_iterator_begin(struct BLI_Iterator *iter, void *data_in);
|
|||
void BKE_scene_objects_iterator_next(struct BLI_Iterator *iter);
|
||||
void BKE_scene_objects_iterator_end(struct BLI_Iterator *iter);
|
||||
|
||||
/** Iterate over objects in the scene based on a flag.
|
||||
/**
|
||||
* Iterate over objects in the scene based on a flag.
|
||||
*
|
||||
* \note The object->flag is tested against flag.
|
||||
* */
|
||||
*/
|
||||
typedef struct SceneObjectsIteratorExData {
|
||||
struct Scene *scene;
|
||||
int flag;
|
||||
|
|
|
@ -316,8 +316,8 @@ bool BKE_library_ID_is_indirectly_used(struct Main *bmain, void *idv);
|
|||
*/
|
||||
void BKE_library_ID_test_usages(struct Main *bmain,
|
||||
void *idv,
|
||||
bool *is_used_local,
|
||||
bool *is_used_linked);
|
||||
bool *r_is_used_local,
|
||||
bool *r_is_used_linked);
|
||||
|
||||
/**
|
||||
* Tag all unused IDs (a.k.a 'orphaned').
|
||||
|
|
|
@ -115,19 +115,6 @@ void BKE_mesh_ensure_default_orig_index_customdata(struct Mesh *mesh);
|
|||
*/
|
||||
void BKE_mesh_ensure_default_orig_index_customdata_no_check(struct Mesh *mesh);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/**
|
||||
* Sets each output array element to the edge index if it is a real edge, or -1.
|
||||
*/
|
||||
void BKE_mesh_looptri_get_real_edges(const blender::int2 *edges,
|
||||
const int *corner_verts,
|
||||
const int *corner_edges,
|
||||
const struct MLoopTri *tri,
|
||||
int r_edges[3]);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Free (or release) any data used by this mesh (does not free the mesh itself).
|
||||
* Only use for undo, in most cases `BKE_id_free(nullptr, me)` should be used.
|
||||
|
@ -227,14 +214,6 @@ void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigne
|
|||
void BKE_mesh_smooth_flag_set(struct Mesh *me, bool use_smooth);
|
||||
void BKE_mesh_sharp_edges_set_from_angle(struct Mesh *me, float angle);
|
||||
|
||||
/**
|
||||
* Used for unit testing; compares two meshes, checking only
|
||||
* differences we care about. should be usable with leaf's
|
||||
* testing framework I get RNA work done, will use hackish
|
||||
* testing code for now.
|
||||
*/
|
||||
const char *BKE_mesh_cmp(struct Mesh *me1, struct Mesh *me2, float thresh);
|
||||
|
||||
void BKE_mesh_texspace_calc(struct Mesh *me);
|
||||
void BKE_mesh_texspace_ensure(struct Mesh *me);
|
||||
void BKE_mesh_texspace_get(struct Mesh *me,
|
||||
|
@ -299,26 +278,6 @@ void BKE_mesh_mselect_active_set(struct Mesh *me, int index, int type);
|
|||
|
||||
void BKE_mesh_count_selected_items(const struct Mesh *mesh, int r_count[3]);
|
||||
|
||||
float (*BKE_mesh_vert_coords_alloc(const struct Mesh *mesh, int *r_vert_len))[3];
|
||||
|
||||
void BKE_mesh_vert_coords_apply_with_mat4(struct Mesh *mesh,
|
||||
const float (*vert_coords)[3],
|
||||
const float mat[4][4]);
|
||||
void BKE_mesh_vert_coords_apply(struct Mesh *mesh, const float (*vert_coords)[3]);
|
||||
|
||||
/* *** mesh_tessellate.cc *** */
|
||||
|
||||
/**
|
||||
* See #bke::mesh::looptris_calc
|
||||
*/
|
||||
void BKE_mesh_recalc_looptri(const int *corner_verts,
|
||||
const int *face_offsets,
|
||||
const float (*vert_positions)[3],
|
||||
int totvert,
|
||||
int totloop,
|
||||
int faces_num,
|
||||
struct MLoopTri *mlooptri);
|
||||
|
||||
/* *** mesh_normals.cc *** */
|
||||
|
||||
/** Return true if the mesh vertex normals either are not stored or are dirty. */
|
||||
|
@ -572,16 +531,6 @@ bool BKE_mesh_validate_material_indices(struct Mesh *me);
|
|||
* Validate the mesh, \a do_fixes requires \a mesh to be non-null.
|
||||
*
|
||||
* \return false if no changes needed to be made.
|
||||
*
|
||||
* Vertex Normals
|
||||
* ==============
|
||||
*
|
||||
* While zeroed normals are checked, these checks aren't comprehensive.
|
||||
* Technically, to detect errors here a normal recalculation and comparison is necessary.
|
||||
* However this function is mainly to prevent severe errors in geometry
|
||||
* (invalid data that will crash Blender, or cause some features to behave incorrectly),
|
||||
* not to detect subtle differences in the resulting normals which could be caused
|
||||
* by importers that load normals (for example).
|
||||
*/
|
||||
bool BKE_mesh_validate_arrays(struct Mesh *me,
|
||||
float (*vert_positions)[3],
|
||||
|
@ -682,22 +631,6 @@ BLI_INLINE int *BKE_mesh_material_indices_for_write(Mesh *mesh)
|
|||
&mesh->face_data, CD_PROP_INT32, CD_SET_DEFAULT, mesh->faces_num, "material_index");
|
||||
}
|
||||
|
||||
BLI_INLINE const float (*BKE_mesh_vert_positions(const Mesh *mesh))[3]
|
||||
{
|
||||
return (const float(*)[3])CustomData_get_layer_named(
|
||||
&mesh->vert_data, CD_PROP_FLOAT3, "position");
|
||||
}
|
||||
|
||||
BLI_INLINE const int *BKE_mesh_face_offsets(const Mesh *mesh)
|
||||
{
|
||||
return mesh->face_offset_indices;
|
||||
}
|
||||
|
||||
BLI_INLINE const int *BKE_mesh_corner_verts(const Mesh *mesh)
|
||||
{
|
||||
return (const int *)CustomData_get_layer_named(&mesh->loop_data, CD_PROP_INT32, ".corner_vert");
|
||||
}
|
||||
|
||||
BLI_INLINE const MDeformVert *BKE_mesh_deform_verts(const Mesh *mesh)
|
||||
{
|
||||
return (const MDeformVert *)CustomData_get_layer(&mesh->vert_data, CD_MDEFORMVERT);
|
||||
|
|
|
@ -44,6 +44,12 @@ void looptris_calc_with_normals(Span<float3> vert_positions,
|
|||
|
||||
void looptris_calc_face_indices(OffsetIndices<int> faces, MutableSpan<int> looptri_faces);
|
||||
|
||||
/** Return the triangle's three edge indices they are real edges, otherwise -1. */
|
||||
int3 looptri_get_real_edges(Span<int2> edges,
|
||||
Span<int> corner_verts,
|
||||
Span<int> corner_edges,
|
||||
const MLoopTri &tri);
|
||||
|
||||
/** Calculate the average position of the vertices in the face. */
|
||||
float3 face_center_calc(Span<float3> vert_positions, Span<int> face_verts);
|
||||
|
||||
|
|
|
@ -30,7 +30,9 @@ enum eMeshFairingDepth {
|
|||
* Affect_vertices is used to define the fairing area. Indexed by vertex index, set to true when
|
||||
* the vertex should be modified by fairing.
|
||||
*/
|
||||
void BKE_bmesh_prefair_and_fair_verts(BMesh *bm, bool *affect_verts, eMeshFairingDepth depth);
|
||||
void BKE_bmesh_prefair_and_fair_verts(BMesh *bm,
|
||||
const bool affected_verts[],
|
||||
eMeshFairingDepth depth);
|
||||
|
||||
/**
|
||||
* This function can optionally use the vertex coordinates of deform_mverts to read and write the
|
||||
|
@ -38,5 +40,5 @@ void BKE_bmesh_prefair_and_fair_verts(BMesh *bm, bool *affect_verts, eMeshFairin
|
|||
*/
|
||||
void BKE_mesh_prefair_and_fair_verts(Mesh *mesh,
|
||||
blender::MutableSpan<blender::float3> deform_vert_positions,
|
||||
bool *affect_verts,
|
||||
const bool affected_verts[],
|
||||
eMeshFairingDepth depth);
|
||||
|
|
|
@ -53,19 +53,19 @@ enum class MeshNormalDomain : int8_t {
|
|||
* Only #Mesh::face_normals() is necessary. This case is generally the best
|
||||
* for performance, since no mixing is necessary and multithreading is simple.
|
||||
*/
|
||||
Face,
|
||||
Face = 0,
|
||||
/**
|
||||
* The mesh is completely smooth shaded; there are no sharp face or edges. Only
|
||||
* #Mesh::vert_normals() is necessary. Calculating face normals is still necessary though,
|
||||
* since they have to be mixed to become vertex normals.
|
||||
*/
|
||||
Point,
|
||||
Point = 1,
|
||||
/**
|
||||
* The mesh has mixed smooth and sharp shading. In order to split the normals on each side of
|
||||
* sharp edges, they need to be processed per-face-corner. Normals can be retrieved with
|
||||
* #Mesh::corner_normals().
|
||||
*/
|
||||
Corner,
|
||||
Corner = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -46,21 +46,21 @@ struct ImBuf *BKE_movieclip_get_postprocessed_ibuf(struct MovieClip *clip,
|
|||
int postprocess_flag);
|
||||
struct ImBuf *BKE_movieclip_get_stable_ibuf(struct MovieClip *clip,
|
||||
const struct MovieClipUser *user,
|
||||
float loc[2],
|
||||
float *scale,
|
||||
float *angle,
|
||||
int postprocess_flag);
|
||||
int postprocess_flag,
|
||||
float r_loc[2],
|
||||
float *r_scale,
|
||||
float *r_angle);
|
||||
struct ImBuf *BKE_movieclip_get_ibuf_flag(struct MovieClip *clip,
|
||||
const struct MovieClipUser *user,
|
||||
int flag,
|
||||
int cache_flag);
|
||||
void BKE_movieclip_get_size(struct MovieClip *clip,
|
||||
const struct MovieClipUser *user,
|
||||
int *width,
|
||||
int *height);
|
||||
int *r_width,
|
||||
int *r_height);
|
||||
void BKE_movieclip_get_size_fl(struct MovieClip *clip,
|
||||
const struct MovieClipUser *user,
|
||||
float size[2]);
|
||||
float r_size[2]);
|
||||
int BKE_movieclip_get_duration(struct MovieClip *clip);
|
||||
float BKE_movieclip_get_fps(struct MovieClip *clip);
|
||||
void BKE_movieclip_get_aspect(struct MovieClip *clip, float *aspx, float *aspy);
|
||||
|
|
|
@ -78,10 +78,8 @@ Mesh *BKE_multires_create_mesh(Depsgraph *depsgraph, Object *object, MultiresMod
|
|||
* Get coordinates of a deformed base mesh which is an input to the given multi-res modifier.
|
||||
* \note The modifiers will be re-evaluated.
|
||||
*/
|
||||
float (*BKE_multires_create_deformed_base_mesh_vert_coords(Depsgraph *depsgraph,
|
||||
Object *object,
|
||||
MultiresModifierData *mmd,
|
||||
int *r_num_deformed_verts))[3];
|
||||
blender::Array<blender::float3> BKE_multires_create_deformed_base_mesh_vert_coords(
|
||||
Depsgraph *depsgraph, Object *object, MultiresModifierData *mmd);
|
||||
|
||||
/**
|
||||
* \param direction: 1 for delete higher, 0 for lower (not implemented yet).
|
||||
|
|
|
@ -1291,17 +1291,17 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
|
|||
#define GEO_NODE_IMAGE 1191
|
||||
#define GEO_NODE_INTERPOLATE_CURVES 1192
|
||||
#define GEO_NODE_EDGES_TO_FACE_GROUPS 1193
|
||||
#define GEO_NODE_POINTS_TO_SDF_VOLUME 1194
|
||||
#define GEO_NODE_MESH_TO_SDF_VOLUME 1195
|
||||
#define GEO_NODE_SDF_VOLUME_SPHERE 1196
|
||||
#define GEO_NODE_MEAN_FILTER_SDF_VOLUME 1197
|
||||
#define GEO_NODE_OFFSET_SDF_VOLUME 1198
|
||||
// #define GEO_NODE_POINTS_TO_SDF_VOLUME 1194
|
||||
// #define GEO_NODE_MESH_TO_SDF_VOLUME 1195
|
||||
// #define GEO_NODE_SDF_VOLUME_SPHERE 1196
|
||||
// #define GEO_NODE_MEAN_FILTER_SDF_VOLUME 1197
|
||||
// #define GEO_NODE_OFFSET_SDF_VOLUME 1198
|
||||
#define GEO_NODE_INDEX_OF_NEAREST 1199
|
||||
/* Function nodes use the range starting at 1200. */
|
||||
#define GEO_NODE_SIMULATION_INPUT 2100
|
||||
#define GEO_NODE_SIMULATION_OUTPUT 2101
|
||||
#define GEO_NODE_INPUT_SIGNED_DISTANCE 2102
|
||||
#define GEO_NODE_SAMPLE_VOLUME 2103
|
||||
// #define GEO_NODE_INPUT_SIGNED_DISTANCE 2102
|
||||
// #define GEO_NODE_SAMPLE_VOLUME 2103
|
||||
#define GEO_NODE_MESH_TOPOLOGY_CORNERS_OF_EDGE 2104
|
||||
/* Leaving out two indices to avoid crashes with files that were created during the development of
|
||||
* the repeat zone. */
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "BLI_bitmap.h"
|
||||
#include "BLI_compiler_compat.h"
|
||||
#include "BLI_function_ref.hh"
|
||||
#include "BLI_index_mask.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_offset_indices.hh"
|
||||
#include "BLI_span.hh"
|
||||
|
@ -43,6 +44,7 @@ struct PBVHNode;
|
|||
struct PBVHBatches;
|
||||
struct PBVH_GPU_Args;
|
||||
struct SculptSession;
|
||||
struct SubdivCCGFace;
|
||||
struct SubdivCCG;
|
||||
struct TaskParallelSettings;
|
||||
struct Image;
|
||||
|
@ -214,12 +216,11 @@ void BKE_pbvh_update_mesh_pointers(PBVH *pbvh, Mesh *mesh);
|
|||
* Do a full rebuild with on Grids data structure.
|
||||
*/
|
||||
void BKE_pbvh_build_grids(PBVH *pbvh,
|
||||
CCGElem **grids,
|
||||
int totgrid,
|
||||
blender::Span<CCGElem *> grids,
|
||||
CCGKey *key,
|
||||
blender::Span<int> grid_to_face_map,
|
||||
DMFlagMat *flagmats,
|
||||
unsigned int **grid_hidden,
|
||||
blender::Span<DMFlagMat> flagmats,
|
||||
blender::Span<BLI_bitmap *> grid_hidden,
|
||||
Mesh *me,
|
||||
SubdivCCG *subdiv_ccg);
|
||||
/**
|
||||
|
@ -331,14 +332,14 @@ void BKE_pbvh_bounding_box(const PBVH *pbvh, float min[3], float max[3]);
|
|||
/**
|
||||
* Multi-res hidden data, only valid for type == PBVH_GRIDS.
|
||||
*/
|
||||
unsigned int **BKE_pbvh_grid_hidden(const PBVH *pbvh);
|
||||
blender::Span<const BLI_bitmap *> BKE_pbvh_get_grid_visibility(const PBVH *pbvh);
|
||||
|
||||
void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, Mesh *me);
|
||||
|
||||
/**
|
||||
* Returns the number of visible quads in the nodes' grids.
|
||||
*/
|
||||
int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
|
||||
int BKE_pbvh_count_grid_quads(blender::Span<const BLI_bitmap *> grid_hidden,
|
||||
const int *grid_indices,
|
||||
int totgrid,
|
||||
int gridsize,
|
||||
|
@ -349,8 +350,7 @@ int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
|
|||
*/
|
||||
const CCGKey *BKE_pbvh_get_grid_key(const PBVH *pbvh);
|
||||
|
||||
CCGElem **BKE_pbvh_get_grids(const PBVH *pbvh);
|
||||
BLI_bitmap **BKE_pbvh_get_grid_visibility(const PBVH *pbvh);
|
||||
blender::Span<CCGElem *> BKE_pbvh_get_grids(const PBVH *pbvh);
|
||||
int BKE_pbvh_get_grid_num_verts(const PBVH *pbvh);
|
||||
int BKE_pbvh_get_grid_num_faces(const PBVH *pbvh);
|
||||
|
||||
|
@ -403,7 +403,7 @@ void BKE_pbvh_node_get_grids(PBVH *pbvh,
|
|||
int *totgrid,
|
||||
int *maxgrid,
|
||||
int *gridsize,
|
||||
CCGElem ***r_griddata);
|
||||
CCGElem *const **r_griddata);
|
||||
void BKE_pbvh_node_num_verts(const PBVH *pbvh,
|
||||
const PBVHNode *node,
|
||||
int *r_uniquevert,
|
||||
|
@ -457,12 +457,14 @@ void BKE_pbvh_update_vertex_data(PBVH *pbvh, int flags);
|
|||
void BKE_pbvh_update_visibility(PBVH *pbvh);
|
||||
void BKE_pbvh_update_normals(PBVH *pbvh, SubdivCCG *subdiv_ccg);
|
||||
void BKE_pbvh_redraw_BB(PBVH *pbvh, float bb_min[3], float bb_max[3]);
|
||||
void BKE_pbvh_get_grid_updates(PBVH *pbvh, bool clear, void ***r_gridfaces, int *r_totface);
|
||||
blender::IndexMask BKE_pbvh_get_grid_updates(const PBVH *pbvh,
|
||||
blender::Span<const PBVHNode *> nodes,
|
||||
blender::IndexMaskMemory &memory);
|
||||
void BKE_pbvh_grids_update(PBVH *pbvh,
|
||||
CCGElem **grids,
|
||||
blender::Span<CCGElem *> grids,
|
||||
blender::Span<int> grid_to_face_map,
|
||||
DMFlagMat *flagmats,
|
||||
unsigned int **grid_hidden,
|
||||
blender::Span<DMFlagMat> flagmats,
|
||||
blender::Span<BLI_bitmap *> grid_hidden,
|
||||
CCGKey *key);
|
||||
void BKE_pbvh_subdiv_cgg_set(PBVH *pbvh, SubdivCCG *subdiv_ccg);
|
||||
|
||||
|
@ -501,9 +503,9 @@ struct PBVHVertexIter {
|
|||
|
||||
/* grid */
|
||||
CCGKey key;
|
||||
CCGElem **grids;
|
||||
CCGElem *const *grids;
|
||||
CCGElem *grid;
|
||||
BLI_bitmap **grid_hidden, *gh;
|
||||
BLI_bitmap *const *grid_hidden, *gh;
|
||||
const int *grid_indices;
|
||||
int totgrid;
|
||||
int gridsize;
|
||||
|
|
|
@ -18,16 +18,19 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Reporting Information and Errors.
|
||||
/**
|
||||
* Reporting Information and Errors.
|
||||
*
|
||||
* These functions are thread-safe, unless otherwise specified.
|
||||
*
|
||||
* These functions also accept nullptr in case no error reporting is needed. The message are only
|
||||
* printed to the console then. */
|
||||
* printed to the console then.
|
||||
*/
|
||||
|
||||
/* Report structures are stored in DNA. */
|
||||
|
||||
/** Initialize a #ReportList struct.
|
||||
/**
|
||||
* Initialize a #ReportList struct.
|
||||
*
|
||||
* \note: Not thread-safe, should only be called from the 'owner' thread of the report list.
|
||||
*/
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
#include "BKE_bvhutils.hh"
|
||||
#include "BLI_bitmap.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_offset_indices.hh"
|
||||
#include "BLI_span.hh"
|
||||
|
||||
/*
|
||||
* Shrinkwrap is composed by a set of functions and options that define the type of shrink.
|
||||
|
@ -27,6 +27,7 @@ extern "C" {
|
|||
* (So that you don't have to pass an enormous amount of arguments to functions)
|
||||
*/
|
||||
|
||||
struct bContext;
|
||||
struct BVHTree;
|
||||
struct MDeformVert;
|
||||
struct Mesh;
|
||||
|
@ -37,15 +38,15 @@ struct ShrinkwrapModifierData;
|
|||
struct SpaceTransform;
|
||||
|
||||
/* Information about boundary edges in the mesh. */
|
||||
typedef struct ShrinkwrapBoundaryVertData {
|
||||
struct ShrinkwrapBoundaryVertData {
|
||||
/* Average direction of edges that meet here. */
|
||||
float direction[3];
|
||||
|
||||
/* Closest vector to direction that is orthogonal to vertex normal. */
|
||||
float normal_plane[3];
|
||||
} ShrinkwrapBoundaryVertData;
|
||||
};
|
||||
|
||||
typedef struct ShrinkwrapBoundaryData {
|
||||
struct ShrinkwrapBoundaryData {
|
||||
/* True if the edge belongs to exactly one face. */
|
||||
const BLI_bitmap *edge_is_boundary;
|
||||
/* True if the looptri has any boundary edges. */
|
||||
|
@ -58,29 +59,30 @@ typedef struct ShrinkwrapBoundaryData {
|
|||
|
||||
/* Direction data about boundary vertices. */
|
||||
const ShrinkwrapBoundaryVertData *boundary_verts;
|
||||
} ShrinkwrapBoundaryData;
|
||||
};
|
||||
|
||||
/**
|
||||
* Free boundary data for target project.
|
||||
*/
|
||||
void BKE_shrinkwrap_boundary_data_free(ShrinkwrapBoundaryData *data);
|
||||
void BKE_shrinkwrap_compute_boundary_data(struct Mesh *mesh);
|
||||
void BKE_shrinkwrap_compute_boundary_data(Mesh *mesh);
|
||||
|
||||
/* Information about a mesh and BVH tree. */
|
||||
typedef struct ShrinkwrapTreeData {
|
||||
struct ShrinkwrapTreeData {
|
||||
Mesh *mesh;
|
||||
|
||||
BVHTree *bvh;
|
||||
BVHTreeFromMesh treeData;
|
||||
|
||||
const int *face_offsets;
|
||||
const float (*vert_normals)[3];
|
||||
const int *corner_edges;
|
||||
const float (*face_normals)[3];
|
||||
blender::OffsetIndices<int> faces;
|
||||
blender::Span<int> corner_edges;
|
||||
|
||||
blender::Span<blender::float3> face_normals;
|
||||
blender::Span<blender::float3> vert_normals;
|
||||
blender::Span<blender::float3> corner_normals;
|
||||
const bool *sharp_faces;
|
||||
const float (*clnors)[3];
|
||||
ShrinkwrapBoundaryData *boundary;
|
||||
} ShrinkwrapTreeData;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if the modifier needs target normals with these settings.
|
||||
|
@ -90,33 +92,30 @@ bool BKE_shrinkwrap_needs_normals(int shrinkType, int shrinkMode);
|
|||
/**
|
||||
* Initializes the mesh data structure from the given mesh and settings.
|
||||
*/
|
||||
bool BKE_shrinkwrap_init_tree(struct ShrinkwrapTreeData *data,
|
||||
Mesh *mesh,
|
||||
int shrinkType,
|
||||
int shrinkMode,
|
||||
bool force_normals);
|
||||
bool BKE_shrinkwrap_init_tree(
|
||||
ShrinkwrapTreeData *data, Mesh *mesh, int shrinkType, int shrinkMode, bool force_normals);
|
||||
|
||||
/**
|
||||
* Frees the tree data if necessary.
|
||||
*/
|
||||
void BKE_shrinkwrap_free_tree(struct ShrinkwrapTreeData *data);
|
||||
void BKE_shrinkwrap_free_tree(ShrinkwrapTreeData *data);
|
||||
|
||||
/**
|
||||
* Main shrink-wrap function (implementation of the shrink-wrap modifier).
|
||||
*/
|
||||
void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd,
|
||||
const struct ModifierEvalContext *ctx,
|
||||
struct Scene *scene,
|
||||
struct Object *ob,
|
||||
struct Mesh *mesh,
|
||||
const struct MDeformVert *dvert,
|
||||
void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd,
|
||||
const ModifierEvalContext *ctx,
|
||||
Scene *scene,
|
||||
Object *ob,
|
||||
Mesh *mesh,
|
||||
const MDeformVert *dvert,
|
||||
int defgrp_index,
|
||||
float (*vertexCos)[3],
|
||||
int numVerts);
|
||||
/* Implementation of the Shrinkwrap Grease Pencil modifier. */
|
||||
void shrinkwrapGpencilModifier_deform(struct ShrinkwrapGpencilModifierData *mmd,
|
||||
struct Object *ob,
|
||||
struct MDeformVert *dvert,
|
||||
void shrinkwrapGpencilModifier_deform(ShrinkwrapGpencilModifierData *mmd,
|
||||
Object *ob,
|
||||
MDeformVert *dvert,
|
||||
int defgrp_index,
|
||||
float (*vertexCos)[3],
|
||||
int numVerts);
|
||||
|
@ -124,16 +123,12 @@ void shrinkwrapGpencilModifier_deform(struct ShrinkwrapGpencilModifierData *mmd,
|
|||
/**
|
||||
* Used in `editmesh_mask_extract.cc` to shrink-wrap the extracted mesh to the sculpt.
|
||||
*/
|
||||
void BKE_shrinkwrap_mesh_nearest_surface_deform(struct bContext *C,
|
||||
struct Object *ob_source,
|
||||
struct Object *ob_target);
|
||||
void BKE_shrinkwrap_mesh_nearest_surface_deform(bContext *C, Object *ob_source, Object *ob_target);
|
||||
|
||||
/**
|
||||
* Used in `object_remesh.cc` to preserve the details and volume in the voxel remesher.
|
||||
*/
|
||||
void BKE_shrinkwrap_remesh_target_project(struct Mesh *src_me,
|
||||
struct Mesh *target_me,
|
||||
struct Object *ob_target);
|
||||
void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object *ob_target);
|
||||
|
||||
/**
|
||||
* This function ray-cast a single vertex and updates the hit if the "hit" is considered valid.
|
||||
|
@ -156,15 +151,15 @@ bool BKE_shrinkwrap_project_normal(char options,
|
|||
const float vert[3],
|
||||
const float dir[3],
|
||||
float ray_radius,
|
||||
const struct SpaceTransform *transf,
|
||||
struct ShrinkwrapTreeData *tree,
|
||||
const SpaceTransform *transf,
|
||||
ShrinkwrapTreeData *tree,
|
||||
BVHTreeRayHit *hit);
|
||||
|
||||
/**
|
||||
* Maps the point to the nearest surface, either by simple nearest, or by target normal projection.
|
||||
*/
|
||||
void BKE_shrinkwrap_find_nearest_surface(struct ShrinkwrapTreeData *tree,
|
||||
struct BVHTreeNearest *nearest,
|
||||
void BKE_shrinkwrap_find_nearest_surface(ShrinkwrapTreeData *tree,
|
||||
BVHTreeNearest *nearest,
|
||||
float co[3],
|
||||
int type);
|
||||
|
||||
|
@ -175,8 +170,8 @@ void BKE_shrinkwrap_find_nearest_surface(struct ShrinkwrapTreeData *tree,
|
|||
* \param transform: transform from the hit coordinate space to the object space; may be null.
|
||||
* \param r_no: output in hit coordinate space; may be shared with inputs.
|
||||
*/
|
||||
void BKE_shrinkwrap_compute_smooth_normal(const struct ShrinkwrapTreeData *tree,
|
||||
const struct SpaceTransform *transform,
|
||||
void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree,
|
||||
const SpaceTransform *transform,
|
||||
int looptri_idx,
|
||||
const float hit_co[3],
|
||||
const float hit_no[3],
|
||||
|
@ -189,8 +184,8 @@ void BKE_shrinkwrap_compute_smooth_normal(const struct ShrinkwrapTreeData *tree,
|
|||
* \param transform: transform from the hit coordinate space to the object space; may be null.
|
||||
* \param r_point_co: may be the same memory location as `point_co`, `hit_co`, or `hit_no`.
|
||||
*/
|
||||
void BKE_shrinkwrap_snap_point_to_surface(const struct ShrinkwrapTreeData *tree,
|
||||
const struct SpaceTransform *transform,
|
||||
void BKE_shrinkwrap_snap_point_to_surface(const ShrinkwrapTreeData *tree,
|
||||
const SpaceTransform *transform,
|
||||
int mode,
|
||||
int hit_idx,
|
||||
const float hit_co[3],
|
||||
|
@ -218,7 +213,3 @@ void BKE_shrinkwrap_snap_point_to_surface(const struct ShrinkwrapTreeData *tree,
|
|||
{ \
|
||||
0, \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -132,10 +132,9 @@ struct SubdivCCG {
|
|||
*/
|
||||
/* Indexed by a grid index, points to a grid data which is stored in
|
||||
* grids_storage. */
|
||||
CCGElem **grids = nullptr;
|
||||
blender::Array<CCGElem *> grids;
|
||||
/* Flat array of all grids' data. */
|
||||
unsigned char *grids_storage = nullptr;
|
||||
int num_grids = -1;
|
||||
blender::Array<uchar> grids_storage;
|
||||
/* Loose edges, each array element contains grid_size elements
|
||||
* corresponding to vertices created by subdividing coarse edges. */
|
||||
CCGElem **edges = nullptr;
|
||||
|
@ -157,25 +156,22 @@ struct SubdivCCG {
|
|||
int mask_offset = -1;
|
||||
|
||||
/* Faces from which grids are emitted. */
|
||||
int num_faces = -1;
|
||||
SubdivCCGFace *faces = nullptr;
|
||||
blender::Array<SubdivCCGFace> faces;
|
||||
/* Indexed by grid index, points to corresponding face from `faces`. */
|
||||
blender::Array<int> grid_to_face_map;
|
||||
|
||||
/* Edges which are adjacent to faces.
|
||||
* Used for faster grid stitching, in the cost of extra memory.
|
||||
* Used for faster grid stitching, at the cost of extra memory.
|
||||
*/
|
||||
int num_adjacent_edges = -1;
|
||||
SubdivCCGAdjacentEdge *adjacent_edges = nullptr;
|
||||
blender::Array<SubdivCCGAdjacentEdge> adjacent_edges;
|
||||
|
||||
/* Vertices which are adjacent to faces
|
||||
* Used for faster grid stitching, in the cost of extra memory.
|
||||
* Used for faster grid stitching, at the cost of extra memory.
|
||||
*/
|
||||
int num_adjacent_vertices = -1;
|
||||
SubdivCCGAdjacentVertex *adjacent_vertices = nullptr;
|
||||
blender::Array<SubdivCCGAdjacentVertex> adjacent_verts;
|
||||
|
||||
DMFlagMat *grid_flag_mats = nullptr;
|
||||
BLI_bitmap **grid_hidden = nullptr;
|
||||
blender::Array<DMFlagMat> grid_flag_mats;
|
||||
blender::Array<BLI_bitmap *> grid_hidden;
|
||||
|
||||
/* TODO(sergey): Consider adding some accessors to a "decoded" geometry,
|
||||
* to make integration with draw manager and such easy.
|
||||
|
@ -198,7 +194,7 @@ struct SubdivCCG {
|
|||
/* Cached values, are not supposed to be accessed directly. */
|
||||
struct {
|
||||
/* Indexed by face, indicates index of the first grid which corresponds to the face. */
|
||||
int *start_face_grid_index = nullptr;
|
||||
blender::Array<int> start_face_grid_index;
|
||||
} cache_;
|
||||
};
|
||||
|
||||
|
@ -213,8 +209,8 @@ struct SubdivCCG {
|
|||
* TODO(sergey): Allow some user-counter or more explicit control over who owns
|
||||
* the Subdiv. The goal should be to allow viewport GL Mesh and CCG to share
|
||||
* same Subsurf without conflicts. */
|
||||
SubdivCCG *BKE_subdiv_to_ccg(Subdiv *subdiv,
|
||||
const SubdivToCCGSettings *settings,
|
||||
SubdivCCG *BKE_subdiv_to_ccg(Subdiv &subdiv,
|
||||
const SubdivToCCGSettings &settings,
|
||||
SubdivCCGMaskEvaluator *mask_evaluator,
|
||||
SubdivCCGMaterialFlagsEvaluator *material_flags_evaluator);
|
||||
|
||||
|
@ -224,36 +220,33 @@ void BKE_subdiv_ccg_destroy(SubdivCCG *subdiv_ccg);
|
|||
/* Helper function, creates Mesh structure which is properly setup to use
|
||||
* grids.
|
||||
*/
|
||||
Mesh *BKE_subdiv_to_ccg_mesh(Subdiv *subdiv,
|
||||
const SubdivToCCGSettings *settings,
|
||||
const Mesh *coarse_mesh);
|
||||
Mesh *BKE_subdiv_to_ccg_mesh(Subdiv &subdiv,
|
||||
const SubdivToCCGSettings &settings,
|
||||
const Mesh &coarse_mesh);
|
||||
|
||||
/* Create a key for accessing grid elements at a given level. */
|
||||
void BKE_subdiv_ccg_key(CCGKey *key, const SubdivCCG *subdiv_ccg, int level);
|
||||
void BKE_subdiv_ccg_key_top_level(CCGKey *key, const SubdivCCG *subdiv_ccg);
|
||||
void BKE_subdiv_ccg_key(CCGKey &key, const SubdivCCG &subdiv_ccg, int level);
|
||||
void BKE_subdiv_ccg_key_top_level(CCGKey &key, const SubdivCCG &subdiv_ccg);
|
||||
|
||||
/* Recalculate all normals based on grid element coordinates. */
|
||||
void BKE_subdiv_ccg_recalc_normals(SubdivCCG *subdiv_ccg);
|
||||
void BKE_subdiv_ccg_recalc_normals(SubdivCCG &subdiv_ccg);
|
||||
|
||||
/* Update normals of affected faces. */
|
||||
void BKE_subdiv_ccg_update_normals(SubdivCCG *subdiv_ccg,
|
||||
CCGFace **effected_faces,
|
||||
int num_effected_faces);
|
||||
void BKE_subdiv_ccg_update_normals(SubdivCCG &subdiv_ccg, const blender::IndexMask &face_mask);
|
||||
|
||||
/* Average grid coordinates and normals along the grid boundaries. */
|
||||
void BKE_subdiv_ccg_average_grids(SubdivCCG *subdiv_ccg);
|
||||
void BKE_subdiv_ccg_average_grids(SubdivCCG &subdiv_ccg);
|
||||
|
||||
/* Similar to above, but only updates given faces. */
|
||||
void BKE_subdiv_ccg_average_stitch_faces(SubdivCCG *subdiv_ccg,
|
||||
CCGFace **effected_faces,
|
||||
int num_effected_faces);
|
||||
void BKE_subdiv_ccg_average_stitch_faces(SubdivCCG &subdiv_ccg,
|
||||
const blender::IndexMask &face_mask);
|
||||
|
||||
/* Get geometry counters at the current subdivision level. */
|
||||
void BKE_subdiv_ccg_topology_counters(const SubdivCCG *subdiv_ccg,
|
||||
int *r_num_vertices,
|
||||
int *r_num_edges,
|
||||
int *r_num_faces,
|
||||
int *r_num_loops);
|
||||
void BKE_subdiv_ccg_topology_counters(const SubdivCCG &subdiv_ccg,
|
||||
int &r_num_vertices,
|
||||
int &r_num_edges,
|
||||
int &r_num_faces,
|
||||
int &r_num_loops);
|
||||
|
||||
struct SubdivCCGNeighbors {
|
||||
SubdivCCGCoord *coords;
|
||||
|
@ -263,8 +256,8 @@ struct SubdivCCGNeighbors {
|
|||
SubdivCCGCoord coords_fixed[256];
|
||||
};
|
||||
|
||||
void BKE_subdiv_ccg_print_coord(const char *message, const SubdivCCGCoord *coord);
|
||||
bool BKE_subdiv_ccg_check_coord_valid(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord);
|
||||
void BKE_subdiv_ccg_print_coord(const char *message, const SubdivCCGCoord &coord);
|
||||
bool BKE_subdiv_ccg_check_coord_valid(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord);
|
||||
|
||||
/* CCG element neighbors.
|
||||
*
|
||||
|
@ -286,14 +279,14 @@ bool BKE_subdiv_ccg_check_coord_valid(const SubdivCCG *subdiv_ccg, const SubdivC
|
|||
*
|
||||
* If include_duplicates is true, vertices in other grids that match
|
||||
* the current vertex are added at the end of the coords array. */
|
||||
void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG *subdiv_ccg,
|
||||
const SubdivCCGCoord *coord,
|
||||
void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG &subdiv_ccg,
|
||||
const SubdivCCGCoord &coord,
|
||||
bool include_duplicates,
|
||||
SubdivCCGNeighbors *r_neighbors);
|
||||
SubdivCCGNeighbors &r_neighbors);
|
||||
|
||||
int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG *subdiv_ccg, int grid_index);
|
||||
void BKE_subdiv_ccg_eval_limit_point(const SubdivCCG *subdiv_ccg,
|
||||
const SubdivCCGCoord *coord,
|
||||
int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG &subdiv_ccg, int grid_index);
|
||||
void BKE_subdiv_ccg_eval_limit_point(const SubdivCCG &subdiv_ccg,
|
||||
const SubdivCCGCoord &coord,
|
||||
float r_point[3]);
|
||||
|
||||
enum SubdivCCGAdjacencyType {
|
||||
|
@ -306,12 +299,12 @@ enum SubdivCCGAdjacencyType {
|
|||
* adjacent to an edge, r_v1 and r_v2 will be set to the two vertices of that edge. If it is
|
||||
* adjacent to a vertex, r_v1 and r_v2 will be the index of that vertex. */
|
||||
SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(
|
||||
const SubdivCCG *subdiv_ccg,
|
||||
const SubdivCCGCoord *coord,
|
||||
const SubdivCCG &subdiv_ccg,
|
||||
const SubdivCCGCoord &coord,
|
||||
blender::Span<int> corner_verts,
|
||||
blender::OffsetIndices<int> faces,
|
||||
int *r_v1,
|
||||
int *r_v2);
|
||||
int &r_v1,
|
||||
int &r_v2);
|
||||
|
||||
/* Get array which is indexed by face index and contains index of a first grid of the face.
|
||||
*
|
||||
|
@ -319,8 +312,8 @@ SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(
|
|||
* descriptor. This function is NOT safe for threading.
|
||||
*
|
||||
* The "get" version simply returns cached array. */
|
||||
const int *BKE_subdiv_ccg_start_face_grid_index_ensure(SubdivCCG *subdiv_ccg);
|
||||
const int *BKE_subdiv_ccg_start_face_grid_index_get(const SubdivCCG *subdiv_ccg);
|
||||
const int *BKE_subdiv_ccg_start_face_grid_index_ensure(SubdivCCG &subdiv_ccg);
|
||||
const int *BKE_subdiv_ccg_start_face_grid_index_get(const SubdivCCG &subdiv_ccg);
|
||||
|
||||
void BKE_subdiv_ccg_grid_hidden_ensure(SubdivCCG *subdiv_ccg, int grid_index);
|
||||
void BKE_subdiv_ccg_grid_hidden_free(SubdivCCG *subdiv_ccg, int grid_index);
|
||||
void BKE_subdiv_ccg_grid_hidden_ensure(SubdivCCG &subdiv_ccg, int grid_index);
|
||||
void BKE_subdiv_ccg_grid_hidden_free(SubdivCCG &subdiv_ccg, int grid_index);
|
||||
|
|
|
@ -4,14 +4,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_sys_types.h"
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct UnitSettings;
|
||||
|
||||
/* In all cases the value is assumed to be scaled by the user-preference. */
|
||||
|
@ -36,7 +34,7 @@ size_t BKE_unit_value_as_string(char *str,
|
|||
double value,
|
||||
int prec,
|
||||
int type,
|
||||
const struct UnitSettings *settings,
|
||||
const UnitSettings *settings,
|
||||
bool pad);
|
||||
|
||||
/**
|
||||
|
@ -67,7 +65,7 @@ bool BKE_unit_string_contains_unit(const char *str, int type);
|
|||
/**
|
||||
* If user does not specify a unit, this converts it to the unit from the settings.
|
||||
*/
|
||||
double BKE_unit_apply_preferred_unit(const struct UnitSettings *settings, int type, double value);
|
||||
double BKE_unit_apply_preferred_unit(const UnitSettings *settings, int type, double value);
|
||||
|
||||
/**
|
||||
* Make string keyboard-friendly, e.g: `10µm -> 10um`.
|
||||
|
@ -120,7 +118,3 @@ enum {
|
|||
B_UNIT_TEMPERATURE = 12,
|
||||
B_UNIT_TYPE_TOT = 13,
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -3,14 +3,12 @@
|
|||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "BLI_sys_types.h"
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct CharInfo;
|
||||
struct Curve;
|
||||
struct Main;
|
||||
|
@ -24,19 +22,19 @@ struct CharTrans {
|
|||
char dobreak;
|
||||
};
|
||||
|
||||
typedef struct EditFontSelBox {
|
||||
struct EditFontSelBox {
|
||||
float x, y, w, h;
|
||||
float rot;
|
||||
} EditFontSelBox;
|
||||
};
|
||||
|
||||
/**
|
||||
* Edit data for #Curve (a text curve, with an #Object::type of `OB_FONT`).
|
||||
* */
|
||||
typedef struct EditFont {
|
||||
struct EditFont {
|
||||
/** Array of UTF32 code-points. */
|
||||
char32_t *textbuf;
|
||||
/** Text style info (aligned with `textbuf`). */
|
||||
struct CharInfo *textbufinfo;
|
||||
CharInfo *textbufinfo;
|
||||
|
||||
/** Array of rectangles & rotation. */
|
||||
float textcurs[4][2];
|
||||
|
@ -65,10 +63,9 @@ typedef struct EditFont {
|
|||
* Set #Main.is_memfile_undo_flush_needed when enabling.
|
||||
*/
|
||||
char needs_flush_to_id;
|
||||
};
|
||||
|
||||
} EditFont;
|
||||
|
||||
typedef enum eEditFontMode {
|
||||
enum eEditFontMode {
|
||||
FO_EDIT = 0,
|
||||
FO_CURS = 1,
|
||||
FO_CURSUP = 2,
|
||||
|
@ -77,62 +74,56 @@ typedef enum eEditFontMode {
|
|||
FO_PAGEUP = 8,
|
||||
FO_PAGEDOWN = 9,
|
||||
FO_SELCHANGE = 10,
|
||||
} eEditFontMode;
|
||||
};
|
||||
|
||||
/* BKE_vfont_to_curve will move the cursor in these cases */
|
||||
#define FO_CURS_IS_MOTION(mode) (ELEM(mode, FO_CURSUP, FO_CURSDOWN, FO_PAGEUP, FO_PAGEDOWN))
|
||||
|
||||
bool BKE_vfont_is_builtin(const struct VFont *vfont);
|
||||
bool BKE_vfont_is_builtin(const VFont *vfont);
|
||||
void BKE_vfont_builtin_register(const void *mem, int size);
|
||||
|
||||
void BKE_vfont_free_data(struct VFont *vfont);
|
||||
void BKE_vfont_free_data(VFont *vfont);
|
||||
/**
|
||||
* Return the built-in #VFont, without adding a user (the user-count may be zero).
|
||||
* The caller is responsible for adding a user.
|
||||
*/
|
||||
struct VFont *BKE_vfont_builtin_get(void);
|
||||
struct VFont *BKE_vfont_load(struct Main *bmain, const char *filepath);
|
||||
struct VFont *BKE_vfont_load_exists_ex(struct Main *bmain, const char *filepath, bool *r_exists);
|
||||
struct VFont *BKE_vfont_load_exists(struct Main *bmain, const char *filepath);
|
||||
VFont *BKE_vfont_builtin_get();
|
||||
VFont *BKE_vfont_load(Main *bmain, const char *filepath);
|
||||
VFont *BKE_vfont_load_exists_ex(Main *bmain, const char *filepath, bool *r_exists);
|
||||
VFont *BKE_vfont_load_exists(Main *bmain, const char *filepath);
|
||||
|
||||
bool BKE_vfont_to_curve_ex(struct Object *ob,
|
||||
struct Curve *cu,
|
||||
bool BKE_vfont_to_curve_ex(Object *ob,
|
||||
Curve *cu,
|
||||
eEditFontMode mode,
|
||||
struct ListBase *r_nubase,
|
||||
ListBase *r_nubase,
|
||||
const char32_t **r_text,
|
||||
int *r_text_len,
|
||||
bool *r_text_free,
|
||||
struct CharTrans **r_chartransdata);
|
||||
bool BKE_vfont_to_curve_nubase(struct Object *ob, eEditFontMode mode, struct ListBase *r_nubase);
|
||||
CharTrans **r_chartransdata);
|
||||
bool BKE_vfont_to_curve_nubase(Object *ob, eEditFontMode mode, ListBase *r_nubase);
|
||||
|
||||
int BKE_vfont_cursor_to_text_index(struct Object *ob, float cursor_location[2]);
|
||||
int BKE_vfont_cursor_to_text_index(Object *ob, float cursor_location[2]);
|
||||
|
||||
/**
|
||||
* \warning Expects to have access to evaluated data (i.e. passed object should be evaluated one).
|
||||
*/
|
||||
bool BKE_vfont_to_curve(struct Object *ob, eEditFontMode mode);
|
||||
void BKE_vfont_build_char(struct Curve *cu,
|
||||
struct ListBase *nubase,
|
||||
bool BKE_vfont_to_curve(Object *ob, eEditFontMode mode);
|
||||
void BKE_vfont_build_char(Curve *cu,
|
||||
ListBase *nubase,
|
||||
unsigned int character,
|
||||
struct CharInfo *info,
|
||||
CharInfo *info,
|
||||
float ofsx,
|
||||
float ofsy,
|
||||
float rot,
|
||||
int charidx,
|
||||
float fsize);
|
||||
|
||||
int BKE_vfont_select_get(struct Object *ob, int *r_start, int *r_end);
|
||||
void BKE_vfont_select_clamp(struct Object *ob);
|
||||
int BKE_vfont_select_get(Object *ob, int *r_start, int *r_end);
|
||||
void BKE_vfont_select_clamp(Object *ob);
|
||||
|
||||
void BKE_vfont_clipboard_free(void);
|
||||
void BKE_vfont_clipboard_set(const char32_t *text_buf,
|
||||
const struct CharInfo *info_buf,
|
||||
size_t len);
|
||||
void BKE_vfont_clipboard_set(const char32_t *text_buf, const CharInfo *info_buf, size_t len);
|
||||
void BKE_vfont_clipboard_get(char32_t **r_text_buf,
|
||||
struct CharInfo **r_info_buf,
|
||||
CharInfo **r_info_buf,
|
||||
size_t *r_len_utf8,
|
||||
size_t *r_len_utf32);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -12,27 +12,24 @@
|
|||
|
||||
#include "DNA_listBase.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct GHash;
|
||||
struct PackedFile;
|
||||
struct VFont;
|
||||
|
||||
typedef struct VFontData {
|
||||
struct GHash *characters;
|
||||
struct VFontData {
|
||||
GHash *characters;
|
||||
char name[128];
|
||||
float scale;
|
||||
/* Calculated from the font. */
|
||||
float em_height;
|
||||
float ascender;
|
||||
} VFontData;
|
||||
};
|
||||
|
||||
typedef struct VChar {
|
||||
struct VChar {
|
||||
ListBase nurbsbase;
|
||||
unsigned int index;
|
||||
float width;
|
||||
} VChar;
|
||||
};
|
||||
|
||||
/**
|
||||
* Construct a new #VFontData structure from free-type font data in `pf`.
|
||||
|
@ -40,12 +37,8 @@ typedef struct VChar {
|
|||
* \param pf: The font data.
|
||||
* \retval A new #VFontData structure, or NULL if unable to load.
|
||||
*/
|
||||
VFontData *BKE_vfontdata_from_freetypefont(struct PackedFile *pf);
|
||||
VFontData *BKE_vfontdata_from_freetypefont(PackedFile *pf);
|
||||
VFontData *BKE_vfontdata_copy(const VFontData *vfont_src, int flag);
|
||||
|
||||
VChar *BKE_vfontdata_char_from_freetypefont(struct VFont *vfont, unsigned long character);
|
||||
VChar *BKE_vfontdata_char_from_freetypefont(VFont *vfont, unsigned long character);
|
||||
VChar *BKE_vfontdata_char_copy(const VChar *vchar_src);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -10,10 +10,6 @@
|
|||
|
||||
#ifdef WITH_FFMPEG
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
enum {
|
||||
FFMPEG_MPEG1 = 0,
|
||||
FFMPEG_MPEG2 = 1,
|
||||
|
@ -48,37 +44,33 @@ struct ReportList;
|
|||
struct Scene;
|
||||
|
||||
int BKE_ffmpeg_start(void *context_v,
|
||||
const struct Scene *scene,
|
||||
struct RenderData *rd,
|
||||
const Scene *scene,
|
||||
RenderData *rd,
|
||||
int rectx,
|
||||
int recty,
|
||||
struct ReportList *reports,
|
||||
ReportList *reports,
|
||||
bool preview,
|
||||
const char *suffix);
|
||||
void BKE_ffmpeg_end(void *context_v);
|
||||
int BKE_ffmpeg_append(void *context_v,
|
||||
struct RenderData *rd,
|
||||
RenderData *rd,
|
||||
int start_frame,
|
||||
int frame,
|
||||
int *pixels,
|
||||
int rectx,
|
||||
int recty,
|
||||
const char *suffix,
|
||||
struct ReportList *reports);
|
||||
ReportList *reports);
|
||||
void BKE_ffmpeg_filepath_get(char filepath[/*FILE_MAX*/ 1024],
|
||||
const struct RenderData *rd,
|
||||
const RenderData *rd,
|
||||
bool preview,
|
||||
const char *suffix);
|
||||
|
||||
void BKE_ffmpeg_preset_set(struct RenderData *rd, int preset);
|
||||
void BKE_ffmpeg_image_type_verify(struct RenderData *rd, const struct ImageFormatData *imf);
|
||||
bool BKE_ffmpeg_alpha_channel_is_supported(const struct RenderData *rd);
|
||||
void BKE_ffmpeg_preset_set(RenderData *rd, int preset);
|
||||
void BKE_ffmpeg_image_type_verify(RenderData *rd, const ImageFormatData *imf);
|
||||
bool BKE_ffmpeg_alpha_channel_is_supported(const RenderData *rd);
|
||||
|
||||
void *BKE_ffmpeg_context_create(void);
|
||||
void BKE_ffmpeg_context_free(void *context_v);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
|
@ -481,7 +481,7 @@ set(SRC
|
|||
BKE_screen.hh
|
||||
BKE_sequencer_offscreen.h
|
||||
BKE_shader_fx.h
|
||||
BKE_shrinkwrap.h
|
||||
BKE_shrinkwrap.hh
|
||||
BKE_softbody.h
|
||||
BKE_sound.h
|
||||
BKE_speaker.h
|
||||
|
@ -501,9 +501,9 @@ set(SRC
|
|||
BKE_tracking.h
|
||||
BKE_type_conversions.hh
|
||||
BKE_undo_system.h
|
||||
BKE_unit.h
|
||||
BKE_vfont.h
|
||||
BKE_vfontdata.h
|
||||
BKE_unit.hh
|
||||
BKE_vfont.hh
|
||||
BKE_vfontdata.hh
|
||||
BKE_viewer_path.hh
|
||||
BKE_volume.hh
|
||||
BKE_volume_openvdb.hh
|
||||
|
@ -638,8 +638,8 @@ endif()
|
|||
|
||||
if(WITH_CODEC_FFMPEG)
|
||||
list(APPEND SRC
|
||||
intern/writeffmpeg.c
|
||||
BKE_writeffmpeg.h
|
||||
intern/writeffmpeg.cc
|
||||
BKE_writeffmpeg.hh
|
||||
)
|
||||
list(APPEND INC
|
||||
../../../intern/ffmpeg
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
|
||||
#include "BLI_sys_types.h" /* for intptr_t support */
|
||||
|
||||
#include "BKE_shrinkwrap.h"
|
||||
#include "BKE_shrinkwrap.hh"
|
||||
#include "DEG_depsgraph.hh"
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
|
||||
|
@ -391,7 +391,9 @@ static Mesh *create_orco_mesh(Object *ob, Mesh *me, BMEditMesh *em, int layer)
|
|||
orco = get_orco_coords(ob, em, layer, &free);
|
||||
|
||||
if (orco) {
|
||||
BKE_mesh_vert_coords_apply(mesh, orco);
|
||||
mesh->vert_positions_for_write().copy_from(
|
||||
{reinterpret_cast<const float3 *>(orco), mesh->totvert});
|
||||
BKE_mesh_tag_positions_changed(mesh);
|
||||
if (free) {
|
||||
MEM_freeN(orco);
|
||||
}
|
||||
|
|
|
@ -2578,6 +2578,12 @@ static int rebuild_pose_bone(
|
|||
pchan->bone = bone;
|
||||
pchan->parent = parchan;
|
||||
|
||||
/* Prevent custom bone colors from having alpha zero.
|
||||
* Part of the fix for issue #115434. */
|
||||
pchan->color.custom.solid[3] = 255;
|
||||
pchan->color.custom.select[3] = 255;
|
||||
pchan->color.custom.active[3] = 255;
|
||||
|
||||
/* We ensure the current pchan is immediately after the one we just generated/updated in the
|
||||
* previous call to `rebuild_pose_bone`.
|
||||
*
|
||||
|
|
|
@ -306,14 +306,16 @@ static bool reuse_bmain_data_remapper_is_id_remapped(IDRemapper *remapper, ID *i
|
|||
return false;
|
||||
}
|
||||
|
||||
/** Does a complete replacement of data in `new_bmain` by data from `old_bmain. Original new data
|
||||
/**
|
||||
* Does a complete replacement of data in `new_bmain` by data from `old_bmain. Original new data
|
||||
* are moved to the `old_bmain`, and will be freed together with it.
|
||||
*
|
||||
* WARNING: Currently only expects to work on local data, won't work properly if some of the IDs of
|
||||
* given type are linked.
|
||||
*
|
||||
* NOTE: There is no support at all for potential dependencies of the IDs moved around. This is not
|
||||
* expected to be necessary for the current use cases (UI-related IDs). */
|
||||
* expected to be necessary for the current use cases (UI-related IDs).
|
||||
*/
|
||||
static void swap_old_bmain_data_for_blendfile(ReuseOldBMainData *reuse_data, const short id_code)
|
||||
{
|
||||
Main *new_bmain = reuse_data->new_bmain;
|
||||
|
@ -382,9 +384,11 @@ static void swap_old_bmain_data_for_blendfile(ReuseOldBMainData *reuse_data, con
|
|||
FOREACH_MAIN_LISTBASE_ID_END;
|
||||
}
|
||||
|
||||
/** Similar to #swap_old_bmain_data_for_blendfile, but with special handling for WM ID. Tightly
|
||||
/**
|
||||
* Similar to #swap_old_bmain_data_for_blendfile, but with special handling for WM ID. Tightly
|
||||
* related to further WM post-processing from calling WM code (see #WM_file_read and
|
||||
* #wm_homefile_read_ex). */
|
||||
* #wm_homefile_read_ex).
|
||||
*/
|
||||
static void swap_wm_data_for_blendfile(ReuseOldBMainData *reuse_data, const bool load_ui)
|
||||
{
|
||||
Main *old_bmain = reuse_data->old_bmain;
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
#include "BKE_main.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_vfont.h"
|
||||
#include "BKE_vfont.hh"
|
||||
|
||||
#include "BKE_bpath.h" /* own include */
|
||||
|
||||
|
|
|
@ -241,14 +241,13 @@ static void mesh_faces_nearest_point(void *userdata,
|
|||
BVHTreeNearest *nearest)
|
||||
{
|
||||
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
|
||||
const float(*positions)[3] = data->vert_positions;
|
||||
const MFace *face = data->face + index;
|
||||
|
||||
const float *t0, *t1, *t2, *t3;
|
||||
t0 = positions[face->v1];
|
||||
t1 = positions[face->v2];
|
||||
t2 = positions[face->v3];
|
||||
t3 = face->v4 ? positions[face->v4] : nullptr;
|
||||
t0 = data->vert_positions[face->v1];
|
||||
t1 = data->vert_positions[face->v2];
|
||||
t2 = data->vert_positions[face->v3];
|
||||
t3 = face->v4 ? &data->vert_positions[face->v4].x : nullptr;
|
||||
|
||||
do {
|
||||
float nearest_tmp[3], dist_sq;
|
||||
|
@ -276,12 +275,11 @@ static void mesh_looptri_nearest_point(void *userdata,
|
|||
BVHTreeNearest *nearest)
|
||||
{
|
||||
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
|
||||
const float(*positions)[3] = data->vert_positions;
|
||||
const MLoopTri *lt = &data->looptri[index];
|
||||
const MLoopTri *lt = &data->looptris[index];
|
||||
const float *vtri_co[3] = {
|
||||
positions[data->corner_verts[lt->tri[0]]],
|
||||
positions[data->corner_verts[lt->tri[1]]],
|
||||
positions[data->corner_verts[lt->tri[2]]],
|
||||
data->vert_positions[data->corner_verts[lt->tri[0]]],
|
||||
data->vert_positions[data->corner_verts[lt->tri[1]]],
|
||||
data->vert_positions[data->corner_verts[lt->tri[2]]],
|
||||
};
|
||||
float nearest_tmp[3], dist_sq;
|
||||
|
||||
|
@ -336,14 +334,13 @@ static void mesh_faces_spherecast(void *userdata,
|
|||
BVHTreeRayHit *hit)
|
||||
{
|
||||
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
|
||||
const float(*positions)[3] = data->vert_positions;
|
||||
const MFace *face = &data->face[index];
|
||||
|
||||
const float *t0, *t1, *t2, *t3;
|
||||
t0 = positions[face->v1];
|
||||
t1 = positions[face->v2];
|
||||
t2 = positions[face->v3];
|
||||
t3 = face->v4 ? positions[face->v4] : nullptr;
|
||||
t0 = data->vert_positions[face->v1];
|
||||
t1 = data->vert_positions[face->v2];
|
||||
t2 = data->vert_positions[face->v3];
|
||||
t3 = face->v4 ? &data->vert_positions[face->v4].x : nullptr;
|
||||
|
||||
do {
|
||||
float dist;
|
||||
|
@ -375,8 +372,8 @@ static void mesh_looptri_spherecast(void *userdata,
|
|||
BVHTreeRayHit *hit)
|
||||
{
|
||||
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
|
||||
const float(*positions)[3] = data->vert_positions;
|
||||
const MLoopTri *lt = &data->looptri[index];
|
||||
const Span<float3> positions = data->vert_positions;
|
||||
const MLoopTri *lt = &data->looptris[index];
|
||||
const float *vtri_co[3] = {
|
||||
positions[data->corner_verts[lt->tri[0]]],
|
||||
positions[data->corner_verts[lt->tri[1]]],
|
||||
|
@ -444,8 +441,8 @@ static void mesh_edges_nearest_point(void *userdata,
|
|||
BVHTreeNearest *nearest)
|
||||
{
|
||||
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
|
||||
const float(*positions)[3] = data->vert_positions;
|
||||
const blender::int2 &edge = reinterpret_cast<const blender::int2 *>(data->edge)[index];
|
||||
const Span<float3> positions = data->vert_positions;
|
||||
const blender::int2 edge = data->edges[index];
|
||||
float nearest_tmp[3], dist_sq;
|
||||
|
||||
const float *t0, *t1;
|
||||
|
@ -526,8 +523,8 @@ static void mesh_edges_spherecast(void *userdata,
|
|||
BVHTreeRayHit *hit)
|
||||
{
|
||||
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
|
||||
const float(*positions)[3] = data->vert_positions;
|
||||
const blender::int2 &edge = reinterpret_cast<const blender::int2 *>(data->edge)[index];
|
||||
const Span<float3> positions = data->vert_positions;
|
||||
const blender::int2 edge = data->edges[index];
|
||||
|
||||
const float radius_sq = square_f(ray->radius);
|
||||
float dist;
|
||||
|
@ -577,22 +574,22 @@ static void mesh_edges_spherecast(void *userdata,
|
|||
|
||||
static void bvhtree_from_mesh_setup_data(BVHTree *tree,
|
||||
const BVHCacheType bvh_cache_type,
|
||||
const float (*positions)[3],
|
||||
const blender::int2 *edge,
|
||||
const MFace *face,
|
||||
const int *corner_verts,
|
||||
const Span<float3> positions,
|
||||
const Span<blender::int2> edges,
|
||||
const Span<int> corner_verts,
|
||||
const Span<MLoopTri> looptris,
|
||||
const MFace *face,
|
||||
BVHTreeFromMesh *r_data)
|
||||
{
|
||||
memset(r_data, 0, sizeof(*r_data));
|
||||
*r_data = {};
|
||||
|
||||
r_data->tree = tree;
|
||||
|
||||
r_data->vert_positions = positions;
|
||||
r_data->edge = reinterpret_cast<const vec2i *>(edge);
|
||||
r_data->edges = edges;
|
||||
r_data->face = face;
|
||||
r_data->corner_verts = corner_verts;
|
||||
r_data->looptri = looptris.data();
|
||||
r_data->looptris = looptris;
|
||||
|
||||
switch (bvh_cache_type) {
|
||||
case BVHTREE_FROM_VERTS:
|
||||
|
@ -715,17 +712,16 @@ static BVHTree *bvhtree_from_editmesh_verts_create_tree(float epsilon,
|
|||
static BVHTree *bvhtree_from_mesh_verts_create_tree(float epsilon,
|
||||
int tree_type,
|
||||
int axis,
|
||||
const float (*positions)[3],
|
||||
const int verts_num,
|
||||
const Span<float3> positions,
|
||||
const BitSpan verts_mask,
|
||||
int verts_num_active)
|
||||
{
|
||||
BVHTree *tree = bvhtree_new_common(epsilon, tree_type, axis, verts_num, verts_num_active);
|
||||
BVHTree *tree = bvhtree_new_common(epsilon, tree_type, axis, positions.size(), verts_num_active);
|
||||
if (!tree) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (int i = 0; i < verts_num; i++) {
|
||||
for (const int i : positions.index_range()) {
|
||||
if (!verts_mask.is_empty() && !verts_mask[i]) {
|
||||
continue;
|
||||
}
|
||||
|
@ -763,8 +759,7 @@ BVHTree *bvhtree_from_editmesh_verts(
|
|||
}
|
||||
|
||||
BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data,
|
||||
const float (*vert_positions)[3],
|
||||
const int verts_num,
|
||||
const Span<float3> vert_positions,
|
||||
const BitSpan verts_mask,
|
||||
int verts_num_active,
|
||||
float epsilon,
|
||||
|
@ -772,14 +767,13 @@ BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data,
|
|||
int axis)
|
||||
{
|
||||
BVHTree *tree = bvhtree_from_mesh_verts_create_tree(
|
||||
epsilon, tree_type, axis, vert_positions, verts_num, verts_mask, verts_num_active);
|
||||
epsilon, tree_type, axis, vert_positions, verts_mask, verts_num_active);
|
||||
|
||||
bvhtree_balance(tree, false);
|
||||
|
||||
if (data) {
|
||||
/* Setup BVHTreeFromMesh */
|
||||
bvhtree_from_mesh_setup_data(
|
||||
tree, BVHTREE_FROM_VERTS, vert_positions, nullptr, nullptr, nullptr, {}, data);
|
||||
bvhtree_from_mesh_setup_data(tree, BVHTREE_FROM_VERTS, vert_positions, {}, {}, {}, {}, data);
|
||||
}
|
||||
|
||||
return tree;
|
||||
|
@ -825,8 +819,8 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree(float epsilon,
|
|||
return tree;
|
||||
}
|
||||
|
||||
static BVHTree *bvhtree_from_mesh_edges_create_tree(const float (*positions)[3],
|
||||
blender::Span<blender::int2> edges,
|
||||
static BVHTree *bvhtree_from_mesh_edges_create_tree(const Span<float3> positions,
|
||||
const blender::Span<blender::int2> edges,
|
||||
const BitSpan edges_mask,
|
||||
int edges_num_active,
|
||||
float epsilon,
|
||||
|
@ -879,9 +873,8 @@ BVHTree *bvhtree_from_editmesh_edges(
|
|||
}
|
||||
|
||||
BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
|
||||
const float (*vert_positions)[3],
|
||||
const blender::int2 *edge,
|
||||
const int edges_num,
|
||||
const Span<float3> vert_positions,
|
||||
const Span<blender::int2> edges,
|
||||
const BitSpan edges_mask,
|
||||
int edges_num_active,
|
||||
float epsilon,
|
||||
|
@ -889,14 +882,14 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
|
|||
int axis)
|
||||
{
|
||||
BVHTree *tree = bvhtree_from_mesh_edges_create_tree(
|
||||
vert_positions, {edge, edges_num}, edges_mask, edges_num_active, epsilon, tree_type, axis);
|
||||
vert_positions, edges, edges_mask, edges_num_active, epsilon, tree_type, axis);
|
||||
|
||||
bvhtree_balance(tree, false);
|
||||
|
||||
if (data) {
|
||||
/* Setup BVHTreeFromMesh */
|
||||
bvhtree_from_mesh_setup_data(
|
||||
tree, BVHTREE_FROM_EDGES, vert_positions, edge, nullptr, nullptr, {}, data);
|
||||
tree, BVHTREE_FROM_EDGES, vert_positions, edges, {}, {}, {}, data);
|
||||
}
|
||||
|
||||
return tree;
|
||||
|
@ -911,7 +904,7 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
|
|||
static BVHTree *bvhtree_from_mesh_faces_create_tree(float epsilon,
|
||||
int tree_type,
|
||||
int axis,
|
||||
const float (*positions)[3],
|
||||
const Span<float3> positions,
|
||||
const MFace *face,
|
||||
const int faces_num,
|
||||
const BitSpan faces_mask,
|
||||
|
@ -922,7 +915,7 @@ static BVHTree *bvhtree_from_mesh_faces_create_tree(float epsilon,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (positions && face) {
|
||||
if (!positions.is_empty() && face) {
|
||||
for (int i = 0; i < faces_num; i++) {
|
||||
float co[4][3];
|
||||
if (!faces_mask.is_empty() && !faces_mask[i]) {
|
||||
|
@ -992,13 +985,13 @@ static BVHTree *bvhtree_from_editmesh_looptri_create_tree(float epsilon,
|
|||
static BVHTree *bvhtree_from_mesh_looptri_create_tree(float epsilon,
|
||||
int tree_type,
|
||||
int axis,
|
||||
const float (*positions)[3],
|
||||
const int *corner_verts,
|
||||
const Span<float3> positions,
|
||||
const Span<int> corner_verts,
|
||||
const Span<MLoopTri> looptris,
|
||||
const BitSpan looptri_mask,
|
||||
int looptri_num_active)
|
||||
{
|
||||
if (positions == nullptr) {
|
||||
if (positions.is_empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1055,10 +1048,9 @@ BVHTree *bvhtree_from_editmesh_looptri(
|
|||
}
|
||||
|
||||
BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
|
||||
const float (*vert_positions)[3],
|
||||
const int *corner_verts,
|
||||
const MLoopTri *looptri,
|
||||
const int looptri_num,
|
||||
const Span<float3> vert_positions,
|
||||
const Span<int> corner_verts,
|
||||
const Span<MLoopTri> looptris,
|
||||
const BitSpan looptri_mask,
|
||||
int looptri_num_active,
|
||||
float epsilon,
|
||||
|
@ -1070,7 +1062,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
|
|||
axis,
|
||||
vert_positions,
|
||||
corner_verts,
|
||||
{looptri, looptri_num},
|
||||
looptris,
|
||||
looptri_mask,
|
||||
looptri_num_active);
|
||||
|
||||
|
@ -1078,14 +1070,8 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
|
|||
|
||||
if (data) {
|
||||
/* Setup BVHTreeFromMesh */
|
||||
bvhtree_from_mesh_setup_data(tree,
|
||||
BVHTREE_FROM_LOOPTRI,
|
||||
vert_positions,
|
||||
nullptr,
|
||||
nullptr,
|
||||
corner_verts,
|
||||
{looptri, looptri_num},
|
||||
data);
|
||||
bvhtree_from_mesh_setup_data(
|
||||
tree, BVHTREE_FROM_LOOPTRI, vert_positions, {}, corner_verts, looptris, nullptr, data);
|
||||
}
|
||||
|
||||
return tree;
|
||||
|
@ -1134,7 +1120,8 @@ BVHTree *BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data,
|
|||
if (ELEM(bvh_cache_type, BVHTREE_FROM_LOOPTRI, BVHTREE_FROM_LOOPTRI_NO_HIDDEN)) {
|
||||
looptris = mesh->looptris();
|
||||
}
|
||||
const float(*positions)[3] = reinterpret_cast<const float(*)[3]>(mesh->vert_positions().data());
|
||||
|
||||
const Span<float3> positions = mesh->vert_positions();
|
||||
const Span<blender::int2> edges = mesh->edges();
|
||||
const Span<int> corner_verts = mesh->corner_verts();
|
||||
|
||||
|
@ -1142,10 +1129,10 @@ BVHTree *BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data,
|
|||
bvhtree_from_mesh_setup_data(nullptr,
|
||||
bvh_cache_type,
|
||||
positions,
|
||||
edges.data(),
|
||||
(const MFace *)CustomData_get_layer(&mesh->fdata_legacy, CD_MFACE),
|
||||
corner_verts.data(),
|
||||
edges,
|
||||
corner_verts,
|
||||
looptris,
|
||||
(const MFace *)CustomData_get_layer(&mesh->fdata_legacy, CD_MFACE),
|
||||
data);
|
||||
|
||||
bool lock_started = false;
|
||||
|
@ -1164,18 +1151,12 @@ BVHTree *BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data,
|
|||
switch (bvh_cache_type) {
|
||||
case BVHTREE_FROM_LOOSEVERTS: {
|
||||
const blender::bke::LooseVertCache &loose_verts = mesh->loose_verts();
|
||||
data->tree = bvhtree_from_mesh_verts_create_tree(0.0f,
|
||||
tree_type,
|
||||
6,
|
||||
positions,
|
||||
mesh->totvert,
|
||||
loose_verts.is_loose_bits,
|
||||
loose_verts.count);
|
||||
data->tree = bvhtree_from_mesh_verts_create_tree(
|
||||
0.0f, tree_type, 6, positions, loose_verts.is_loose_bits, loose_verts.count);
|
||||
break;
|
||||
}
|
||||
case BVHTREE_FROM_VERTS: {
|
||||
data->tree = bvhtree_from_mesh_verts_create_tree(
|
||||
0.0f, tree_type, 6, positions, mesh->totvert, {}, -1);
|
||||
data->tree = bvhtree_from_mesh_verts_create_tree(0.0f, tree_type, 6, positions, {}, -1);
|
||||
break;
|
||||
}
|
||||
case BVHTREE_FROM_LOOSEEDGES: {
|
||||
|
@ -1211,12 +1192,12 @@ BVHTree *BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data,
|
|||
looptris.size(),
|
||||
&mask_bits_act_len);
|
||||
data->tree = bvhtree_from_mesh_looptri_create_tree(
|
||||
0.0f, tree_type, 6, positions, corner_verts.data(), looptris, mask, mask_bits_act_len);
|
||||
0.0f, tree_type, 6, positions, corner_verts, looptris, mask, mask_bits_act_len);
|
||||
break;
|
||||
}
|
||||
case BVHTREE_FROM_LOOPTRI: {
|
||||
data->tree = bvhtree_from_mesh_looptri_create_tree(
|
||||
0.0f, tree_type, 6, positions, corner_verts.data(), looptris, {}, -1);
|
||||
0.0f, tree_type, 6, positions, corner_verts, looptris, {}, -1);
|
||||
break;
|
||||
}
|
||||
case BVHTREE_FROM_EM_LOOSEVERTS:
|
||||
|
@ -1361,7 +1342,7 @@ void free_bvhtree_from_mesh(BVHTreeFromMesh *data)
|
|||
BLI_bvhtree_free(data->tree);
|
||||
}
|
||||
|
||||
memset(data, 0, sizeof(*data));
|
||||
*data = {};
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -1420,7 +1420,7 @@ static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata,
|
|||
treedata->tree, new_co, no, radius, &rayhit, treedata->raycast_callback, treedata);
|
||||
|
||||
int vert_idx = -1;
|
||||
const int *corner_verts = treedata->corner_verts;
|
||||
const int *corner_verts = treedata->corner_verts.data();
|
||||
const MLoopTri *lt = nullptr;
|
||||
|
||||
if (rayhit.index != -1 && rayhit.dist <= max_length) {
|
||||
|
@ -1430,7 +1430,7 @@ static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata,
|
|||
}
|
||||
|
||||
float min_len = FLT_MAX;
|
||||
lt = &treedata->looptri[rayhit.index];
|
||||
lt = &treedata->looptris[rayhit.index];
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int tmp_vert_idx = corner_verts[lt->tri[i]];
|
||||
|
|
|
@ -1047,8 +1047,10 @@ static void collection_gobject_hash_ensure(Collection *collection)
|
|||
collection_gobject_assert_internal_consistency(collection, true);
|
||||
}
|
||||
|
||||
/** Similar to #collection_gobject_hash_ensure/#collection_gobject_hash_create, but does fix
|
||||
* inconsistencies in the collection objects list. */
|
||||
/**
|
||||
* Similar to #collection_gobject_hash_ensure/#collection_gobject_hash_create, but does fix
|
||||
* inconsistencies in the collection objects list.
|
||||
*/
|
||||
static void collection_gobject_hash_ensure_fix(Collection *collection)
|
||||
{
|
||||
bool changed = false;
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
#include "BKE_object.hh"
|
||||
#include "BKE_object_types.hh"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_shrinkwrap.h"
|
||||
#include "BKE_shrinkwrap.hh"
|
||||
#include "BKE_tracking.h"
|
||||
|
||||
#include "BIK_api.h"
|
||||
|
@ -354,7 +354,8 @@ void BKE_constraint_mat_convertspace(Object *ob,
|
|||
/* local to pose - do inverse procedure that was done for pose to local */
|
||||
else {
|
||||
if (pchan->bone) {
|
||||
/* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */
|
||||
/* We need the:
|
||||
* `posespace_matrix = local_matrix + (parent_posespace_matrix + restpos)`. */
|
||||
BKE_armature_mat_bone_to_pose(pchan, mat, mat);
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
#include "BKE_main.h"
|
||||
#include "BKE_object.hh"
|
||||
#include "BKE_object_types.hh"
|
||||
#include "BKE_vfont.h"
|
||||
#include "BKE_vfont.hh"
|
||||
|
||||
#include "DEG_depsgraph.hh"
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "BKE_displist.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_modifier.hh"
|
||||
#include "BKE_vfont.h"
|
||||
#include "BKE_vfont.hh"
|
||||
|
||||
#include "DEG_depsgraph.hh"
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#include "BKE_modifier.hh"
|
||||
#include "BKE_object.hh"
|
||||
#include "BKE_object_types.hh"
|
||||
#include "BKE_vfont.h"
|
||||
#include "BKE_vfont.hh"
|
||||
|
||||
#include "BLI_sys_types.h" /* For #intptr_t support. */
|
||||
|
||||
|
|
|
@ -3448,9 +3448,9 @@ static void mesh_tris_spherecast_dp(void *userdata,
|
|||
BVHTreeRayHit *hit)
|
||||
{
|
||||
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
|
||||
const float(*positions)[3] = data->vert_positions;
|
||||
const MLoopTri *looptris = data->looptri;
|
||||
const int *corner_verts = data->corner_verts;
|
||||
const blender::Span<blender::float3> positions = data->vert_positions;
|
||||
const MLoopTri *looptris = data->looptris.data();
|
||||
const int *corner_verts = data->corner_verts.data();
|
||||
|
||||
const float *t0, *t1, *t2;
|
||||
float dist;
|
||||
|
@ -3480,9 +3480,9 @@ static void mesh_tris_nearest_point_dp(void *userdata,
|
|||
BVHTreeNearest *nearest)
|
||||
{
|
||||
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
|
||||
const float(*positions)[3] = data->vert_positions;
|
||||
const MLoopTri *looptris = data->looptri;
|
||||
const int *corner_verts = data->corner_verts;
|
||||
const blender::Span<blender::float3> positions = data->vert_positions;
|
||||
const MLoopTri *looptris = data->looptris.data();
|
||||
const int *corner_verts = data->corner_verts.data();
|
||||
float nearest_tmp[3], dist_sq;
|
||||
|
||||
const float *t0, *t1, *t2;
|
||||
|
|
|
@ -670,8 +670,8 @@ bool closest_point_on_surface(SurfaceModifierData *surmd,
|
|||
}
|
||||
|
||||
if (surface_vel) {
|
||||
const int *corner_verts = bvhtree->corner_verts;
|
||||
const MLoopTri *lt = &bvhtree->looptri[nearest.index];
|
||||
const int *corner_verts = bvhtree->corner_verts.data();
|
||||
const MLoopTri *lt = &bvhtree->looptris[nearest.index];
|
||||
|
||||
copy_v3_v3(surface_vel, surmd->runtime.vert_velocities[corner_verts[lt->tri[0]]]);
|
||||
add_v3_v3(surface_vel, surmd->runtime.vert_velocities[corner_verts[lt->tri[1]]]);
|
||||
|
|
|
@ -219,7 +219,7 @@ static Collection *gpencil_get_parent_collection(Scene *scene, Object *ob)
|
|||
return mycol;
|
||||
}
|
||||
static int gpencil_get_stroke_material_fromcurve(
|
||||
Main *bmain, Object *ob_gp, Object *ob_cu, bool *do_stroke, bool *do_fill)
|
||||
Main *bmain, Object *ob_gp, Object *ob_cu, bool *r_do_stroke, bool *r_do_fill)
|
||||
{
|
||||
Curve *cu = (Curve *)ob_cu->data;
|
||||
|
||||
|
@ -234,21 +234,21 @@ static int gpencil_get_stroke_material_fromcurve(
|
|||
* If the has only one material, if the name contains "_stroke",
|
||||
* it's used as a stroke, otherwise as fill. */
|
||||
if (ob_cu->totcol >= 2) {
|
||||
*do_stroke = true;
|
||||
*do_fill = true;
|
||||
*r_do_stroke = true;
|
||||
*r_do_fill = true;
|
||||
mat_curve_fill = BKE_object_material_get(ob_cu, 1);
|
||||
mat_curve_stroke = BKE_object_material_get(ob_cu, 2);
|
||||
}
|
||||
else if (ob_cu->totcol == 1) {
|
||||
mat_curve_stroke = BKE_object_material_get(ob_cu, 1);
|
||||
if ((mat_curve_stroke) && (strstr(mat_curve_stroke->id.name, "_stroke") != nullptr)) {
|
||||
*do_stroke = true;
|
||||
*do_fill = false;
|
||||
*r_do_stroke = true;
|
||||
*r_do_fill = false;
|
||||
mat_curve_fill = nullptr;
|
||||
}
|
||||
else {
|
||||
*do_stroke = false;
|
||||
*do_fill = true;
|
||||
*r_do_stroke = false;
|
||||
*r_do_fill = true;
|
||||
/* Invert materials. */
|
||||
mat_curve_fill = mat_curve_stroke;
|
||||
mat_curve_stroke = nullptr;
|
||||
|
@ -256,7 +256,7 @@ static int gpencil_get_stroke_material_fromcurve(
|
|||
}
|
||||
else {
|
||||
/* No materials in the curve. */
|
||||
*do_fill = false;
|
||||
*r_do_fill = false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -268,11 +268,11 @@ static int gpencil_get_stroke_material_fromcurve(
|
|||
}
|
||||
|
||||
int r_idx = gpencil_check_same_material_color(
|
||||
ob_gp, color_stroke, color_fill, *do_stroke, *do_fill, &mat_gp);
|
||||
ob_gp, color_stroke, color_fill, *r_do_stroke, *r_do_fill, &mat_gp);
|
||||
|
||||
if ((ob_gp->totcol < r_idx) || (r_idx < 0)) {
|
||||
mat_gp = gpencil_add_from_curve_material(
|
||||
bmain, ob_gp, color_stroke, color_fill, *do_stroke, *do_fill, &r_idx);
|
||||
bmain, ob_gp, color_stroke, color_fill, *r_do_stroke, *r_do_fill, &r_idx);
|
||||
}
|
||||
|
||||
/* Set fill and stroke depending of curve type (3D or 2D). */
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include "BKE_object.hh"
|
||||
#include "BKE_object_types.hh"
|
||||
#include "BKE_screen.hh"
|
||||
#include "BKE_shrinkwrap.h"
|
||||
#include "BKE_shrinkwrap.hh"
|
||||
|
||||
#include "DEG_depsgraph.hh"
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
|
|
|
@ -4828,17 +4828,16 @@ void BKE_image_pool_free(ImagePool *pool)
|
|||
}
|
||||
|
||||
BLI_INLINE ImBuf *image_pool_find_item(
|
||||
ImagePool *pool, Image *image, int entry, int index, bool *found)
|
||||
ImagePool *pool, Image *image, int entry, int index, bool *r_found)
|
||||
{
|
||||
*found = false;
|
||||
|
||||
LISTBASE_FOREACH (ImagePoolItem *, item, &pool->image_buffers) {
|
||||
if (item->image == image && item->entry == entry && item->index == index) {
|
||||
*found = true;
|
||||
*r_found = true;
|
||||
return item->ibuf;
|
||||
}
|
||||
}
|
||||
|
||||
*r_found = false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -238,80 +238,80 @@ static AdrBit2Path *adrcode_bitmaps_to_paths(int blocktype, int adrcode, int *to
|
|||
/* ADRCODE to RNA-Path Conversion Code - Standard */
|
||||
|
||||
/* Object types */
|
||||
static const char *ob_adrcodes_to_paths(int adrcode, int *array_index)
|
||||
static const char *ob_adrcodes_to_paths(int adrcode, int *r_array_index)
|
||||
{
|
||||
/* Set array index like this in-case nothing sets it correctly. */
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
|
||||
/* result depends on adrcode */
|
||||
switch (adrcode) {
|
||||
case OB_LOC_X:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "location";
|
||||
case OB_LOC_Y:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "location";
|
||||
case OB_LOC_Z:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "location";
|
||||
case OB_DLOC_X:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "delta_location";
|
||||
case OB_DLOC_Y:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "delta_location";
|
||||
case OB_DLOC_Z:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "delta_location";
|
||||
|
||||
case OB_ROT_X:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "rotation_euler";
|
||||
case OB_ROT_Y:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "rotation_euler";
|
||||
case OB_ROT_Z:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "rotation_euler";
|
||||
case OB_DROT_X:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "delta_rotation_euler";
|
||||
case OB_DROT_Y:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "delta_rotation_euler";
|
||||
case OB_DROT_Z:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "delta_rotation_euler";
|
||||
|
||||
case OB_SIZE_X:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "scale";
|
||||
case OB_SIZE_Y:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "scale";
|
||||
case OB_SIZE_Z:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "scale";
|
||||
case OB_DSIZE_X:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "delta_scale";
|
||||
case OB_DSIZE_Y:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "delta_scale";
|
||||
case OB_DSIZE_Z:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "delta_scale";
|
||||
case OB_COL_R:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "color";
|
||||
case OB_COL_G:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "color";
|
||||
case OB_COL_B:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "color";
|
||||
case OB_COL_A:
|
||||
*array_index = 3;
|
||||
*r_array_index = 3;
|
||||
return "color";
|
||||
#if 0
|
||||
case OB_PD_FSTR:
|
||||
|
@ -353,54 +353,54 @@ static const char *ob_adrcodes_to_paths(int adrcode, int *array_index)
|
|||
/* PoseChannel types
|
||||
* NOTE: pchan name comes from 'actname' added earlier...
|
||||
*/
|
||||
static const char *pchan_adrcodes_to_paths(int adrcode, int *array_index)
|
||||
static const char *pchan_adrcodes_to_paths(int adrcode, int *r_array_index)
|
||||
{
|
||||
/* Set array index like this in-case nothing sets it correctly. */
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
|
||||
/* result depends on adrcode */
|
||||
switch (adrcode) {
|
||||
case AC_QUAT_W:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "rotation_quaternion";
|
||||
case AC_QUAT_X:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "rotation_quaternion";
|
||||
case AC_QUAT_Y:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "rotation_quaternion";
|
||||
case AC_QUAT_Z:
|
||||
*array_index = 3;
|
||||
*r_array_index = 3;
|
||||
return "rotation_quaternion";
|
||||
|
||||
case AC_EUL_X:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "rotation_euler";
|
||||
case AC_EUL_Y:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "rotation_euler";
|
||||
case AC_EUL_Z:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "rotation_euler";
|
||||
|
||||
case AC_LOC_X:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "location";
|
||||
case AC_LOC_Y:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "location";
|
||||
case AC_LOC_Z:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "location";
|
||||
|
||||
case AC_SIZE_X:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "scale";
|
||||
case AC_SIZE_Y:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "scale";
|
||||
case AC_SIZE_Z:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "scale";
|
||||
}
|
||||
|
||||
|
@ -410,10 +410,10 @@ static const char *pchan_adrcodes_to_paths(int adrcode, int *array_index)
|
|||
}
|
||||
|
||||
/* Constraint types */
|
||||
static const char *constraint_adrcodes_to_paths(int adrcode, int *array_index)
|
||||
static const char *constraint_adrcodes_to_paths(int adrcode, int *r_array_index)
|
||||
{
|
||||
/* Set array index like this in-case nothing sets it correctly. */
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
|
||||
/* result depends on adrcode */
|
||||
switch (adrcode) {
|
||||
|
@ -431,7 +431,7 @@ static const char *constraint_adrcodes_to_paths(int adrcode, int *array_index)
|
|||
* NOTE: as we don't have access to the keyblock where the data comes from (for now),
|
||||
* we'll just use numerical indices for now...
|
||||
*/
|
||||
static char *shapekey_adrcodes_to_paths(ID *id, int adrcode, int * /*array_index*/)
|
||||
static char *shapekey_adrcodes_to_paths(ID *id, int adrcode, int * /*r_array_index*/)
|
||||
{
|
||||
static char buf[128];
|
||||
|
||||
|
@ -461,7 +461,7 @@ static char *shapekey_adrcodes_to_paths(ID *id, int adrcode, int * /*array_index
|
|||
}
|
||||
|
||||
/* MTex (Texture Slot) types */
|
||||
static const char *mtex_adrcodes_to_paths(int adrcode, int * /*array_index*/)
|
||||
static const char *mtex_adrcodes_to_paths(int adrcode, int * /*r_array_index*/)
|
||||
{
|
||||
const char *base = nullptr, *prop = nullptr;
|
||||
static char buf[128];
|
||||
|
@ -581,10 +581,10 @@ static const char *mtex_adrcodes_to_paths(int adrcode, int * /*array_index*/)
|
|||
}
|
||||
|
||||
/* Texture types */
|
||||
static const char *texture_adrcodes_to_paths(int adrcode, int *array_index)
|
||||
static const char *texture_adrcodes_to_paths(int adrcode, int *r_array_index)
|
||||
{
|
||||
/* Set array index like this in-case nothing sets it correctly. */
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
|
||||
/* result depends on adrcode */
|
||||
switch (adrcode) {
|
||||
|
@ -607,16 +607,16 @@ static const char *texture_adrcodes_to_paths(int adrcode, int *array_index)
|
|||
|
||||
/* voronoi */
|
||||
case TE_VNW1:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "feature_weights";
|
||||
case TE_VNW2:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "feature_weights";
|
||||
case TE_VNW3:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "feature_weights";
|
||||
case TE_VNW4:
|
||||
*array_index = 3;
|
||||
*r_array_index = 3;
|
||||
return "feature_weights";
|
||||
case TE_VNMEXP:
|
||||
return "minkovsky_exponent";
|
||||
|
@ -649,13 +649,13 @@ static const char *texture_adrcodes_to_paths(int adrcode, int *array_index)
|
|||
return "gain";
|
||||
|
||||
case TE_COL_R:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "rgb_factor";
|
||||
case TE_COL_G:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "rgb_factor";
|
||||
case TE_COL_B:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "rgb_factor";
|
||||
|
||||
case TE_BRIGHT:
|
||||
|
@ -668,41 +668,41 @@ static const char *texture_adrcodes_to_paths(int adrcode, int *array_index)
|
|||
}
|
||||
|
||||
/* Material Types */
|
||||
static const char *material_adrcodes_to_paths(int adrcode, int *array_index)
|
||||
static const char *material_adrcodes_to_paths(int adrcode, int *r_array_index)
|
||||
{
|
||||
/* Set array index like this in-case nothing sets it correctly. */
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
|
||||
/* result depends on adrcode */
|
||||
switch (adrcode) {
|
||||
case MA_COL_R:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "diffuse_color";
|
||||
case MA_COL_G:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "diffuse_color";
|
||||
case MA_COL_B:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "diffuse_color";
|
||||
|
||||
case MA_SPEC_R:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "specular_color";
|
||||
case MA_SPEC_G:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "specular_color";
|
||||
case MA_SPEC_B:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "specular_color";
|
||||
|
||||
case MA_MIR_R:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "mirror_color";
|
||||
case MA_MIR_G:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "mirror_color";
|
||||
case MA_MIR_B:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "mirror_color";
|
||||
|
||||
case MA_ALPHA:
|
||||
|
@ -754,17 +754,17 @@ static const char *material_adrcodes_to_paths(int adrcode, int *array_index)
|
|||
return "halo.add";
|
||||
|
||||
default: /* for now, we assume that the others were MTex channels */
|
||||
return mtex_adrcodes_to_paths(adrcode, array_index);
|
||||
return mtex_adrcodes_to_paths(adrcode, r_array_index);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Camera Types */
|
||||
static const char *camera_adrcodes_to_paths(int adrcode, int *array_index)
|
||||
static const char *camera_adrcodes_to_paths(int adrcode, int *r_array_index)
|
||||
{
|
||||
/* Set array index like this in-case nothing sets it correctly. */
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
|
||||
/* result depends on adrcode */
|
||||
switch (adrcode) {
|
||||
|
@ -806,10 +806,10 @@ static const char *camera_adrcodes_to_paths(int adrcode, int *array_index)
|
|||
}
|
||||
|
||||
/* Light Types */
|
||||
static const char *light_adrcodes_to_paths(int adrcode, int *array_index)
|
||||
static const char *light_adrcodes_to_paths(int adrcode, int *r_array_index)
|
||||
{
|
||||
/* Set array index like this in-case nothing sets it correctly. */
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
|
||||
/* result depends on adrcode */
|
||||
switch (adrcode) {
|
||||
|
@ -817,13 +817,13 @@ static const char *light_adrcodes_to_paths(int adrcode, int *array_index)
|
|||
return "energy";
|
||||
|
||||
case LA_COL_R:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "color";
|
||||
case LA_COL_G:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "color";
|
||||
case LA_COL_B:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "color";
|
||||
|
||||
case LA_DIST:
|
||||
|
@ -843,7 +843,7 @@ static const char *light_adrcodes_to_paths(int adrcode, int *array_index)
|
|||
return "halo_intensity";
|
||||
|
||||
default: /* for now, we assume that the others were MTex channels */
|
||||
return mtex_adrcodes_to_paths(adrcode, array_index);
|
||||
return mtex_adrcodes_to_paths(adrcode, r_array_index);
|
||||
}
|
||||
|
||||
/* unrecognized adrcode, or not-yet-handled ones! */
|
||||
|
@ -851,10 +851,10 @@ static const char *light_adrcodes_to_paths(int adrcode, int *array_index)
|
|||
}
|
||||
|
||||
/* Sound Types */
|
||||
static const char *sound_adrcodes_to_paths(int adrcode, int *array_index)
|
||||
static const char *sound_adrcodes_to_paths(int adrcode, int *r_array_index)
|
||||
{
|
||||
/* Set array index like this in-case nothing sets it correctly. */
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
|
||||
/* result depends on adrcode */
|
||||
switch (adrcode) {
|
||||
|
@ -877,30 +877,30 @@ static const char *sound_adrcodes_to_paths(int adrcode, int *array_index)
|
|||
}
|
||||
|
||||
/* World Types */
|
||||
static const char *world_adrcodes_to_paths(int adrcode, int *array_index)
|
||||
static const char *world_adrcodes_to_paths(int adrcode, int *r_array_index)
|
||||
{
|
||||
/* Set array index like this in-case nothing sets it correctly. */
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
|
||||
/* result depends on adrcode */
|
||||
switch (adrcode) {
|
||||
case WO_HOR_R:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "horizon_color";
|
||||
case WO_HOR_G:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "horizon_color";
|
||||
case WO_HOR_B:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "horizon_color";
|
||||
case WO_ZEN_R:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "zenith_color";
|
||||
case WO_ZEN_G:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "zenith_color";
|
||||
case WO_ZEN_B:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "zenith_color";
|
||||
|
||||
case WO_EXPOS:
|
||||
|
@ -916,17 +916,17 @@ static const char *world_adrcodes_to_paths(int adrcode, int *array_index)
|
|||
return "mist.height";
|
||||
|
||||
default: /* for now, we assume that the others were MTex channels */
|
||||
return mtex_adrcodes_to_paths(adrcode, array_index);
|
||||
return mtex_adrcodes_to_paths(adrcode, r_array_index);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Particle Types */
|
||||
static const char *particle_adrcodes_to_paths(int adrcode, int *array_index)
|
||||
static const char *particle_adrcodes_to_paths(int adrcode, int *r_array_index)
|
||||
{
|
||||
/* Set array index like this in-case nothing sets it correctly. */
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
|
||||
/* result depends on adrcode */
|
||||
switch (adrcode) {
|
||||
|
@ -945,13 +945,13 @@ static const char *particle_adrcodes_to_paths(int adrcode, int *array_index)
|
|||
case PART_LENGTH:
|
||||
return "settings.length";
|
||||
case PART_GRAV_X:
|
||||
*array_index = 0;
|
||||
*r_array_index = 0;
|
||||
return "settings.acceleration";
|
||||
case PART_GRAV_Y:
|
||||
*array_index = 1;
|
||||
*r_array_index = 1;
|
||||
return "settings.acceleration";
|
||||
case PART_GRAV_Z:
|
||||
*array_index = 2;
|
||||
*r_array_index = 2;
|
||||
return "settings.acceleration";
|
||||
case PART_KINK_AMP:
|
||||
return "settings.kink_amplitude";
|
||||
|
@ -1015,7 +1015,7 @@ static const char *particle_adrcodes_to_paths(int adrcode, int *array_index)
|
|||
* - blocktype, adrcode - determines setting to get
|
||||
* - actname, constname, seq - used to build path
|
||||
* Output:
|
||||
* - array_index - index in property's array (if applicable) to use
|
||||
* - r_array_index - index in property's array (if applicable) to use
|
||||
* - return - the allocated path...
|
||||
*/
|
||||
static char *get_rna_access(ID *id,
|
||||
|
@ -1024,7 +1024,7 @@ static char *get_rna_access(ID *id,
|
|||
char actname[],
|
||||
char constname[],
|
||||
Sequence *seq,
|
||||
int *array_index)
|
||||
int *r_array_index)
|
||||
{
|
||||
DynStr *path = BLI_dynstr_new();
|
||||
const char *propname = nullptr;
|
||||
|
@ -1125,8 +1125,8 @@ static char *get_rna_access(ID *id,
|
|||
*/
|
||||
if ((propname == nullptr) && (blocktype > 0)) {
|
||||
/* nothing was found, so exit */
|
||||
if (array_index) {
|
||||
*array_index = 0;
|
||||
if (r_array_index) {
|
||||
*r_array_index = 0;
|
||||
}
|
||||
|
||||
BLI_dynstr_free(path);
|
||||
|
@ -1134,8 +1134,8 @@ static char *get_rna_access(ID *id,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (array_index) {
|
||||
*array_index = dummy_index;
|
||||
if (r_array_index) {
|
||||
*r_array_index = dummy_index;
|
||||
}
|
||||
|
||||
/* 'buf' _must_ be initialized in this block */
|
||||
|
@ -1193,7 +1193,7 @@ static char *get_rna_access(ID *id,
|
|||
BLI_dynstr_append(path, propname);
|
||||
|
||||
/* if there was no array index pointer provided, add it to the path */
|
||||
if (array_index == nullptr) {
|
||||
if (r_array_index == nullptr) {
|
||||
SNPRINTF(buf, "[\"%d\"]", dummy_index);
|
||||
BLI_dynstr_append(path, buf);
|
||||
}
|
||||
|
|
|
@ -641,34 +641,35 @@ static char *key_block_get_data(Key *key, KeyBlock *actkb, KeyBlock *kb, char **
|
|||
return static_cast<char *>(kb->data);
|
||||
}
|
||||
|
||||
/* currently only the first value of 'ofs' may be set. */
|
||||
static bool key_pointer_size(const Key *key, const int mode, int *poinsize, int *ofs, int *step)
|
||||
/* currently only the first value of 'r_ofs' may be set. */
|
||||
static bool key_pointer_size(
|
||||
const Key *key, const int mode, int *r_poinsize, int *r_ofs, int *r_step)
|
||||
{
|
||||
if (key->from == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*step = 1;
|
||||
*r_step = 1;
|
||||
|
||||
switch (GS(key->from->name)) {
|
||||
case ID_ME:
|
||||
*ofs = sizeof(float[KEYELEM_FLOAT_LEN_COORD]);
|
||||
*poinsize = *ofs;
|
||||
*r_ofs = sizeof(float[KEYELEM_FLOAT_LEN_COORD]);
|
||||
*r_poinsize = *r_ofs;
|
||||
break;
|
||||
case ID_LT:
|
||||
*ofs = sizeof(float[KEYELEM_FLOAT_LEN_COORD]);
|
||||
*poinsize = *ofs;
|
||||
*r_ofs = sizeof(float[KEYELEM_FLOAT_LEN_COORD]);
|
||||
*r_poinsize = *r_ofs;
|
||||
break;
|
||||
case ID_CU_LEGACY:
|
||||
if (mode == KEY_MODE_BPOINT) {
|
||||
*ofs = sizeof(float[KEYELEM_FLOAT_LEN_BPOINT]);
|
||||
*step = KEYELEM_ELEM_LEN_BPOINT;
|
||||
*r_ofs = sizeof(float[KEYELEM_FLOAT_LEN_BPOINT]);
|
||||
*r_step = KEYELEM_ELEM_LEN_BPOINT;
|
||||
}
|
||||
else {
|
||||
*ofs = sizeof(float[KEYELEM_FLOAT_LEN_BEZTRIPLE]);
|
||||
*step = KEYELEM_ELEM_LEN_BEZTRIPLE;
|
||||
*r_ofs = sizeof(float[KEYELEM_FLOAT_LEN_BEZTRIPLE]);
|
||||
*r_step = KEYELEM_ELEM_LEN_BEZTRIPLE;
|
||||
}
|
||||
*poinsize = sizeof(float[KEYELEM_ELEM_SIZE_CURVE]);
|
||||
*r_poinsize = sizeof(float[KEYELEM_ELEM_SIZE_CURVE]);
|
||||
break;
|
||||
default:
|
||||
BLI_assert_msg(0, "invalid 'key->from' ID type");
|
||||
|
@ -1605,6 +1606,7 @@ float *BKE_key_evaluate_object_ex(
|
|||
const int totvert = min_ii(tot, mesh->totvert);
|
||||
mesh->vert_positions_for_write().take_front(totvert).copy_from(
|
||||
{reinterpret_cast<const blender::float3 *>(out), totvert});
|
||||
BKE_mesh_tag_positions_changed(mesh);
|
||||
break;
|
||||
}
|
||||
case ID_LT: {
|
||||
|
|
|
@ -94,9 +94,11 @@ BLI_INLINE IDOverrideLibraryRuntime *override_library_runtime_ensure(
|
|||
return liboverride->runtime;
|
||||
}
|
||||
|
||||
/** Helper to preserve Pose mode on override objects.
|
||||
/**
|
||||
* Helper to preserve Pose mode on override objects.
|
||||
* A bit annoying to have this special case, but not much to be done here currently, since the
|
||||
* matching RNA property is read-only. */
|
||||
* matching RNA property is read-only.
|
||||
*/
|
||||
BLI_INLINE void lib_override_object_posemode_transfer(ID *id_dst, ID *id_src)
|
||||
{
|
||||
if (GS(id_src->name) == ID_OB && GS(id_dst->name) == ID_OB) {
|
||||
|
@ -3420,10 +3422,12 @@ static int lib_override_sort_libraries_func(LibraryIDLinkCallbackData *cb_data)
|
|||
return IDWALK_RET_NOP;
|
||||
}
|
||||
|
||||
/** Define the `temp_index` of libraries from their highest level of indirect usage.
|
||||
/**
|
||||
* Define the `temp_index` of libraries from their highest level of indirect usage.
|
||||
*
|
||||
* E.g. if lib_a uses lib_b, lib_c and lib_d, and lib_b also uses lib_d, then lib_a has an index of
|
||||
* 1, lib_b and lib_c an index of 2, and lib_d an index of 3. */
|
||||
* 1, lib_b and lib_c an index of 2, and lib_d an index of 3.
|
||||
*/
|
||||
static int lib_override_libraries_index_define(Main *bmain)
|
||||
{
|
||||
LISTBASE_FOREACH (Library *, library, &bmain->libraries) {
|
||||
|
|
|
@ -653,7 +653,10 @@ bool BKE_library_ID_is_indirectly_used(Main *bmain, void *idv)
|
|||
return library_ID_is_used(bmain, idv, true);
|
||||
}
|
||||
|
||||
void BKE_library_ID_test_usages(Main *bmain, void *idv, bool *is_used_local, bool *is_used_linked)
|
||||
void BKE_library_ID_test_usages(Main *bmain,
|
||||
void *idv,
|
||||
bool *r_is_used_local,
|
||||
bool *r_is_used_linked)
|
||||
{
|
||||
IDUsersIter iter;
|
||||
ListBase *lb_array[INDEX_ID_MAX];
|
||||
|
@ -683,8 +686,8 @@ void BKE_library_ID_test_usages(Main *bmain, void *idv, bool *is_used_local, boo
|
|||
}
|
||||
}
|
||||
|
||||
*is_used_local = (iter.count_direct != 0);
|
||||
*is_used_linked = (iter.count_indirect != 0);
|
||||
*r_is_used_local = (iter.count_direct != 0);
|
||||
*r_is_used_linked = (iter.count_indirect != 0);
|
||||
}
|
||||
|
||||
/* ***** IDs usages.checking/tagging. ***** */
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
#include "BKE_object_types.hh"
|
||||
#include "BKE_preview_image.hh"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_vfont.h"
|
||||
#include "BKE_vfont.hh"
|
||||
|
||||
#include "DEG_depsgraph.hh"
|
||||
#include "DEG_depsgraph_build.hh"
|
||||
|
|
|
@ -278,7 +278,9 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
|
|||
CustomData_blend_write_prepare(mesh->edge_data, edge_layers, {});
|
||||
CustomData_blend_write_prepare(mesh->loop_data, loop_layers, {});
|
||||
CustomData_blend_write_prepare(mesh->face_data, face_layers, {});
|
||||
mesh_sculpt_mask_to_legacy(vert_layers);
|
||||
if (!is_undo) {
|
||||
mesh_sculpt_mask_to_legacy(vert_layers);
|
||||
}
|
||||
}
|
||||
|
||||
mesh->runtime = nullptr;
|
||||
|
@ -1078,27 +1080,6 @@ void BKE_mesh_sharp_edges_set_from_angle(Mesh *me, const float angle)
|
|||
sharp_edges.finish();
|
||||
}
|
||||
|
||||
void BKE_mesh_looptri_get_real_edges(const blender::int2 *edges,
|
||||
const int *corner_verts,
|
||||
const int *corner_edges,
|
||||
const MLoopTri *tri,
|
||||
int r_edges[3])
|
||||
{
|
||||
for (int i = 2, i_next = 0; i_next < 3; i = i_next++) {
|
||||
const int corner_1 = tri->tri[i];
|
||||
const int corner_2 = tri->tri[i_next];
|
||||
const int vert_1 = corner_verts[corner_1];
|
||||
const int vert_2 = corner_verts[corner_2];
|
||||
const int edge_i = corner_edges[corner_1];
|
||||
const blender::int2 &edge = edges[edge_i];
|
||||
|
||||
bool is_real = (vert_1 == edge[0] && vert_2 == edge[1]) ||
|
||||
(vert_1 == edge[1] && vert_2 == edge[0]);
|
||||
|
||||
r_edges[i] = is_real ? edge_i : -1;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<blender::Bounds<blender::float3>> Mesh::bounds_min_max() const
|
||||
{
|
||||
using namespace blender;
|
||||
|
@ -1322,37 +1303,6 @@ void BKE_mesh_count_selected_items(const Mesh *mesh, int r_count[3])
|
|||
/* We could support faces in paint modes. */
|
||||
}
|
||||
|
||||
float (*BKE_mesh_vert_coords_alloc(const Mesh *mesh, int *r_vert_len))[3]
|
||||
{
|
||||
float(*vert_coords)[3] = (float(*)[3])MEM_mallocN(sizeof(float[3]) * mesh->totvert, __func__);
|
||||
MutableSpan(reinterpret_cast<float3 *>(vert_coords), mesh->totvert)
|
||||
.copy_from(mesh->vert_positions());
|
||||
if (r_vert_len) {
|
||||
*r_vert_len = mesh->totvert;
|
||||
}
|
||||
return vert_coords;
|
||||
}
|
||||
|
||||
void BKE_mesh_vert_coords_apply(Mesh *mesh, const float (*vert_coords)[3])
|
||||
{
|
||||
MutableSpan<float3> positions = mesh->vert_positions_for_write();
|
||||
for (const int i : positions.index_range()) {
|
||||
copy_v3_v3(positions[i], vert_coords[i]);
|
||||
}
|
||||
BKE_mesh_tag_positions_changed(mesh);
|
||||
}
|
||||
|
||||
void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh,
|
||||
const float (*vert_coords)[3],
|
||||
const float mat[4][4])
|
||||
{
|
||||
MutableSpan<float3> positions = mesh->vert_positions_for_write();
|
||||
for (const int i : positions.index_range()) {
|
||||
mul_v3_m4v3(positions[i], mat, vert_coords[i]);
|
||||
}
|
||||
BKE_mesh_tag_positions_changed(mesh);
|
||||
}
|
||||
|
||||
/* **** Depsgraph evaluation **** */
|
||||
|
||||
void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *mesh)
|
||||
|
|
|
@ -39,13 +39,13 @@ using std::array;
|
|||
|
||||
class VertexWeight {
|
||||
public:
|
||||
virtual float weight_at_index(const int index) = 0;
|
||||
virtual float weight_at_index(const int index) const = 0;
|
||||
virtual ~VertexWeight() = default;
|
||||
};
|
||||
|
||||
class LoopWeight {
|
||||
public:
|
||||
virtual float weight_at_index(const int index) = 0;
|
||||
virtual float weight_at_index(const int index) const = 0;
|
||||
virtual ~LoopWeight() = default;
|
||||
};
|
||||
|
||||
|
@ -81,13 +81,13 @@ class FairingContext {
|
|||
|
||||
virtual ~FairingContext() = default;
|
||||
|
||||
void fair_verts(bool *affected,
|
||||
void fair_verts(const bool affected_verts[],
|
||||
const eMeshFairingDepth depth,
|
||||
VertexWeight *vertex_weight,
|
||||
LoopWeight *loop_weight)
|
||||
const VertexWeight *vertex_weight,
|
||||
const LoopWeight *loop_weight)
|
||||
{
|
||||
|
||||
fair_verts_ex(affected, int(depth), vertex_weight, loop_weight);
|
||||
fair_verts_ex(affected_verts, int(depth), vertex_weight, loop_weight);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -105,8 +105,8 @@ class FairingContext {
|
|||
float multiplier,
|
||||
const int depth,
|
||||
Map<int, int> &vert_col_map,
|
||||
VertexWeight *vertex_weight,
|
||||
LoopWeight *loop_weight)
|
||||
const VertexWeight *vertex_weight,
|
||||
const LoopWeight *loop_weight)
|
||||
{
|
||||
if (depth == 0) {
|
||||
if (vert_col_map.contains(v)) {
|
||||
|
@ -147,15 +147,15 @@ class FairingContext {
|
|||
loop_weight);
|
||||
}
|
||||
|
||||
void fair_verts_ex(const bool *affected,
|
||||
void fair_verts_ex(const bool affected_verts[],
|
||||
const int order,
|
||||
VertexWeight *vertex_weight,
|
||||
LoopWeight *loop_weight)
|
||||
const VertexWeight *vertex_weight,
|
||||
const LoopWeight *loop_weight)
|
||||
{
|
||||
Map<int, int> vert_col_map;
|
||||
int affected_verts_num = 0;
|
||||
for (int i = 0; i < totvert_; i++) {
|
||||
if (!affected[i]) {
|
||||
if (!affected_verts[i]) {
|
||||
continue;
|
||||
}
|
||||
vert_col_map.add(i, affected_verts_num);
|
||||
|
@ -331,7 +331,7 @@ class UniformVertexWeight : public VertexWeight {
|
|||
}
|
||||
}
|
||||
|
||||
float weight_at_index(const int index) override
|
||||
float weight_at_index(const int index) const override
|
||||
{
|
||||
return vertex_weights_[index];
|
||||
}
|
||||
|
@ -384,7 +384,7 @@ class VoronoiVertexWeight : public VertexWeight {
|
|||
}
|
||||
}
|
||||
|
||||
float weight_at_index(const int index) override
|
||||
float weight_at_index(const int index) const override
|
||||
{
|
||||
return vertex_weights_[index];
|
||||
}
|
||||
|
@ -425,14 +425,14 @@ class VoronoiVertexWeight : public VertexWeight {
|
|||
|
||||
class UniformLoopWeight : public LoopWeight {
|
||||
public:
|
||||
float weight_at_index(const int /*index*/) override
|
||||
float weight_at_index(const int /*index*/) const override
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
};
|
||||
|
||||
static void prefair_and_fair_verts(FairingContext *fairing_context,
|
||||
bool *affected_verts,
|
||||
const bool affected_verts[],
|
||||
const eMeshFairingDepth depth)
|
||||
{
|
||||
/* Pre-fair. */
|
||||
|
@ -452,7 +452,7 @@ static void prefair_and_fair_verts(FairingContext *fairing_context,
|
|||
|
||||
void BKE_mesh_prefair_and_fair_verts(Mesh *mesh,
|
||||
blender::MutableSpan<float3> deform_vert_positions,
|
||||
bool *affect_verts,
|
||||
const bool affected_verts[],
|
||||
const eMeshFairingDepth depth)
|
||||
{
|
||||
MutableSpan<float3> deform_positions_span;
|
||||
|
@ -460,13 +460,15 @@ void BKE_mesh_prefair_and_fair_verts(Mesh *mesh,
|
|||
deform_positions_span = deform_vert_positions;
|
||||
}
|
||||
MeshFairingContext *fairing_context = new MeshFairingContext(mesh, deform_positions_span);
|
||||
prefair_and_fair_verts(fairing_context, affect_verts, depth);
|
||||
prefair_and_fair_verts(fairing_context, affected_verts, depth);
|
||||
delete fairing_context;
|
||||
}
|
||||
|
||||
void BKE_bmesh_prefair_and_fair_verts(BMesh *bm, bool *affect_verts, const eMeshFairingDepth depth)
|
||||
void BKE_bmesh_prefair_and_fair_verts(BMesh *bm,
|
||||
const bool affected_verts[],
|
||||
const eMeshFairingDepth depth)
|
||||
{
|
||||
BMeshFairingContext *fairing_context = new BMeshFairingContext(bm);
|
||||
prefair_and_fair_verts(fairing_context, affect_verts, depth);
|
||||
prefair_and_fair_verts(fairing_context, affected_verts, depth);
|
||||
delete fairing_context;
|
||||
}
|
||||
|
|
|
@ -403,6 +403,7 @@ GroupedSpan<int> build_vert_to_edge_map(const Span<int2> edges,
|
|||
}
|
||||
}
|
||||
});
|
||||
sort_small_groups(offsets, 1024, r_indices);
|
||||
return {offsets, r_indices};
|
||||
}
|
||||
|
||||
|
|
|
@ -1431,14 +1431,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
|||
}
|
||||
}
|
||||
}
|
||||
bvhtree_from_mesh_verts_ex(&treedata[tindex],
|
||||
reinterpret_cast<const float(*)[3]>(positions_src.data()),
|
||||
num_verts_src,
|
||||
verts_active,
|
||||
num_verts_active,
|
||||
0.0,
|
||||
2,
|
||||
6);
|
||||
bvhtree_from_mesh_verts_ex(
|
||||
&treedata[tindex], positions_src, verts_active, num_verts_active, 0.0, 2, 6);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1463,10 +1457,9 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
|||
}
|
||||
}
|
||||
bvhtree_from_mesh_looptri_ex(&treedata[tindex],
|
||||
reinterpret_cast<const float(*)[3]>(positions_src.data()),
|
||||
corner_verts_src.data(),
|
||||
looptris_src.data(),
|
||||
int(looptris_src.size()),
|
||||
positions_src,
|
||||
corner_verts_src,
|
||||
looptris_src,
|
||||
looptri_active,
|
||||
num_looptri_active,
|
||||
0.0,
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "BKE_mesh.hh"
|
||||
#include "BKE_mesh_mapping.hh"
|
||||
#include "BKE_mesh_runtime.hh"
|
||||
#include "BKE_shrinkwrap.h"
|
||||
#include "BKE_shrinkwrap.hh"
|
||||
#include "BKE_subdiv_ccg.hh"
|
||||
|
||||
using blender::float3;
|
||||
|
|
|
@ -324,19 +324,26 @@ void looptris_calc_with_normals(const Span<float3> vert_positions,
|
|||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::bke::mesh
|
||||
|
||||
void BKE_mesh_recalc_looptri(const int *corner_verts,
|
||||
const int *face_offsets,
|
||||
const float (*vert_positions)[3],
|
||||
int totvert,
|
||||
int totloop,
|
||||
int faces_num,
|
||||
MLoopTri *mlooptri)
|
||||
int3 looptri_get_real_edges(const Span<int2> edges,
|
||||
const Span<int> corner_verts,
|
||||
const Span<int> corner_edges,
|
||||
const MLoopTri &tri)
|
||||
{
|
||||
blender::bke::mesh::looptris_calc(
|
||||
{reinterpret_cast<const blender::float3 *>(vert_positions), totvert},
|
||||
blender::Span(face_offsets, faces_num + 1),
|
||||
{corner_verts, totloop},
|
||||
{mlooptri, poly_to_tri_count(faces_num, totloop)});
|
||||
int3 real_edges;
|
||||
for (int i = 2, i_next = 0; i_next < 3; i = i_next++) {
|
||||
const int corner_1 = int(tri.tri[i]);
|
||||
const int corner_2 = int(tri.tri[i_next]);
|
||||
const int vert_1 = corner_verts[corner_1];
|
||||
const int vert_2 = corner_verts[corner_2];
|
||||
const int edge_i = corner_edges[corner_1];
|
||||
const int2 edge = edges[edge_i];
|
||||
|
||||
const bool is_real = (vert_1 == edge[0] && vert_2 == edge[1]) ||
|
||||
(vert_1 == edge[1] && vert_2 == edge[0]);
|
||||
|
||||
real_edges[i] = is_real ? edge_i : -1;
|
||||
}
|
||||
return real_edges;
|
||||
}
|
||||
|
||||
} // namespace blender::bke::mesh
|
||||
|
|
|
@ -1427,10 +1427,10 @@ static ImBuf *put_stabilized_frame_to_cache(MovieClip *clip,
|
|||
|
||||
ImBuf *BKE_movieclip_get_stable_ibuf(MovieClip *clip,
|
||||
const MovieClipUser *user,
|
||||
float loc[2],
|
||||
float *scale,
|
||||
float *angle,
|
||||
const int postprocess_flag)
|
||||
const int postprocess_flag,
|
||||
float r_loc[2],
|
||||
float *r_scale,
|
||||
float *r_angle)
|
||||
{
|
||||
ImBuf *ibuf, *stableibuf = nullptr;
|
||||
int framenr = user->framenr;
|
||||
|
@ -1450,29 +1450,29 @@ ImBuf *BKE_movieclip_get_stable_ibuf(MovieClip *clip,
|
|||
stableibuf = put_stabilized_frame_to_cache(clip, user, ibuf, framenr, postprocess_flag);
|
||||
}
|
||||
|
||||
if (loc) {
|
||||
copy_v2_v2(loc, cache->stabilized.loc);
|
||||
if (r_loc) {
|
||||
copy_v2_v2(r_loc, cache->stabilized.loc);
|
||||
}
|
||||
|
||||
if (scale) {
|
||||
*scale = cache->stabilized.scale;
|
||||
if (r_scale) {
|
||||
*r_scale = cache->stabilized.scale;
|
||||
}
|
||||
|
||||
if (angle) {
|
||||
*angle = cache->stabilized.angle;
|
||||
if (r_angle) {
|
||||
*r_angle = cache->stabilized.angle;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (loc) {
|
||||
zero_v2(loc);
|
||||
if (r_loc) {
|
||||
zero_v2(r_loc);
|
||||
}
|
||||
|
||||
if (scale) {
|
||||
*scale = 1.0f;
|
||||
if (r_scale) {
|
||||
*r_scale = 1.0f;
|
||||
}
|
||||
|
||||
if (angle) {
|
||||
*angle = 0.0f;
|
||||
if (r_angle) {
|
||||
*r_angle = 0.0f;
|
||||
}
|
||||
|
||||
stableibuf = ibuf;
|
||||
|
@ -1498,22 +1498,25 @@ bool BKE_movieclip_has_frame(MovieClip *clip, const MovieClipUser *user)
|
|||
return false;
|
||||
}
|
||||
|
||||
void BKE_movieclip_get_size(MovieClip *clip, const MovieClipUser *user, int *width, int *height)
|
||||
void BKE_movieclip_get_size(MovieClip *clip,
|
||||
const MovieClipUser *user,
|
||||
int *r_width,
|
||||
int *r_height)
|
||||
{
|
||||
/* TODO(sergey): Support reading sequences of different resolution. */
|
||||
if (clip->lastsize[0] != 0 && clip->lastsize[1] != 0) {
|
||||
*width = clip->lastsize[0];
|
||||
*height = clip->lastsize[1];
|
||||
*r_width = clip->lastsize[0];
|
||||
*r_height = clip->lastsize[1];
|
||||
}
|
||||
else {
|
||||
ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user);
|
||||
|
||||
if (ibuf && ibuf->x && ibuf->y) {
|
||||
real_ibuf_size(clip, user, ibuf, width, height);
|
||||
real_ibuf_size(clip, user, ibuf, r_width, r_height);
|
||||
}
|
||||
else {
|
||||
*width = clip->lastsize[0];
|
||||
*height = clip->lastsize[1];
|
||||
*r_width = clip->lastsize[0];
|
||||
*r_height = clip->lastsize[1];
|
||||
}
|
||||
|
||||
if (ibuf) {
|
||||
|
@ -1521,13 +1524,13 @@ void BKE_movieclip_get_size(MovieClip *clip, const MovieClipUser *user, int *wid
|
|||
}
|
||||
}
|
||||
}
|
||||
void BKE_movieclip_get_size_fl(MovieClip *clip, const MovieClipUser *user, float size[2])
|
||||
void BKE_movieclip_get_size_fl(MovieClip *clip, const MovieClipUser *user, float r_size[2])
|
||||
{
|
||||
int width, height;
|
||||
BKE_movieclip_get_size(clip, user, &width, &height);
|
||||
|
||||
size[0] = float(width);
|
||||
size[1] = float(height);
|
||||
r_size[0] = float(width);
|
||||
r_size[1] = float(height);
|
||||
}
|
||||
|
||||
int BKE_movieclip_get_duration(MovieClip *clip)
|
||||
|
@ -1550,7 +1553,7 @@ float BKE_movieclip_get_fps(MovieClip *clip)
|
|||
}
|
||||
short frs_sec;
|
||||
float frs_sec_base;
|
||||
if (IMB_anim_get_fps(clip->anim, &frs_sec, &frs_sec_base, true)) {
|
||||
if (IMB_anim_get_fps(clip->anim, true, &frs_sec, &frs_sec_base)) {
|
||||
return float(frs_sec) / frs_sec_base;
|
||||
}
|
||||
return 0.0f;
|
||||
|
|
|
@ -246,8 +246,8 @@ Mesh *BKE_multires_create_mesh(Depsgraph *depsgraph, Object *object, MultiresMod
|
|||
return result;
|
||||
}
|
||||
|
||||
float (*BKE_multires_create_deformed_base_mesh_vert_coords(
|
||||
Depsgraph *depsgraph, Object *object, MultiresModifierData *mmd, int *r_num_deformed_verts))[3]
|
||||
blender::Array<blender::float3> BKE_multires_create_deformed_base_mesh_vert_coords(
|
||||
Depsgraph *depsgraph, Object *object, MultiresModifierData *mmd)
|
||||
{
|
||||
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
|
||||
Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
|
||||
|
@ -272,34 +272,22 @@ float (*BKE_multires_create_deformed_base_mesh_vert_coords(
|
|||
|
||||
Mesh *base_mesh = static_cast<Mesh *>(object->data);
|
||||
|
||||
int num_deformed_verts;
|
||||
float(*deformed_verts)[3] = BKE_mesh_vert_coords_alloc(base_mesh, &num_deformed_verts);
|
||||
blender::Array<blender::float3> deformed_verts(base_mesh->vert_positions());
|
||||
|
||||
for (ModifierData *md = first_md; md != nullptr; md = md->next) {
|
||||
const ModifierTypeInfo *mti = BKE_modifier_get_info(ModifierType(md->type));
|
||||
|
||||
if (md == &mmd->modifier) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!BKE_modifier_is_enabled(scene_eval, md, required_mode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mti->type != ModifierTypeType::OnlyDeform) {
|
||||
break;
|
||||
}
|
||||
|
||||
BKE_modifier_deform_verts(
|
||||
md,
|
||||
&mesh_eval_context,
|
||||
base_mesh,
|
||||
{reinterpret_cast<blender::float3 *>(deformed_verts), num_deformed_verts});
|
||||
BKE_modifier_deform_verts(md, &mesh_eval_context, base_mesh, deformed_verts);
|
||||
}
|
||||
|
||||
if (r_num_deformed_verts != nullptr) {
|
||||
*r_num_deformed_verts = num_deformed_verts;
|
||||
}
|
||||
return deformed_verts;
|
||||
}
|
||||
|
||||
|
@ -1228,12 +1216,11 @@ void multires_stitch_grids(Object *ob)
|
|||
/* NOTE: Currently CCG does not keep track of faces, making it impossible
|
||||
* to use BKE_pbvh_get_grid_updates().
|
||||
*/
|
||||
CCGFace **faces;
|
||||
int num_faces;
|
||||
BKE_pbvh_get_grid_updates(pbvh, false, (void ***)&faces, &num_faces);
|
||||
if (num_faces) {
|
||||
BKE_subdiv_ccg_average_stitch_faces(subdiv_ccg, faces, num_faces);
|
||||
MEM_freeN(faces);
|
||||
blender::IndexMaskMemory memory;
|
||||
blender::Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(pbvh, {});
|
||||
const blender::IndexMask mask = BKE_pbvh_get_grid_updates(pbvh, nodes, memory);
|
||||
if (!mask.is_empty()) {
|
||||
BKE_subdiv_ccg_average_stitch_faces(*subdiv_ccg, mask);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -89,6 +89,7 @@ bool multiresModifier_reshapeFromDeformModifier(Depsgraph *depsgraph,
|
|||
MultiresModifierData *mmd,
|
||||
ModifierData *deform_md)
|
||||
{
|
||||
using namespace blender;
|
||||
MultiresModifierData highest_mmd = blender::dna::shallow_copy(*mmd);
|
||||
highest_mmd.sculptlvl = highest_mmd.totlvl;
|
||||
highest_mmd.lvl = highest_mmd.totlvl;
|
||||
|
@ -97,8 +98,7 @@ bool multiresModifier_reshapeFromDeformModifier(Depsgraph *depsgraph,
|
|||
/* Create mesh for the multires, ignoring any further modifiers (leading
|
||||
* deformation modifiers will be applied though). */
|
||||
Mesh *multires_mesh = BKE_multires_create_mesh(depsgraph, object, &highest_mmd);
|
||||
int num_deformed_verts;
|
||||
float(*deformed_verts)[3] = BKE_mesh_vert_coords_alloc(multires_mesh, &num_deformed_verts);
|
||||
Array<float3> deformed_verts(multires_mesh->vert_positions());
|
||||
|
||||
/* Apply deformation modifier on the multires, */
|
||||
ModifierEvalContext modifier_ctx{};
|
||||
|
@ -106,19 +106,16 @@ bool multiresModifier_reshapeFromDeformModifier(Depsgraph *depsgraph,
|
|||
modifier_ctx.object = object;
|
||||
modifier_ctx.flag = MOD_APPLY_USECACHE | MOD_APPLY_IGNORE_SIMPLIFY;
|
||||
|
||||
BKE_modifier_deform_verts(
|
||||
deform_md,
|
||||
&modifier_ctx,
|
||||
multires_mesh,
|
||||
{reinterpret_cast<blender::float3 *>(deformed_verts), num_deformed_verts});
|
||||
BKE_modifier_deform_verts(deform_md, &modifier_ctx, multires_mesh, deformed_verts);
|
||||
BKE_id_free(nullptr, multires_mesh);
|
||||
|
||||
/* Reshaping */
|
||||
bool result = multiresModifier_reshapeFromVertcos(
|
||||
depsgraph, object, &highest_mmd, deformed_verts, num_deformed_verts);
|
||||
|
||||
/* Cleanup */
|
||||
MEM_freeN(deformed_verts);
|
||||
depsgraph,
|
||||
object,
|
||||
&highest_mmd,
|
||||
reinterpret_cast<float(*)[3]>(deformed_verts.data()),
|
||||
deformed_verts.size());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -159,11 +159,10 @@ void multires_reshape_apply_base_refine_from_deform(MultiresReshapeContext *resh
|
|||
BLI_assert(object != nullptr);
|
||||
BLI_assert(mmd != nullptr);
|
||||
|
||||
float(*deformed_verts)[3] = BKE_multires_create_deformed_base_mesh_vert_coords(
|
||||
depsgraph, object, mmd, nullptr);
|
||||
blender::Array<blender::float3> deformed_verts =
|
||||
BKE_multires_create_deformed_base_mesh_vert_coords(depsgraph, object, mmd);
|
||||
|
||||
BKE_subdiv_eval_refine_from_mesh(
|
||||
reshape_context->subdiv, reshape_context->base_mesh, deformed_verts);
|
||||
|
||||
MEM_freeN(deformed_verts);
|
||||
BKE_subdiv_eval_refine_from_mesh(reshape_context->subdiv,
|
||||
reshape_context->base_mesh,
|
||||
reinterpret_cast<float(*)[3]>(deformed_verts.data()));
|
||||
}
|
||||
|
|
|
@ -19,12 +19,12 @@ bool multires_reshape_assign_final_coords_from_ccg(const MultiresReshapeContext
|
|||
SubdivCCG *subdiv_ccg)
|
||||
{
|
||||
CCGKey reshape_level_key;
|
||||
BKE_subdiv_ccg_key(&reshape_level_key, subdiv_ccg, reshape_context->reshape.level);
|
||||
BKE_subdiv_ccg_key(reshape_level_key, *subdiv_ccg, reshape_context->reshape.level);
|
||||
|
||||
const int reshape_grid_size = reshape_context->reshape.grid_size;
|
||||
const float reshape_grid_size_1_inv = 1.0f / (float(reshape_grid_size) - 1.0f);
|
||||
|
||||
int num_grids = subdiv_ccg->num_grids;
|
||||
int num_grids = subdiv_ccg->grids.size();
|
||||
for (int grid_index = 0; grid_index < num_grids; ++grid_index) {
|
||||
CCGElem *ccg_grid = subdiv_ccg->grids[grid_index];
|
||||
for (int y = 0; y < reshape_grid_size; ++y) {
|
||||
|
@ -46,7 +46,7 @@ bool multires_reshape_assign_final_coords_from_ccg(const MultiresReshapeContext
|
|||
sizeof(float[3]));
|
||||
|
||||
/* NOTE: The sculpt mode might have SubdivCCG's data out of sync from what is stored in
|
||||
* the original object. This happens upon the following scenario:
|
||||
* the original object. This happens in the following scenario:
|
||||
*
|
||||
* - User enters sculpt mode of the default cube object.
|
||||
* - Sculpt mode creates new `layer`
|
||||
|
@ -61,9 +61,9 @@ bool multires_reshape_assign_final_coords_from_ccg(const MultiresReshapeContext
|
|||
* for example, that if the undo system says object does not have paint mask layer, it is
|
||||
* not to be updated.
|
||||
*
|
||||
* This is a fragile logic, and is only working correctly because the code path is only
|
||||
* This is fragile logic, and is only working correctly because the code path is only
|
||||
* used by sculpt changes. In other use cases the code might not catch inconsistency and
|
||||
* silently do wrong decision. */
|
||||
* silently make the wrong decision. */
|
||||
/* NOTE: There is a known bug in Undo code that results in first Sculpt step
|
||||
* after a Memfile one to never be undone (see #83806). This might be the root cause of
|
||||
* this inconsistency. */
|
||||
|
|
|
@ -129,7 +129,7 @@
|
|||
#include "BKE_speaker.h"
|
||||
#include "BKE_subdiv_ccg.hh"
|
||||
#include "BKE_subsurf.hh"
|
||||
#include "BKE_vfont.h"
|
||||
#include "BKE_vfont.hh"
|
||||
#include "BKE_volume.hh"
|
||||
|
||||
#include "DEG_depsgraph.hh"
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
#include "BKE_particle.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_type_conversions.hh"
|
||||
#include "BKE_vfont.h"
|
||||
#include "BKE_vfont.hh"
|
||||
|
||||
#include "DEG_depsgraph.hh"
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "BKE_packedFile.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_sound.h"
|
||||
#include "BKE_vfont.h"
|
||||
#include "BKE_vfont.hh"
|
||||
#include "BKE_volume.hh"
|
||||
|
||||
#include "IMB_imbuf.h"
|
||||
|
|
|
@ -2150,24 +2150,24 @@ void BKE_sculpt_sync_face_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv_ccg)
|
|||
".hide_poly", ATTR_DOMAIN_FACE, false);
|
||||
if (hide_poly.is_single() && !hide_poly.get_internal_single()) {
|
||||
/* Nothing is hidden, so we can just remove all visibility bitmaps. */
|
||||
for (const int i : IndexRange(subdiv_ccg->num_grids)) {
|
||||
BKE_subdiv_ccg_grid_hidden_free(subdiv_ccg, i);
|
||||
for (const int i : subdiv_ccg->grid_hidden.index_range()) {
|
||||
BKE_subdiv_ccg_grid_hidden_free(*subdiv_ccg, i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const VArraySpan<bool> hide_poly_span(hide_poly);
|
||||
CCGKey key;
|
||||
BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
|
||||
BKE_subdiv_ccg_key_top_level(key, *subdiv_ccg);
|
||||
for (int i = 0; i < mesh->totloop; i++) {
|
||||
const int face_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, i);
|
||||
const int face_index = BKE_subdiv_ccg_grid_to_face_index(*subdiv_ccg, i);
|
||||
const bool is_hidden = hide_poly_span[face_index];
|
||||
|
||||
/* Avoid creating and modifying the grid_hidden bitmap if the base mesh face is visible and
|
||||
* there is not bitmap for the grid. This is because missing grid_hidden implies grid is fully
|
||||
* visible. */
|
||||
if (is_hidden) {
|
||||
BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg, i);
|
||||
BKE_subdiv_ccg_grid_hidden_ensure(*subdiv_ccg, i);
|
||||
}
|
||||
|
||||
BLI_bitmap *gh = subdiv_ccg->grid_hidden[i];
|
||||
|
@ -2209,7 +2209,7 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform)
|
|||
static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg)
|
||||
{
|
||||
CCGKey key;
|
||||
BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
|
||||
BKE_subdiv_ccg_key_top_level(key, *subdiv_ccg);
|
||||
PBVH *pbvh = BKE_pbvh_new(PBVH_GRIDS);
|
||||
|
||||
Mesh *base_mesh = BKE_mesh_from_object(ob);
|
||||
|
@ -2217,7 +2217,6 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg)
|
|||
|
||||
BKE_pbvh_build_grids(pbvh,
|
||||
subdiv_ccg->grids,
|
||||
subdiv_ccg->num_grids,
|
||||
&key,
|
||||
subdiv_ccg->grid_to_face_map,
|
||||
subdiv_ccg->grid_flag_mats,
|
||||
|
@ -2304,7 +2303,7 @@ bool BKE_object_sculpt_use_dyntopo(const Object *object)
|
|||
void BKE_sculpt_bvh_update_from_ccg(PBVH *pbvh, SubdivCCG *subdiv_ccg)
|
||||
{
|
||||
CCGKey key;
|
||||
BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
|
||||
BKE_subdiv_ccg_key_top_level(key, *subdiv_ccg);
|
||||
|
||||
BKE_pbvh_grids_update(pbvh,
|
||||
subdiv_ccg->grids,
|
||||
|
|
|
@ -236,10 +236,10 @@ static int partition_indices_grids(blender::MutableSpan<int> prim_indices,
|
|||
int i1 = lo, i2 = 0;
|
||||
|
||||
while (i1 < hi) {
|
||||
int face_i = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, prim_scratch[i2]);
|
||||
int face_i = BKE_subdiv_ccg_grid_to_face_index(*subdiv_ccg, prim_scratch[i2]);
|
||||
bool side = prim_bbc[prim_scratch[i2]].bcentroid[axis] >= mid;
|
||||
|
||||
while (i1 < hi && BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, prim_scratch[i2]) == face_i) {
|
||||
while (i1 < hi && BKE_subdiv_ccg_grid_to_face_index(*subdiv_ccg, prim_scratch[i2]) == face_i) {
|
||||
prim_indices[side ? hi2-- : lo2++] = prim_scratch[i2];
|
||||
i1++;
|
||||
i2++;
|
||||
|
@ -254,7 +254,7 @@ static int partition_indices_material(
|
|||
PBVH *pbvh, const int *material_indices, const bool *sharp_faces, int lo, int hi)
|
||||
{
|
||||
const Span<int> looptri_faces = pbvh->looptri_faces;
|
||||
const DMFlagMat *flagmats = pbvh->grid_flag_mats;
|
||||
const Span<DMFlagMat> flagmats = pbvh->grid_flag_mats;
|
||||
MutableSpan<int> indices = pbvh->prim_indices;
|
||||
int i = lo, j = hi;
|
||||
|
||||
|
@ -374,7 +374,7 @@ static void update_vb(PBVH *pbvh, PBVHNode *node, const Span<BBC> prim_bbc, int
|
|||
node->orig_vb = node->vb;
|
||||
}
|
||||
|
||||
int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
|
||||
int BKE_pbvh_count_grid_quads(const Span<const BLI_bitmap *> grid_hidden,
|
||||
const int *grid_indices,
|
||||
int totgrid,
|
||||
int gridsize,
|
||||
|
@ -661,7 +661,6 @@ static void pbvh_draw_args_init(const Mesh &mesh, PBVH *pbvh, PBVH_GPU_Args *arg
|
|||
memset((void *)args, 0, sizeof(*args));
|
||||
|
||||
args->pbvh_type = pbvh->header.type;
|
||||
args->mesh_grids_num = pbvh->totgrid;
|
||||
args->node = node;
|
||||
|
||||
args->grid_hidden = pbvh->grid_hidden;
|
||||
|
@ -707,7 +706,6 @@ static void pbvh_draw_args_init(const Mesh &mesh, PBVH *pbvh, PBVH_GPU_Args *arg
|
|||
args->subdiv_ccg = pbvh->subdiv_ccg;
|
||||
args->faces = pbvh->faces;
|
||||
|
||||
args->mesh_grids_num = pbvh->totgrid;
|
||||
args->grids = pbvh->grids;
|
||||
args->grid_flag_mats = pbvh->grid_flag_mats;
|
||||
args->vert_normals = pbvh->vert_normals;
|
||||
|
@ -900,12 +898,11 @@ void BKE_pbvh_build_mesh(PBVH *pbvh, Mesh *mesh)
|
|||
}
|
||||
|
||||
void BKE_pbvh_build_grids(PBVH *pbvh,
|
||||
CCGElem **grids,
|
||||
int totgrid,
|
||||
const Span<CCGElem *> grids,
|
||||
CCGKey *key,
|
||||
blender::Span<int> grid_to_face_map,
|
||||
DMFlagMat *flagmats,
|
||||
BLI_bitmap **grid_hidden,
|
||||
const Span<int> grid_to_face_map,
|
||||
const Span<DMFlagMat> flagmats,
|
||||
const Span<BLI_bitmap *> grid_hidden,
|
||||
Mesh *me,
|
||||
SubdivCCG *subdiv_ccg)
|
||||
{
|
||||
|
@ -915,7 +912,6 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
|
|||
pbvh->grids = grids;
|
||||
pbvh->grid_to_face_map = grid_to_face_map;
|
||||
pbvh->grid_flag_mats = flagmats;
|
||||
pbvh->totgrid = totgrid;
|
||||
pbvh->gridkey = *key;
|
||||
pbvh->grid_hidden = grid_hidden;
|
||||
pbvh->subdiv_ccg = subdiv_ccg;
|
||||
|
@ -946,11 +942,11 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
|
|||
pbvh->mesh = me;
|
||||
|
||||
/* For each grid, store the AABB and the AABB centroid */
|
||||
blender::Array<BBC> prim_bbc(totgrid);
|
||||
blender::Array<BBC> prim_bbc(grids.size());
|
||||
BB cb;
|
||||
BB_reset(&cb);
|
||||
cb = blender::threading::parallel_reduce(
|
||||
blender::IndexRange(totgrid),
|
||||
grids.index_range(),
|
||||
1024,
|
||||
cb,
|
||||
[&](const blender::IndexRange range, const BB &init) {
|
||||
|
@ -973,12 +969,12 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
|
|||
return current;
|
||||
});
|
||||
|
||||
if (totgrid) {
|
||||
if (!grids.is_empty()) {
|
||||
const int *material_indices = static_cast<const int *>(
|
||||
CustomData_get_layer_named(&me->face_data, CD_PROP_INT32, "material_index"));
|
||||
const bool *sharp_faces = (const bool *)CustomData_get_layer_named(
|
||||
&me->face_data, CD_PROP_BOOL, "sharp_face");
|
||||
pbvh_build(pbvh, material_indices, sharp_faces, &cb, prim_bbc, totgrid);
|
||||
pbvh_build(pbvh, material_indices, sharp_faces, &cb, prim_bbc, grids.size());
|
||||
|
||||
#ifdef TEST_PBVH_FACE_SPLIT
|
||||
test_face_boundaries(pbvh);
|
||||
|
@ -1602,18 +1598,17 @@ static void pbvh_faces_node_visibility_update(PBVH *pbvh, PBVHNode *node)
|
|||
|
||||
static void pbvh_grids_node_visibility_update(PBVH *pbvh, PBVHNode *node)
|
||||
{
|
||||
CCGElem **grids;
|
||||
BLI_bitmap **grid_hidden;
|
||||
CCGElem *const *grids;
|
||||
const int *grid_indices;
|
||||
int totgrid, i;
|
||||
|
||||
BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, nullptr, nullptr, &grids);
|
||||
grid_hidden = BKE_pbvh_grid_hidden(pbvh);
|
||||
const Span<const BLI_bitmap *> grid_hidden = BKE_pbvh_get_grid_visibility(pbvh);
|
||||
CCGKey key = *BKE_pbvh_get_grid_key(pbvh);
|
||||
|
||||
for (i = 0; i < totgrid; i++) {
|
||||
int g = grid_indices[i], x, y;
|
||||
BLI_bitmap *gh = grid_hidden[g];
|
||||
const BLI_bitmap *gh = grid_hidden[g];
|
||||
|
||||
if (!gh) {
|
||||
BKE_pbvh_node_fully_hidden_set(node, false);
|
||||
|
@ -1712,53 +1707,24 @@ void BKE_pbvh_redraw_BB(PBVH *pbvh, float bb_min[3], float bb_max[3])
|
|||
copy_v3_v3(bb_max, bb.bmax);
|
||||
}
|
||||
|
||||
void BKE_pbvh_get_grid_updates(PBVH *pbvh, bool clear, void ***r_gridfaces, int *r_totface)
|
||||
blender::IndexMask BKE_pbvh_get_grid_updates(const PBVH *pbvh,
|
||||
const Span<const PBVHNode *> nodes,
|
||||
blender::IndexMaskMemory &memory)
|
||||
{
|
||||
if (pbvh->nodes.is_empty()) {
|
||||
return;
|
||||
}
|
||||
GSet *face_set = BLI_gset_ptr_new(__func__);
|
||||
PBVHNode *node;
|
||||
PBVHIter iter;
|
||||
|
||||
pbvh_iter_begin(&iter, pbvh, {});
|
||||
|
||||
SubdivCCGFace *all_faces = pbvh->subdiv_ccg->faces;
|
||||
while ((node = pbvh_iter_next(&iter, PBVH_Leaf))) {
|
||||
if (node->flag & PBVH_UpdateNormals) {
|
||||
using namespace blender;
|
||||
/* Using a #VectorSet for index deduplication would also work, but the performance gets much
|
||||
* worse with large selections since the loop would be single-threaded. A boolean array has an
|
||||
* overhead regardless of selection size, but that is small. */
|
||||
Array<bool> faces_to_update(pbvh->faces_num, false);
|
||||
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
|
||||
for (const PBVHNode *node : nodes.slice(range)) {
|
||||
for (const int grid : node->prim_indices) {
|
||||
void *face = &all_faces[pbvh->grid_to_face_map[grid]];
|
||||
BLI_gset_add(face_set, face);
|
||||
}
|
||||
|
||||
if (clear) {
|
||||
node->flag &= ~PBVH_UpdateNormals;
|
||||
const int face = pbvh->grid_to_face_map[grid];
|
||||
faces_to_update[face] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pbvh_iter_end(&iter);
|
||||
|
||||
const int tot = BLI_gset_len(face_set);
|
||||
if (tot == 0) {
|
||||
*r_totface = 0;
|
||||
*r_gridfaces = nullptr;
|
||||
BLI_gset_free(face_set, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
void **faces = static_cast<void **>(MEM_mallocN(sizeof(*faces) * tot, __func__));
|
||||
|
||||
GSetIterator gs_iter;
|
||||
int i;
|
||||
GSET_ITER_INDEX (gs_iter, face_set, i) {
|
||||
faces[i] = BLI_gsetIterator_getKey(&gs_iter);
|
||||
}
|
||||
|
||||
BLI_gset_free(face_set, nullptr);
|
||||
|
||||
*r_totface = tot;
|
||||
*r_gridfaces = faces;
|
||||
});
|
||||
return IndexMask::from_bools(faces_to_update, memory);
|
||||
}
|
||||
|
||||
/***************************** PBVH Access ***********************************/
|
||||
|
@ -1784,7 +1750,7 @@ void BKE_pbvh_bounding_box(const PBVH *pbvh, float min[3], float max[3])
|
|||
copy_v3_v3(max, bb->bmax);
|
||||
}
|
||||
|
||||
BLI_bitmap **BKE_pbvh_grid_hidden(const PBVH *pbvh)
|
||||
Span<const BLI_bitmap *> BKE_pbvh_get_grid_visibility(const PBVH *pbvh)
|
||||
{
|
||||
BLI_assert(pbvh->header.type == PBVH_GRIDS);
|
||||
return pbvh->grid_hidden;
|
||||
|
@ -1796,28 +1762,22 @@ const CCGKey *BKE_pbvh_get_grid_key(const PBVH *pbvh)
|
|||
return &pbvh->gridkey;
|
||||
}
|
||||
|
||||
CCGElem **BKE_pbvh_get_grids(const PBVH *pbvh)
|
||||
Span<CCGElem *> BKE_pbvh_get_grids(const PBVH *pbvh)
|
||||
{
|
||||
BLI_assert(pbvh->header.type == PBVH_GRIDS);
|
||||
return pbvh->grids;
|
||||
}
|
||||
|
||||
BLI_bitmap **BKE_pbvh_get_grid_visibility(const PBVH *pbvh)
|
||||
{
|
||||
BLI_assert(pbvh->header.type == PBVH_GRIDS);
|
||||
return pbvh->grid_hidden;
|
||||
}
|
||||
|
||||
int BKE_pbvh_get_grid_num_verts(const PBVH *pbvh)
|
||||
{
|
||||
BLI_assert(pbvh->header.type == PBVH_GRIDS);
|
||||
return pbvh->totgrid * pbvh->gridkey.grid_area;
|
||||
return pbvh->grids.size() * pbvh->gridkey.grid_area;
|
||||
}
|
||||
|
||||
int BKE_pbvh_get_grid_num_faces(const PBVH *pbvh)
|
||||
{
|
||||
BLI_assert(pbvh->header.type == PBVH_GRIDS);
|
||||
return pbvh->totgrid * (pbvh->gridkey.grid_size - 1) * (pbvh->gridkey.grid_size - 1);
|
||||
return pbvh->grids.size() * (pbvh->gridkey.grid_size - 1) * (pbvh->gridkey.grid_size - 1);
|
||||
}
|
||||
|
||||
/***************************** Node Access ***********************************/
|
||||
|
@ -1990,7 +1950,7 @@ blender::Vector<int> BKE_pbvh_node_calc_face_indices(const PBVH &pbvh, const PBV
|
|||
const SubdivCCG &subdiv_ccg = *pbvh.subdiv_ccg;
|
||||
int prev_face = -1;
|
||||
for (const int prim : node.prim_indices) {
|
||||
const int face = BKE_subdiv_ccg_grid_to_face_index(&subdiv_ccg, prim);
|
||||
const int face = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, prim);
|
||||
if (face != prev_face) {
|
||||
faces.append(face);
|
||||
prev_face = face;
|
||||
|
@ -2063,7 +2023,7 @@ void BKE_pbvh_node_get_grids(PBVH *pbvh,
|
|||
int *r_totgrid,
|
||||
int *r_maxgrid,
|
||||
int *r_gridsize,
|
||||
CCGElem ***r_griddata)
|
||||
CCGElem *const **r_griddata)
|
||||
{
|
||||
switch (pbvh->header.type) {
|
||||
case PBVH_GRIDS:
|
||||
|
@ -2074,13 +2034,13 @@ void BKE_pbvh_node_get_grids(PBVH *pbvh,
|
|||
*r_totgrid = node->prim_indices.size();
|
||||
}
|
||||
if (r_maxgrid) {
|
||||
*r_maxgrid = pbvh->totgrid;
|
||||
*r_maxgrid = pbvh->grids.size();
|
||||
}
|
||||
if (r_gridsize) {
|
||||
*r_gridsize = pbvh->gridkey.grid_size;
|
||||
}
|
||||
if (r_griddata) {
|
||||
*r_griddata = pbvh->grids;
|
||||
*r_griddata = pbvh->grids.data();
|
||||
}
|
||||
break;
|
||||
case PBVH_FACES:
|
||||
|
@ -2861,6 +2821,7 @@ bool BKE_pbvh_node_frustum_exclude_AABB(PBVHNode *node, PBVHFrustumPlanes *data)
|
|||
|
||||
void BKE_pbvh_update_normals(PBVH *pbvh, SubdivCCG *subdiv_ccg)
|
||||
{
|
||||
using namespace blender;
|
||||
/* Update normals */
|
||||
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(
|
||||
pbvh, [&](PBVHNode &node) { return update_search(&node, PBVH_UpdateNormals); });
|
||||
|
@ -2872,12 +2833,11 @@ void BKE_pbvh_update_normals(PBVH *pbvh, SubdivCCG *subdiv_ccg)
|
|||
pbvh_faces_update_normals(pbvh, nodes, *pbvh->mesh);
|
||||
}
|
||||
else if (pbvh->header.type == PBVH_GRIDS) {
|
||||
CCGFace **faces;
|
||||
int num_faces;
|
||||
BKE_pbvh_get_grid_updates(pbvh, true, (void ***)&faces, &num_faces);
|
||||
if (num_faces > 0) {
|
||||
BKE_subdiv_ccg_update_normals(subdiv_ccg, faces, num_faces);
|
||||
MEM_freeN(faces);
|
||||
IndexMaskMemory memory;
|
||||
const IndexMask faces_to_update = BKE_pbvh_get_grid_updates(pbvh, nodes, memory);
|
||||
BKE_subdiv_ccg_update_normals(*subdiv_ccg, faces_to_update);
|
||||
for (PBVHNode *node : nodes) {
|
||||
node->flag &= ~PBVH_UpdateNormals;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2990,17 +2950,19 @@ void BKE_pbvh_draw_debug_cb(PBVH *pbvh,
|
|||
}
|
||||
|
||||
void BKE_pbvh_grids_update(PBVH *pbvh,
|
||||
CCGElem **grids,
|
||||
blender::Span<int> grid_to_face_map,
|
||||
DMFlagMat *flagmats,
|
||||
BLI_bitmap **grid_hidden,
|
||||
const blender::Span<CCGElem *> grids,
|
||||
const blender::Span<int> grid_to_face_map,
|
||||
const blender::Span<DMFlagMat> flagmats,
|
||||
const blender::Span<BLI_bitmap *> grid_hidden,
|
||||
CCGKey *key)
|
||||
{
|
||||
pbvh->gridkey = *key;
|
||||
pbvh->grids = grids;
|
||||
pbvh->grid_to_face_map = grid_to_face_map;
|
||||
|
||||
if (flagmats != pbvh->grid_flag_mats || pbvh->grid_hidden != grid_hidden) {
|
||||
if (flagmats.data() != pbvh->grid_flag_mats.data() ||
|
||||
pbvh->grid_hidden.data() != grid_hidden.data())
|
||||
{
|
||||
pbvh->grid_flag_mats = flagmats;
|
||||
pbvh->grid_hidden = grid_hidden;
|
||||
|
||||
|
@ -3105,7 +3067,7 @@ void BKE_pbvh_node_color_buffer_free(PBVH *pbvh)
|
|||
|
||||
void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int mode)
|
||||
{
|
||||
CCGElem **grids;
|
||||
CCGElem *const *grids;
|
||||
const int *grid_indices;
|
||||
int totgrid, gridsize, uniq_verts, totvert;
|
||||
|
||||
|
@ -3146,7 +3108,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
|
|||
|
||||
vi->gh = nullptr;
|
||||
if (vi->grids && mode == PBVH_ITER_UNIQUE) {
|
||||
vi->grid_hidden = pbvh->grid_hidden;
|
||||
vi->grid_hidden = pbvh->grid_hidden.data();
|
||||
}
|
||||
|
||||
vi->mask = 0.0f;
|
||||
|
|
|
@ -178,11 +178,10 @@ struct PBVH {
|
|||
|
||||
/* Grid Data */
|
||||
CCGKey gridkey;
|
||||
CCGElem **grids;
|
||||
blender::Span<CCGElem *> grids;
|
||||
blender::Span<int> grid_to_face_map;
|
||||
const DMFlagMat *grid_flag_mats;
|
||||
int totgrid;
|
||||
BLI_bitmap **grid_hidden;
|
||||
blender::Span<DMFlagMat> grid_flag_mats;
|
||||
blender::Span<BLI_bitmap *> grid_hidden;
|
||||
|
||||
/* Used during BVH build and later to mark that a vertex needs to update
|
||||
* (its normal must be recalculated). */
|
||||
|
|
|
@ -1876,7 +1876,7 @@ static int ptcache_old_elemsize(PTCacheID *pid)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ptcache_find_frames_around(PTCacheID *pid, uint frame, int *fra1, int *fra2)
|
||||
static void ptcache_find_frames_around(PTCacheID *pid, uint frame, int *r_fra1, int *r_fra2)
|
||||
{
|
||||
if (pid->cache->flag & PTCACHE_DISK_CACHE) {
|
||||
int cfra1 = frame, cfra2 = frame + 1;
|
||||
|
@ -1898,12 +1898,12 @@ static void ptcache_find_frames_around(PTCacheID *pid, uint frame, int *fra1, in
|
|||
}
|
||||
|
||||
if (cfra1 && !cfra2) {
|
||||
*fra1 = 0;
|
||||
*fra2 = cfra1;
|
||||
*r_fra1 = 0;
|
||||
*r_fra2 = cfra1;
|
||||
}
|
||||
else {
|
||||
*fra1 = cfra1;
|
||||
*fra2 = cfra2;
|
||||
*r_fra1 = cfra1;
|
||||
*r_fra2 = cfra2;
|
||||
}
|
||||
}
|
||||
else if (pid->cache->mem_cache.first) {
|
||||
|
@ -1924,12 +1924,12 @@ static void ptcache_find_frames_around(PTCacheID *pid, uint frame, int *fra1, in
|
|||
}
|
||||
|
||||
if (!pm2) {
|
||||
*fra1 = 0;
|
||||
*fra2 = pm->frame;
|
||||
*r_fra1 = 0;
|
||||
*r_fra2 = pm->frame;
|
||||
}
|
||||
else {
|
||||
*fra1 = pm->frame;
|
||||
*fra2 = pm2->frame;
|
||||
*r_fra1 = pm->frame;
|
||||
*r_fra2 = pm2->frame;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -674,14 +674,14 @@ void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
|
|||
|
||||
const blender::Span<blender::float3> positions = mesh->vert_positions();
|
||||
const blender::Span<MLoopTri> looptris = mesh->looptris();
|
||||
const int *corner_verts = BKE_mesh_corner_verts(mesh);
|
||||
const blender::Span<int> corner_verts = mesh->corner_verts();
|
||||
|
||||
if (!positions.is_empty() && !looptris.is_empty()) {
|
||||
BKE_mesh_calc_volume(reinterpret_cast<const float(*)[3]>(positions.data()),
|
||||
positions.size(),
|
||||
looptris.data(),
|
||||
looptris.size(),
|
||||
corner_verts,
|
||||
corner_verts.data(),
|
||||
&volume,
|
||||
nullptr);
|
||||
const float volume_scale = mat4_to_volume_scale(ob->object_to_world);
|
||||
|
|
|
@ -88,7 +88,7 @@
|
|||
#include "BKE_scene.h"
|
||||
#include "BKE_screen.hh"
|
||||
#include "BKE_sound.h"
|
||||
#include "BKE_unit.h"
|
||||
#include "BKE_unit.hh"
|
||||
#include "BKE_workspace.h"
|
||||
#include "BKE_world.h"
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include "BKE_lattice.hh"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_modifier.hh"
|
||||
#include "BKE_shrinkwrap.h"
|
||||
#include "BKE_shrinkwrap.hh"
|
||||
|
||||
#include "BKE_deform.h"
|
||||
#include "BKE_editmesh.hh"
|
||||
|
@ -102,7 +102,7 @@ bool BKE_shrinkwrap_needs_normals(int shrinkType, int shrinkMode)
|
|||
bool BKE_shrinkwrap_init_tree(
|
||||
ShrinkwrapTreeData *data, Mesh *mesh, int shrinkType, int shrinkMode, bool force_normals)
|
||||
{
|
||||
memset(data, 0, sizeof(*data));
|
||||
*data = {};
|
||||
|
||||
if (mesh == nullptr) {
|
||||
return false;
|
||||
|
@ -118,11 +118,11 @@ bool BKE_shrinkwrap_init_tree(
|
|||
}
|
||||
|
||||
data->mesh = mesh;
|
||||
data->face_offsets = mesh->face_offsets().data();
|
||||
data->corner_edges = mesh->corner_edges().data();
|
||||
data->vert_normals = reinterpret_cast<const float(*)[3]>(mesh->vert_normals().data());
|
||||
data->faces = mesh->faces();
|
||||
data->corner_edges = mesh->corner_edges();
|
||||
data->vert_normals = mesh->vert_normals();
|
||||
data->sharp_faces = static_cast<const bool *>(
|
||||
CustomData_get_layer_named(&mesh->edge_data, CD_PROP_BOOL, "sharp_face"));
|
||||
CustomData_get_layer_named(&mesh->face_data, 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);
|
||||
|
@ -141,9 +141,9 @@ bool BKE_shrinkwrap_init_tree(
|
|||
}
|
||||
|
||||
if (force_normals || BKE_shrinkwrap_needs_normals(shrinkType, shrinkMode)) {
|
||||
data->face_normals = reinterpret_cast<const float(*)[3]>(mesh->face_normals().data());
|
||||
data->face_normals = mesh->face_normals();
|
||||
if (mesh->normals_domain() == blender::bke::MeshNormalDomain::Corner) {
|
||||
data->clnors = reinterpret_cast<const float(*)[3]>(mesh->corner_normals().data());
|
||||
data->corner_normals = mesh->corner_normals();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,9 +246,8 @@ static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh)
|
|||
"ShrinkwrapBoundaryData::looptri_is_boundary");
|
||||
|
||||
for (const int64_t i : looptris.index_range()) {
|
||||
int real_edges[3];
|
||||
BKE_mesh_looptri_get_real_edges(
|
||||
edges.data(), corner_verts.data(), corner_edges.data(), &looptris[i], real_edges);
|
||||
const int3 real_edges = bke::mesh::looptri_get_real_edges(
|
||||
edges, corner_verts, corner_edges, looptris[i]);
|
||||
|
||||
for (int j = 0; j < 3; j++) {
|
||||
if (real_edges[j] >= 0 && edge_mode[real_edges[j]]) {
|
||||
|
@ -947,7 +946,7 @@ static void target_project_edge(const ShrinkwrapTreeData *tree,
|
|||
int eidx)
|
||||
{
|
||||
const BVHTreeFromMesh *data = &tree->treeData;
|
||||
const blender::int2 &edge = reinterpret_cast<const blender::int2 *>(data->edge)[eidx];
|
||||
const blender::int2 &edge = data->edges[eidx];
|
||||
const float *vedge_co[2] = {data->vert_positions[edge[0]], data->vert_positions[edge[1]]};
|
||||
|
||||
#ifdef TRACE_TARGET_PROJECT
|
||||
|
@ -1021,9 +1020,10 @@ static void mesh_looptri_target_project(void *userdata,
|
|||
const float co[3],
|
||||
BVHTreeNearest *nearest)
|
||||
{
|
||||
using namespace blender;
|
||||
const ShrinkwrapTreeData *tree = (ShrinkwrapTreeData *)userdata;
|
||||
const BVHTreeFromMesh *data = &tree->treeData;
|
||||
const MLoopTri *lt = &data->looptri[index];
|
||||
const MLoopTri *lt = &data->looptris[index];
|
||||
const int tri_verts[3] = {data->corner_verts[lt->tri[0]],
|
||||
data->corner_verts[lt->tri[1]],
|
||||
data->corner_verts[lt->tri[2]]};
|
||||
|
@ -1062,13 +1062,8 @@ static void mesh_looptri_target_project(void *userdata,
|
|||
/* Boundary edges */
|
||||
else if (tree->boundary && BLI_BITMAP_TEST(tree->boundary->looptri_has_boundary, index)) {
|
||||
const BLI_bitmap *is_boundary = tree->boundary->edge_is_boundary;
|
||||
int edges[3];
|
||||
|
||||
BKE_mesh_looptri_get_real_edges(reinterpret_cast<const blender::int2 *>(data->edge),
|
||||
data->corner_verts,
|
||||
tree->corner_edges,
|
||||
lt,
|
||||
edges);
|
||||
const int3 edges = bke::mesh::looptri_get_real_edges(
|
||||
data->edges, data->corner_verts, tree->corner_edges, *lt);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (edges[i] >= 0 && BLI_BITMAP_TEST(is_boundary, edges[i])) {
|
||||
|
@ -1190,8 +1185,7 @@ void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree,
|
|||
float r_no[3])
|
||||
{
|
||||
const BVHTreeFromMesh *treeData = &tree->treeData;
|
||||
const MLoopTri *tri = &treeData->looptri[looptri_idx];
|
||||
const float(*vert_normals)[3] = tree->vert_normals;
|
||||
const MLoopTri *tri = &treeData->looptris[looptri_idx];
|
||||
const int face_i = tree->mesh->looptri_faces()[looptri_idx];
|
||||
|
||||
/* Interpolate smooth normals if enabled. */
|
||||
|
@ -1202,16 +1196,16 @@ void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree,
|
|||
float w[3], no[3][3], tmp_co[3];
|
||||
|
||||
/* Custom and auto smooth split normals. */
|
||||
if (tree->clnors) {
|
||||
copy_v3_v3(no[0], tree->clnors[tri->tri[0]]);
|
||||
copy_v3_v3(no[1], tree->clnors[tri->tri[1]]);
|
||||
copy_v3_v3(no[2], tree->clnors[tri->tri[2]]);
|
||||
if (!tree->corner_normals.is_empty()) {
|
||||
copy_v3_v3(no[0], tree->corner_normals[tri->tri[0]]);
|
||||
copy_v3_v3(no[1], tree->corner_normals[tri->tri[1]]);
|
||||
copy_v3_v3(no[2], tree->corner_normals[tri->tri[2]]);
|
||||
}
|
||||
/* Ordinary vertex normals. */
|
||||
else {
|
||||
copy_v3_v3(no[0], vert_normals[vert_indices[0]]);
|
||||
copy_v3_v3(no[1], vert_normals[vert_indices[1]]);
|
||||
copy_v3_v3(no[2], vert_normals[vert_indices[2]]);
|
||||
copy_v3_v3(no[0], tree->vert_normals[vert_indices[0]]);
|
||||
copy_v3_v3(no[1], tree->vert_normals[vert_indices[1]]);
|
||||
copy_v3_v3(no[2], tree->vert_normals[vert_indices[2]]);
|
||||
}
|
||||
|
||||
/* Barycentric weights from hit point. */
|
||||
|
@ -1238,7 +1232,7 @@ void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree,
|
|||
}
|
||||
}
|
||||
/* Use the face normal if flat. */
|
||||
else if (tree->face_normals != nullptr) {
|
||||
else if (!tree->face_normals.is_empty()) {
|
||||
copy_v3_v3(r_no, tree->face_normals[face_i]);
|
||||
}
|
||||
/* Finally fallback to the looptri normal. */
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
#include "BKE_effect.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_layer.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_mesh.hh"
|
||||
#include "BKE_modifier.hh"
|
||||
#include "BKE_pointcache.h"
|
||||
#include "BKE_scene.h"
|
||||
|
@ -571,13 +571,10 @@ static void ccd_update_deflector_hash(Depsgraph *depsgraph,
|
|||
static int count_mesh_quads(Mesh *me)
|
||||
{
|
||||
int result = 0;
|
||||
const int *face_offsets = BKE_mesh_face_offsets(me);
|
||||
if (face_offsets) {
|
||||
for (int i = 0; i < me->faces_num; i++) {
|
||||
const int poly_size = face_offsets[i + 1] - face_offsets[i];
|
||||
if (poly_size == 4) {
|
||||
result++;
|
||||
}
|
||||
const blender::OffsetIndices faces = me->faces();
|
||||
for (const int i : faces.index_range()) {
|
||||
if (faces[i].size() == 4) {
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -593,8 +590,8 @@ static void add_mesh_quad_diag_springs(Object *ob)
|
|||
|
||||
nofquads = count_mesh_quads(me);
|
||||
if (nofquads) {
|
||||
const int *corner_verts = BKE_mesh_corner_verts(me);
|
||||
const int *face_offsets = BKE_mesh_face_offsets(me);
|
||||
const blender::OffsetIndices faces = me->faces();
|
||||
const blender::Span<int> corner_verts = me->corner_verts();
|
||||
BodySpring *bs;
|
||||
|
||||
/* resize spring-array to hold additional quad springs */
|
||||
|
@ -605,14 +602,14 @@ static void add_mesh_quad_diag_springs(Object *ob)
|
|||
bs = &ob->soft->bspring[ob->soft->totspring];
|
||||
// bp = ob->soft->bpoint; /* UNUSED */
|
||||
for (int a = 0; a < me->faces_num; a++) {
|
||||
const int poly_size = face_offsets[a + 1] - face_offsets[a];
|
||||
const int poly_size = faces[a].size();
|
||||
if (poly_size == 4) {
|
||||
bs->v1 = corner_verts[face_offsets[a] + 0];
|
||||
bs->v2 = corner_verts[face_offsets[a] + 2];
|
||||
bs->v1 = corner_verts[faces[a].start() + 0];
|
||||
bs->v2 = corner_verts[faces[a].start() + 2];
|
||||
bs->springtype = SB_STIFFQUAD;
|
||||
bs++;
|
||||
bs->v1 = corner_verts[face_offsets[a] + 1];
|
||||
bs->v2 = corner_verts[face_offsets[a] + 3];
|
||||
bs->v1 = corner_verts[faces[a].start() + 1];
|
||||
bs->v2 = corner_verts[faces[a].start() + 3];
|
||||
bs->springtype = SB_STIFFQUAD;
|
||||
bs++;
|
||||
}
|
||||
|
@ -2651,7 +2648,7 @@ static void springs_from_mesh(Object *ob)
|
|||
BodyPoint *bp;
|
||||
int a;
|
||||
float scale = 1.0f;
|
||||
const float(*vert_positions)[3] = BKE_mesh_vert_positions(me);
|
||||
const blender::Span<blender::float3> positions = me->vert_positions();
|
||||
|
||||
sb = ob->soft;
|
||||
if (me && sb) {
|
||||
|
@ -2662,7 +2659,7 @@ static void springs_from_mesh(Object *ob)
|
|||
if (me->totvert) {
|
||||
bp = ob->soft->bpoint;
|
||||
for (a = 0; a < me->totvert; a++, bp++) {
|
||||
copy_v3_v3(bp->origS, vert_positions[a]);
|
||||
copy_v3_v3(bp->origS, positions[a]);
|
||||
mul_m4_v3(ob->object_to_world, bp->origS);
|
||||
}
|
||||
}
|
||||
|
@ -2772,25 +2769,19 @@ static void mesh_faces_to_scratch(Object *ob)
|
|||
{
|
||||
SoftBody *sb = ob->soft;
|
||||
const Mesh *me = static_cast<const Mesh *>(ob->data);
|
||||
MLoopTri *looptri, *lt;
|
||||
MLoopTri *lt;
|
||||
BodyFace *bodyface;
|
||||
int a;
|
||||
const float(*vert_positions)[3] = BKE_mesh_vert_positions(me);
|
||||
const int *face_offsets = BKE_mesh_face_offsets(me);
|
||||
const int *corner_verts = BKE_mesh_corner_verts(me);
|
||||
const blender::Span<int> corner_verts = me->corner_verts();
|
||||
|
||||
/* Allocate and copy faces. */
|
||||
|
||||
sb->scratch->totface = poly_to_tri_count(me->faces_num, me->totloop);
|
||||
looptri = lt = static_cast<MLoopTri *>(
|
||||
MEM_mallocN(sizeof(*looptri) * sb->scratch->totface, __func__));
|
||||
BKE_mesh_recalc_looptri(corner_verts,
|
||||
face_offsets,
|
||||
vert_positions,
|
||||
me->totvert,
|
||||
me->totloop,
|
||||
me->faces_num,
|
||||
looptri);
|
||||
blender::Array<MLoopTri> looptri(me->totvert);
|
||||
blender::bke::mesh::looptris_calc(
|
||||
me->vert_positions(), me->faces(), me->corner_verts(), looptri);
|
||||
|
||||
lt = looptri.data();
|
||||
|
||||
bodyface = sb->scratch->bodyface = static_cast<BodyFace *>(
|
||||
MEM_mallocN(sizeof(BodyFace) * sb->scratch->totface, "SB_body_Faces"));
|
||||
|
@ -2803,8 +2794,6 @@ static void mesh_faces_to_scratch(Object *ob)
|
|||
bodyface->ext_force[0] = bodyface->ext_force[1] = bodyface->ext_force[2] = 0.0f;
|
||||
bodyface->flag = 0;
|
||||
}
|
||||
|
||||
MEM_freeN(looptri);
|
||||
}
|
||||
static void reference_to_scratch(Object *ob)
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,7 +20,7 @@
|
|||
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BKE_unit.h" /* own include */
|
||||
#include "BKE_unit.hh" /* own include */
|
||||
|
||||
#ifdef WIN32
|
||||
# include "BLI_winstuff.h"
|
||||
|
|
|
@ -44,8 +44,8 @@
|
|||
#include "BKE_main.h"
|
||||
#include "BKE_object_types.hh"
|
||||
#include "BKE_packedFile.h"
|
||||
#include "BKE_vfont.h"
|
||||
#include "BKE_vfontdata.h"
|
||||
#include "BKE_vfont.hh"
|
||||
#include "BKE_vfontdata.hh"
|
||||
|
||||
#include "BLO_read_write.hh"
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
#include "BLI_string_utf8.h"
|
||||
|
||||
#include "BKE_curve.hh"
|
||||
#include "BKE_vfont.h"
|
||||
#include "BKE_vfontdata.h"
|
||||
#include "BKE_vfont.hh"
|
||||
#include "BKE_vfontdata.hh"
|
||||
|
||||
#include "DNA_packedFile_types.h"
|
||||
#include "DNA_vfont_types.h"
|
||||
|
|
|
@ -92,7 +92,7 @@ static void context_free_avi(void *context_v);
|
|||
#endif /* WITH_AVI */
|
||||
|
||||
#ifdef WITH_FFMPEG
|
||||
# include "BKE_writeffmpeg.h"
|
||||
# include "BKE_writeffmpeg.hh"
|
||||
#endif
|
||||
|
||||
bMovieHandle *BKE_movie_handle_get(const char imtype)
|
||||
|
|
|
@ -36,12 +36,13 @@
|
|||
# include "BKE_main.h"
|
||||
# include "BKE_report.h"
|
||||
# include "BKE_sound.h"
|
||||
# include "BKE_writeffmpeg.h"
|
||||
# include "BKE_writeffmpeg.hh"
|
||||
|
||||
# include "IMB_imbuf.h"
|
||||
|
||||
/* This needs to be included after BLI_math_base.h otherwise it will redefine some math defines
|
||||
* like M_SQRT1_2 leading to warnings with MSVC */
|
||||
extern "C" {
|
||||
# include <libavcodec/avcodec.h>
|
||||
# include <libavformat/avformat.h>
|
||||
# include <libavutil/channel_layout.h>
|
||||
|
@ -52,13 +53,14 @@
|
|||
# include <libswscale/swscale.h>
|
||||
|
||||
# include "ffmpeg_compat.h"
|
||||
}
|
||||
|
||||
struct StampData;
|
||||
|
||||
typedef struct FFMpegContext {
|
||||
struct FFMpegContext {
|
||||
int ffmpeg_type;
|
||||
int ffmpeg_codec;
|
||||
int ffmpeg_audio_codec;
|
||||
AVCodecID ffmpeg_codec;
|
||||
AVCodecID ffmpeg_audio_codec;
|
||||
int ffmpeg_video_bitrate;
|
||||
int ffmpeg_audio_bitrate;
|
||||
int ffmpeg_gop_size;
|
||||
|
@ -80,7 +82,7 @@ typedef struct FFMpegContext {
|
|||
|
||||
/* Image frame in Blender's own pixel format, may need conversion to the output pixel format. */
|
||||
AVFrame *img_convert_frame;
|
||||
struct SwsContext *img_convert_ctx;
|
||||
SwsContext *img_convert_ctx;
|
||||
|
||||
uint8_t *audio_input_buffer;
|
||||
uint8_t *audio_deinterleave_buffer;
|
||||
|
@ -90,12 +92,12 @@ typedef struct FFMpegContext {
|
|||
bool audio_deinterleave;
|
||||
int audio_sample_size;
|
||||
|
||||
struct StampData *stamp_data;
|
||||
StampData *stamp_data;
|
||||
|
||||
# ifdef WITH_AUDASPACE
|
||||
AUD_Device *audio_mixdown_device;
|
||||
# endif
|
||||
} FFMpegContext;
|
||||
};
|
||||
|
||||
# define FFMPEG_AUTOSPLIT_SIZE 2000000000
|
||||
|
||||
|
@ -133,7 +135,7 @@ static int request_float_audio_buffer(int codec_id)
|
|||
|
||||
static int write_audio_frame(FFMpegContext *context)
|
||||
{
|
||||
AVFrame *frame = NULL;
|
||||
AVFrame *frame = nullptr;
|
||||
AVCodecContext *c = context->audio_codec;
|
||||
|
||||
AUD_Device_read(
|
||||
|
@ -181,10 +183,12 @@ static int write_audio_frame(FFMpegContext *context)
|
|||
|
||||
int success = 1;
|
||||
|
||||
char error_str[AV_ERROR_MAX_STRING_SIZE];
|
||||
int ret = avcodec_send_frame(c, frame);
|
||||
if (ret < 0) {
|
||||
/* Can't send frame to encoder. This shouldn't happen. */
|
||||
fprintf(stderr, "Can't send audio frame: %s\n", av_err2str(ret));
|
||||
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
|
||||
fprintf(stderr, "Can't send audio frame: %s\n", error_str);
|
||||
success = -1;
|
||||
}
|
||||
|
||||
|
@ -197,7 +201,8 @@ static int write_audio_frame(FFMpegContext *context)
|
|||
break;
|
||||
}
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret));
|
||||
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
|
||||
fprintf(stderr, "Error encoding audio frame: %s\n", error_str);
|
||||
success = -1;
|
||||
}
|
||||
|
||||
|
@ -211,7 +216,8 @@ static int write_audio_frame(FFMpegContext *context)
|
|||
|
||||
int write_ret = av_interleaved_write_frame(context->outfile, pkt);
|
||||
if (write_ret != 0) {
|
||||
fprintf(stderr, "Error writing audio packet: %s\n", av_err2str(write_ret));
|
||||
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
|
||||
fprintf(stderr, "Error writing audio packet: %s\n", error_str);
|
||||
success = -1;
|
||||
break;
|
||||
}
|
||||
|
@ -225,7 +231,7 @@ static int write_audio_frame(FFMpegContext *context)
|
|||
# endif /* #ifdef WITH_AUDASPACE */
|
||||
|
||||
/* Allocate a temporary frame */
|
||||
static AVFrame *alloc_picture(int pix_fmt, int width, int height)
|
||||
static AVFrame *alloc_picture(AVPixelFormat pix_fmt, int width, int height)
|
||||
{
|
||||
AVFrame *f;
|
||||
uint8_t *buf;
|
||||
|
@ -234,14 +240,14 @@ static AVFrame *alloc_picture(int pix_fmt, int width, int height)
|
|||
/* allocate space for the struct */
|
||||
f = av_frame_alloc();
|
||||
if (!f) {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
size = av_image_get_buffer_size(pix_fmt, width, height, 1);
|
||||
/* allocate the actual picture buffer */
|
||||
buf = MEM_mallocN(size, "AVFrame buffer");
|
||||
buf = static_cast<uint8_t *>(MEM_mallocN(size, "AVFrame buffer"));
|
||||
if (!buf) {
|
||||
free(f);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
av_image_fill_arrays(f->data, f->linesize, buf, pix_fmt, width, height, 1);
|
||||
|
@ -258,62 +264,62 @@ static const char **get_file_extensions(int format)
|
|||
{
|
||||
switch (format) {
|
||||
case FFMPEG_DV: {
|
||||
static const char *rv[] = {".dv", NULL};
|
||||
static const char *rv[] = {".dv", nullptr};
|
||||
return rv;
|
||||
}
|
||||
case FFMPEG_MPEG1: {
|
||||
static const char *rv[] = {".mpg", ".mpeg", NULL};
|
||||
static const char *rv[] = {".mpg", ".mpeg", nullptr};
|
||||
return rv;
|
||||
}
|
||||
case FFMPEG_MPEG2: {
|
||||
static const char *rv[] = {".dvd", ".vob", ".mpg", ".mpeg", NULL};
|
||||
static const char *rv[] = {".dvd", ".vob", ".mpg", ".mpeg", nullptr};
|
||||
return rv;
|
||||
}
|
||||
case FFMPEG_MPEG4: {
|
||||
static const char *rv[] = {".mp4", ".mpg", ".mpeg", NULL};
|
||||
static const char *rv[] = {".mp4", ".mpg", ".mpeg", nullptr};
|
||||
return rv;
|
||||
}
|
||||
case FFMPEG_AVI: {
|
||||
static const char *rv[] = {".avi", NULL};
|
||||
static const char *rv[] = {".avi", nullptr};
|
||||
return rv;
|
||||
}
|
||||
case FFMPEG_MOV: {
|
||||
static const char *rv[] = {".mov", NULL};
|
||||
static const char *rv[] = {".mov", nullptr};
|
||||
return rv;
|
||||
}
|
||||
case FFMPEG_H264: {
|
||||
/* FIXME: avi for now... */
|
||||
static const char *rv[] = {".avi", NULL};
|
||||
static const char *rv[] = {".avi", nullptr};
|
||||
return rv;
|
||||
}
|
||||
|
||||
case FFMPEG_XVID: {
|
||||
/* FIXME: avi for now... */
|
||||
static const char *rv[] = {".avi", NULL};
|
||||
static const char *rv[] = {".avi", nullptr};
|
||||
return rv;
|
||||
}
|
||||
case FFMPEG_FLV: {
|
||||
static const char *rv[] = {".flv", NULL};
|
||||
static const char *rv[] = {".flv", nullptr};
|
||||
return rv;
|
||||
}
|
||||
case FFMPEG_MKV: {
|
||||
static const char *rv[] = {".mkv", NULL};
|
||||
static const char *rv[] = {".mkv", nullptr};
|
||||
return rv;
|
||||
}
|
||||
case FFMPEG_OGG: {
|
||||
static const char *rv[] = {".ogv", ".ogg", NULL};
|
||||
static const char *rv[] = {".ogv", ".ogg", nullptr};
|
||||
return rv;
|
||||
}
|
||||
case FFMPEG_WEBM: {
|
||||
static const char *rv[] = {".webm", NULL};
|
||||
static const char *rv[] = {".webm", nullptr};
|
||||
return rv;
|
||||
}
|
||||
case FFMPEG_AV1: {
|
||||
static const char *rv[] = {".mp4", ".mkv", NULL};
|
||||
static const char *rv[] = {".mp4", ".mkv", nullptr};
|
||||
return rv;
|
||||
}
|
||||
default:
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -328,10 +334,12 @@ static int write_video_frame(FFMpegContext *context, AVFrame *frame, ReportList
|
|||
frame->pts = context->video_time;
|
||||
context->video_time++;
|
||||
|
||||
char error_str[AV_ERROR_MAX_STRING_SIZE];
|
||||
ret = avcodec_send_frame(c, frame);
|
||||
if (ret < 0) {
|
||||
/* Can't send frame to encoder. This shouldn't happen. */
|
||||
fprintf(stderr, "Can't send video frame: %s\n", av_err2str(ret));
|
||||
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
|
||||
fprintf(stderr, "Can't send video frame: %s\n", error_str);
|
||||
success = -1;
|
||||
}
|
||||
|
||||
|
@ -343,7 +351,8 @@ static int write_video_frame(FFMpegContext *context, AVFrame *frame, ReportList
|
|||
break;
|
||||
}
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error encoding frame: %s\n", av_err2str(ret));
|
||||
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
|
||||
fprintf(stderr, "Error encoding frame: %s\n", error_str);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -361,7 +370,8 @@ static int write_video_frame(FFMpegContext *context, AVFrame *frame, ReportList
|
|||
|
||||
if (!success) {
|
||||
BKE_report(reports, RPT_ERROR, "Error writing frame");
|
||||
PRINT("Error writing frame: %s\n", av_err2str(ret));
|
||||
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
|
||||
PRINT("Error writing frame: %s\n", error_str);
|
||||
}
|
||||
|
||||
av_packet_free(&packet);
|
||||
|
@ -376,7 +386,7 @@ static AVFrame *generate_video_frame(FFMpegContext *context, const uint8_t *pixe
|
|||
int height = codec->height;
|
||||
AVFrame *rgb_frame;
|
||||
|
||||
if (context->img_convert_frame != NULL) {
|
||||
if (context->img_convert_frame != nullptr) {
|
||||
/* Pixel format conversion is needed. */
|
||||
rgb_frame = context->img_convert_frame;
|
||||
}
|
||||
|
@ -412,7 +422,7 @@ static AVFrame *generate_video_frame(FFMpegContext *context, const uint8_t *pixe
|
|||
}
|
||||
|
||||
/* Convert to the output pixel format, if it's different that Blender's internal one. */
|
||||
if (context->img_convert_frame != NULL) {
|
||||
if (context->img_convert_frame != nullptr) {
|
||||
BLI_assert(context->img_convert_ctx != NULL);
|
||||
sws_scale(context->img_convert_ctx,
|
||||
(const uint8_t *const *)rgb_frame->data,
|
||||
|
@ -438,14 +448,14 @@ static AVRational calc_time_base(uint den, double num, int codec_id)
|
|||
|
||||
/* Calculate the precision of the initial floating point number. */
|
||||
if (num > 1.0) {
|
||||
const uint num_integer_bits = log2_floor_u((uint)num);
|
||||
const uint num_integer_bits = log2_floor_u(uint(num));
|
||||
|
||||
/* Formula for calculating the epsilon value: (power of two range) / (pow mantissa bits)
|
||||
* For example, a float has 23 mantissa bits and the float value 3.5f as a pow2 range of
|
||||
* (4-2=2):
|
||||
* (2) / pow2(23) = floating point precision for 3.5f
|
||||
*/
|
||||
eps = (float)(1 << num_integer_bits) * FLT_EPSILON;
|
||||
eps = float(1 << num_integer_bits) * FLT_EPSILON;
|
||||
}
|
||||
|
||||
/* Calculate how many decimal shifts we can do until we run out of precision. */
|
||||
|
@ -463,7 +473,7 @@ static AVRational calc_time_base(uint den, double num, int codec_id)
|
|||
|
||||
AVRational time_base;
|
||||
time_base.den = den;
|
||||
time_base.num = (int)num;
|
||||
time_base.num = int(num);
|
||||
|
||||
return time_base;
|
||||
}
|
||||
|
@ -475,7 +485,7 @@ static const AVCodec *get_av1_encoder(
|
|||
* tends to give the best compression quality while `libsvtav1` tends to be the fastest encoder.
|
||||
* One of each will be picked based on the preset setting, and if a particular encoder is not
|
||||
* available, then use the default returned by FFMpeg. */
|
||||
const AVCodec *codec = NULL;
|
||||
const AVCodec *codec = nullptr;
|
||||
switch (context->ffmpeg_preset) {
|
||||
case FFM_PRESET_BEST:
|
||||
/* `libaom-av1` may produce better VMAF-scoring videos in several cases, but there are cases
|
||||
|
@ -529,7 +539,7 @@ static const AVCodec *get_av1_encoder(
|
|||
if (context->ffmpeg_crf >= 0) {
|
||||
/* librav1e does not use `-crf`, but uses `-qp` in the range of 0-255.
|
||||
* Calculates the roughly equivalent float, and truncates it to an integer. */
|
||||
uint qp_value = ((float)context->ffmpeg_crf) * 255.0f / 51.0f;
|
||||
uint qp_value = float(context->ffmpeg_crf) * 255.0f / 51.0f;
|
||||
if (qp_value > 255) {
|
||||
qp_value = 255;
|
||||
}
|
||||
|
@ -565,7 +575,7 @@ static const AVCodec *get_av1_encoder(
|
|||
else if (STREQ(codec->name, "libaom-av1")) {
|
||||
/* Speed up libaom-av1 encoding by enabling multi-threading and setting tiles. */
|
||||
ffmpeg_dict_set_int(opts, "row-mt", 1);
|
||||
const char *tiles_string = NULL;
|
||||
const char *tiles_string = nullptr;
|
||||
bool tiles_string_is_dynamic = false;
|
||||
if (rd->threads > 0) {
|
||||
/* See if threads is a square. */
|
||||
|
@ -594,7 +604,7 @@ static const AVCodec *get_av1_encoder(
|
|||
/* Ensure a default minimum. */
|
||||
sqrt_p2 = 2;
|
||||
}
|
||||
int sqrt_p2_next = power_of_2_min_i((int)rd->threads / sqrt_p2);
|
||||
int sqrt_p2_next = power_of_2_min_i(int(rd->threads) / sqrt_p2);
|
||||
if (sqrt_p2_next < 1) {
|
||||
sqrt_p2_next = 1;
|
||||
}
|
||||
|
@ -671,7 +681,7 @@ static const AVCodec *get_av1_encoder(
|
|||
|
||||
static AVStream *alloc_video_stream(FFMpegContext *context,
|
||||
RenderData *rd,
|
||||
int codec_id,
|
||||
AVCodecID codec_id,
|
||||
AVFormatContext *of,
|
||||
int rectx,
|
||||
int recty,
|
||||
|
@ -680,13 +690,13 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
|
|||
{
|
||||
AVStream *st;
|
||||
const AVCodec *codec;
|
||||
AVDictionary *opts = NULL;
|
||||
AVDictionary *opts = nullptr;
|
||||
|
||||
error[0] = '\0';
|
||||
|
||||
st = avformat_new_stream(of, NULL);
|
||||
st = avformat_new_stream(of, nullptr);
|
||||
if (!st) {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
st->id = 0;
|
||||
|
||||
|
@ -702,8 +712,8 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
|
|||
}
|
||||
if (!codec) {
|
||||
fprintf(stderr, "Couldn't find valid video codec\n");
|
||||
context->video_codec = NULL;
|
||||
return NULL;
|
||||
context->video_codec = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
context->video_codec = avcodec_alloc_context3(codec);
|
||||
|
@ -719,9 +729,9 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
|
|||
c->time_base.den = 2997;
|
||||
c->time_base.num = 100;
|
||||
}
|
||||
else if ((float)((int)rd->frs_sec_base) == rd->frs_sec_base) {
|
||||
else if (float(int(rd->frs_sec_base)) == rd->frs_sec_base) {
|
||||
c->time_base.den = rd->frs_sec;
|
||||
c->time_base.num = (int)rd->frs_sec_base;
|
||||
c->time_base.num = int(rd->frs_sec_base);
|
||||
}
|
||||
else {
|
||||
c->time_base = calc_time_base(rd->frs_sec, rd->frs_sec_base, codec_id);
|
||||
|
@ -769,8 +779,8 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
|
|||
/* 'preset' is used by h.264, 'deadline' is used by webm/vp9. I'm not
|
||||
* setting those properties conditionally based on the video codec,
|
||||
* as the FFmpeg encoder simply ignores unknown settings anyway. */
|
||||
char const *preset_name = NULL; /* used by h.264 */
|
||||
char const *deadline_name = NULL; /* used by webm/vp9 */
|
||||
char const *preset_name = nullptr; /* used by h.264 */
|
||||
char const *deadline_name = nullptr; /* used by webm/vp9 */
|
||||
switch (context->ffmpeg_preset) {
|
||||
case FFM_PRESET_GOOD:
|
||||
preset_name = "medium";
|
||||
|
@ -792,7 +802,7 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
|
|||
if (preset_name != NULL && codec_id != AV_CODEC_ID_AV1) {
|
||||
av_dict_set(&opts, "preset", preset_name, 0);
|
||||
}
|
||||
if (deadline_name != NULL) {
|
||||
if (deadline_name != nullptr) {
|
||||
av_dict_set(&opts, "deadline", deadline_name, 0);
|
||||
}
|
||||
}
|
||||
|
@ -861,7 +871,7 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
|
|||
|
||||
/* xasp & yasp got float lately... */
|
||||
|
||||
st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q(((double)rd->xasp / (double)rd->yasp),
|
||||
st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q((double(rd->xasp) / double(rd->yasp)),
|
||||
255);
|
||||
st->avg_frame_rate = av_inv_q(c->time_base);
|
||||
|
||||
|
@ -882,12 +892,14 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
|
|||
int ret = avcodec_open2(c, codec, &opts);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Couldn't initialize video codec: %s\n", av_err2str(ret));
|
||||
char error_str[AV_ERROR_MAX_STRING_SIZE];
|
||||
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
|
||||
fprintf(stderr, "Couldn't initialize video codec: %s\n", error_str);
|
||||
BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
|
||||
av_dict_free(&opts);
|
||||
avcodec_free_context(&c);
|
||||
context->video_codec = NULL;
|
||||
return NULL;
|
||||
context->video_codec = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
av_dict_free(&opts);
|
||||
|
||||
|
@ -896,8 +908,8 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
|
|||
|
||||
if (c->pix_fmt == AV_PIX_FMT_RGBA) {
|
||||
/* Output pixel format is the same we use internally, no conversion necessary. */
|
||||
context->img_convert_frame = NULL;
|
||||
context->img_convert_ctx = NULL;
|
||||
context->img_convert_frame = nullptr;
|
||||
context->img_convert_ctx = nullptr;
|
||||
}
|
||||
else {
|
||||
/* Output pixel format is different, allocate frame for conversion. */
|
||||
|
@ -909,9 +921,9 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
|
|||
c->height,
|
||||
c->pix_fmt,
|
||||
SWS_BICUBIC,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
avcodec_parameters_from_context(st->codecpar, c);
|
||||
|
@ -923,7 +935,7 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
|
|||
|
||||
static AVStream *alloc_audio_stream(FFMpegContext *context,
|
||||
RenderData *rd,
|
||||
int codec_id,
|
||||
AVCodecID codec_id,
|
||||
AVFormatContext *of,
|
||||
char *error,
|
||||
int error_size)
|
||||
|
@ -933,17 +945,17 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
|
|||
|
||||
error[0] = '\0';
|
||||
|
||||
st = avformat_new_stream(of, NULL);
|
||||
st = avformat_new_stream(of, nullptr);
|
||||
if (!st) {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
st->id = 1;
|
||||
|
||||
codec = avcodec_find_encoder(codec_id);
|
||||
if (!codec) {
|
||||
fprintf(stderr, "Couldn't find valid audio codec\n");
|
||||
context->audio_codec = NULL;
|
||||
return NULL;
|
||||
context->audio_codec = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
context->audio_codec = avcodec_alloc_context3(codec);
|
||||
|
@ -1026,14 +1038,16 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
|
|||
c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
||||
}
|
||||
|
||||
int ret = avcodec_open2(c, codec, NULL);
|
||||
int ret = avcodec_open2(c, codec, nullptr);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Couldn't initialize audio codec: %s\n", av_err2str(ret));
|
||||
char error_str[AV_ERROR_MAX_STRING_SIZE];
|
||||
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
|
||||
fprintf(stderr, "Couldn't initialize audio codec: %s\n", error_str);
|
||||
BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
|
||||
avcodec_free_context(&c);
|
||||
context->audio_codec = NULL;
|
||||
return NULL;
|
||||
context->audio_codec = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Need to prevent floating point exception when using VORBIS audio codec,
|
||||
|
@ -1083,7 +1097,7 @@ static void ffmpeg_dict_set_int(AVDictionary **dict, const char *key, int value)
|
|||
static void ffmpeg_add_metadata_callback(void *data,
|
||||
const char *propname,
|
||||
char *propvalue,
|
||||
int UNUSED(propvalue_maxncpy))
|
||||
int /*propvalue_maxncpy*/)
|
||||
{
|
||||
AVDictionary **metadata = (AVDictionary **)data;
|
||||
av_dict_set(metadata, propname, propvalue, 0);
|
||||
|
@ -1101,10 +1115,11 @@ static int start_ffmpeg_impl(FFMpegContext *context,
|
|||
const AVOutputFormat *fmt;
|
||||
char filepath[FILE_MAX], error[1024];
|
||||
const char **exts;
|
||||
int ret = 0;
|
||||
|
||||
context->ffmpeg_type = rd->ffcodecdata.type;
|
||||
context->ffmpeg_codec = rd->ffcodecdata.codec;
|
||||
context->ffmpeg_audio_codec = rd->ffcodecdata.audio_codec;
|
||||
context->ffmpeg_codec = AVCodecID(rd->ffcodecdata.codec);
|
||||
context->ffmpeg_audio_codec = AVCodecID(rd->ffcodecdata.audio_codec);
|
||||
context->ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate;
|
||||
context->ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate;
|
||||
context->ffmpeg_gop_size = rd->ffcodecdata.gop_size;
|
||||
|
@ -1142,7 +1157,7 @@ static int start_ffmpeg_impl(FFMpegContext *context,
|
|||
return 0;
|
||||
}
|
||||
|
||||
fmt = av_guess_format(NULL, exts[0], NULL);
|
||||
fmt = av_guess_format(NULL, exts[0], nullptr);
|
||||
if (!fmt) {
|
||||
BKE_report(reports, RPT_ERROR, "No valid formats found");
|
||||
return 0;
|
||||
|
@ -1265,17 +1280,19 @@ static int start_ffmpeg_impl(FFMpegContext *context,
|
|||
}
|
||||
}
|
||||
|
||||
if (context->stamp_data != NULL) {
|
||||
if (context->stamp_data != nullptr) {
|
||||
BKE_stamp_info_callback(
|
||||
&of->metadata, context->stamp_data, ffmpeg_add_metadata_callback, false);
|
||||
}
|
||||
|
||||
int ret = avformat_write_header(of, NULL);
|
||||
ret = avformat_write_header(of, nullptr);
|
||||
if (ret < 0) {
|
||||
BKE_report(reports,
|
||||
RPT_ERROR,
|
||||
"Could not initialize streams, probably unsupported codec combination");
|
||||
PRINT("Could not write media header: %s\n", av_err2str(ret));
|
||||
char error_str[AV_ERROR_MAX_STRING_SIZE];
|
||||
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
|
||||
PRINT("Could not write media header: %s\n", error_str);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -1290,11 +1307,11 @@ fail:
|
|||
}
|
||||
|
||||
if (context->video_stream) {
|
||||
context->video_stream = NULL;
|
||||
context->video_stream = nullptr;
|
||||
}
|
||||
|
||||
if (context->audio_stream) {
|
||||
context->audio_stream = NULL;
|
||||
context->audio_stream = nullptr;
|
||||
}
|
||||
|
||||
avformat_free_context(of);
|
||||
|
@ -1320,9 +1337,10 @@ fail:
|
|||
*/
|
||||
static void flush_ffmpeg(AVCodecContext *c, AVStream *stream, AVFormatContext *outfile)
|
||||
{
|
||||
char error_str[AV_ERROR_MAX_STRING_SIZE];
|
||||
AVPacket *packet = av_packet_alloc();
|
||||
|
||||
avcodec_send_frame(c, NULL);
|
||||
avcodec_send_frame(c, nullptr);
|
||||
|
||||
/* Get the packets frames. */
|
||||
int ret = 1;
|
||||
|
@ -1334,7 +1352,8 @@ static void flush_ffmpeg(AVCodecContext *c, AVStream *stream, AVFormatContext *o
|
|||
break;
|
||||
}
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error encoding delayed frame: %s\n", av_err2str(ret));
|
||||
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
|
||||
fprintf(stderr, "Error encoding delayed frame: %s\n", error_str);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1346,7 +1365,8 @@ static void flush_ffmpeg(AVCodecContext *c, AVStream *stream, AVFormatContext *o
|
|||
|
||||
int write_ret = av_interleaved_write_frame(outfile, packet);
|
||||
if (write_ret != 0) {
|
||||
fprintf(stderr, "Error writing delayed frame: %s\n", av_err2str(write_ret));
|
||||
av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
|
||||
fprintf(stderr, "Error writing delayed frame: %s\n", error_str);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1405,7 +1425,7 @@ static void ffmpeg_filepath_get(FFMpegContext *context,
|
|||
fe++;
|
||||
}
|
||||
|
||||
if (*fe == NULL) {
|
||||
if (*fe == nullptr) {
|
||||
BLI_strncat(filepath, autosplit, FILE_MAX);
|
||||
|
||||
BLI_path_frame_range(filepath, FILE_MAX, sfra, efra, 4);
|
||||
|
@ -1433,7 +1453,7 @@ void BKE_ffmpeg_filepath_get(char filepath[/*FILE_MAX*/ 1024],
|
|||
bool preview,
|
||||
const char *suffix)
|
||||
{
|
||||
ffmpeg_filepath_get(NULL, filepath, rd, preview, suffix);
|
||||
ffmpeg_filepath_get(nullptr, filepath, rd, preview, suffix);
|
||||
}
|
||||
|
||||
int BKE_ffmpeg_start(void *context_v,
|
||||
|
@ -1446,7 +1466,7 @@ int BKE_ffmpeg_start(void *context_v,
|
|||
const char *suffix)
|
||||
{
|
||||
int success;
|
||||
FFMpegContext *context = context_v;
|
||||
FFMpegContext *context = static_cast<FFMpegContext *>(context_v);
|
||||
|
||||
context->ffmpeg_autosplit_count = 0;
|
||||
context->ffmpeg_preview = preview;
|
||||
|
@ -1459,9 +1479,9 @@ int BKE_ffmpeg_start(void *context_v,
|
|||
|
||||
AUD_DeviceSpecs specs;
|
||||
# ifdef FFMPEG_USE_OLD_CHANNEL_VARS
|
||||
specs.channels = c->channels;
|
||||
specs.channels = AUD_Channels(c->channels);
|
||||
# else
|
||||
specs.channels = c->ch_layout.nb_channels;
|
||||
specs.channels = AUD_Channels(c->ch_layout.nb_channels);
|
||||
# endif
|
||||
|
||||
switch (av_get_packed_sample_fmt(c->sample_fmt)) {
|
||||
|
@ -1503,8 +1523,8 @@ static void write_audio_frames(FFMpegContext *context, double to_pts)
|
|||
if ((context->audio_time_total >= to_pts) || !write_audio_frame(context)) {
|
||||
break;
|
||||
}
|
||||
context->audio_time_total += (double)context->audio_input_samples / (double)c->sample_rate;
|
||||
context->audio_time += (double)context->audio_input_samples / (double)c->sample_rate;
|
||||
context->audio_time_total += double(context->audio_input_samples) / double(c->sample_rate);
|
||||
context->audio_time += double(context->audio_input_samples) / double(c->sample_rate);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
@ -1519,7 +1539,7 @@ int BKE_ffmpeg_append(void *context_v,
|
|||
const char *suffix,
|
||||
ReportList *reports)
|
||||
{
|
||||
FFMpegContext *context = context_v;
|
||||
FFMpegContext *context = static_cast<FFMpegContext *>(context_v);
|
||||
AVFrame *avframe;
|
||||
int success = 1;
|
||||
|
||||
|
@ -1531,7 +1551,7 @@ int BKE_ffmpeg_append(void *context_v,
|
|||
# ifdef WITH_AUDASPACE
|
||||
/* Add +1 frame because we want to encode audio up until the next video frame. */
|
||||
write_audio_frames(
|
||||
context, (frame - start_frame + 1) / (((double)rd->frs_sec) / (double)rd->frs_sec_base));
|
||||
context, (frame - start_frame + 1) / (double(rd->frs_sec) / double(rd->frs_sec_base)));
|
||||
# else
|
||||
UNUSED_VARS(start_frame);
|
||||
# endif
|
||||
|
@ -1557,7 +1577,7 @@ static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit)
|
|||
if (is_autosplit == false) {
|
||||
if (context->audio_mixdown_device) {
|
||||
AUD_Device_free(context->audio_mixdown_device);
|
||||
context->audio_mixdown_device = NULL;
|
||||
context->audio_mixdown_device = nullptr;
|
||||
}
|
||||
}
|
||||
# else
|
||||
|
@ -1580,23 +1600,23 @@ static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit)
|
|||
|
||||
/* Close the video codec */
|
||||
|
||||
if (context->video_stream != NULL) {
|
||||
if (context->video_stream != nullptr) {
|
||||
PRINT("zero video stream %p\n", context->video_stream);
|
||||
context->video_stream = NULL;
|
||||
context->video_stream = nullptr;
|
||||
}
|
||||
|
||||
if (context->audio_stream != NULL) {
|
||||
context->audio_stream = NULL;
|
||||
if (context->audio_stream != nullptr) {
|
||||
context->audio_stream = nullptr;
|
||||
}
|
||||
|
||||
/* free the temp buffer */
|
||||
if (context->current_frame != NULL) {
|
||||
if (context->current_frame != nullptr) {
|
||||
delete_picture(context->current_frame);
|
||||
context->current_frame = NULL;
|
||||
context->current_frame = nullptr;
|
||||
}
|
||||
if (context->img_convert_frame != NULL) {
|
||||
if (context->img_convert_frame != nullptr) {
|
||||
delete_picture(context->img_convert_frame);
|
||||
context->img_convert_frame = NULL;
|
||||
context->img_convert_frame = nullptr;
|
||||
}
|
||||
|
||||
if (context->outfile != NULL && context->outfile->oformat) {
|
||||
|
@ -1605,38 +1625,38 @@ static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit)
|
|||
}
|
||||
}
|
||||
|
||||
if (context->video_codec != NULL) {
|
||||
if (context->video_codec != nullptr) {
|
||||
avcodec_free_context(&context->video_codec);
|
||||
context->video_codec = NULL;
|
||||
context->video_codec = nullptr;
|
||||
}
|
||||
if (context->audio_codec != NULL) {
|
||||
if (context->audio_codec != nullptr) {
|
||||
avcodec_free_context(&context->audio_codec);
|
||||
context->audio_codec = NULL;
|
||||
context->audio_codec = nullptr;
|
||||
}
|
||||
|
||||
if (context->outfile != NULL) {
|
||||
if (context->outfile != nullptr) {
|
||||
avformat_free_context(context->outfile);
|
||||
context->outfile = NULL;
|
||||
context->outfile = nullptr;
|
||||
}
|
||||
if (context->audio_input_buffer != NULL) {
|
||||
if (context->audio_input_buffer != nullptr) {
|
||||
av_free(context->audio_input_buffer);
|
||||
context->audio_input_buffer = NULL;
|
||||
context->audio_input_buffer = nullptr;
|
||||
}
|
||||
|
||||
if (context->audio_deinterleave_buffer != NULL) {
|
||||
if (context->audio_deinterleave_buffer != nullptr) {
|
||||
av_free(context->audio_deinterleave_buffer);
|
||||
context->audio_deinterleave_buffer = NULL;
|
||||
context->audio_deinterleave_buffer = nullptr;
|
||||
}
|
||||
|
||||
if (context->img_convert_ctx != NULL) {
|
||||
if (context->img_convert_ctx != nullptr) {
|
||||
sws_freeContext(context->img_convert_ctx);
|
||||
context->img_convert_ctx = NULL;
|
||||
context->img_convert_ctx = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_ffmpeg_end(void *context_v)
|
||||
{
|
||||
FFMpegContext *context = context_v;
|
||||
FFMpegContext *context = static_cast<FFMpegContext *>(context_v);
|
||||
end_ffmpeg_impl(context, false);
|
||||
}
|
||||
|
||||
|
@ -1803,12 +1823,11 @@ bool BKE_ffmpeg_alpha_channel_is_supported(const RenderData *rd)
|
|||
AV_CODEC_ID_HUFFYUV);
|
||||
}
|
||||
|
||||
void *BKE_ffmpeg_context_create(void)
|
||||
void *BKE_ffmpeg_context_create()
|
||||
{
|
||||
FFMpegContext *context;
|
||||
|
||||
/* new ffmpeg data struct */
|
||||
context = MEM_callocN(sizeof(FFMpegContext), "new ffmpeg context");
|
||||
FFMpegContext *context = static_cast<FFMpegContext *>(
|
||||
MEM_callocN(sizeof(FFMpegContext), "new ffmpeg context"));
|
||||
|
||||
context->ffmpeg_codec = AV_CODEC_ID_MPEG4;
|
||||
context->ffmpeg_audio_codec = AV_CODEC_ID_NONE;
|
||||
|
@ -1818,7 +1837,7 @@ void *BKE_ffmpeg_context_create(void)
|
|||
context->ffmpeg_autosplit = 0;
|
||||
context->ffmpeg_autosplit_count = 0;
|
||||
context->ffmpeg_preview = false;
|
||||
context->stamp_data = NULL;
|
||||
context->stamp_data = nullptr;
|
||||
context->audio_time_total = 0.0;
|
||||
|
||||
return context;
|
||||
|
@ -1826,8 +1845,8 @@ void *BKE_ffmpeg_context_create(void)
|
|||
|
||||
void BKE_ffmpeg_context_free(void *context_v)
|
||||
{
|
||||
FFMpegContext *context = context_v;
|
||||
if (context == NULL) {
|
||||
FFMpegContext *context = static_cast<FFMpegContext *>(context_v);
|
||||
if (context == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (context->stamp_data) {
|
|
@ -423,7 +423,7 @@ const IndexMask &get_static_index_mask_for_min_size(const int64_t min_size);
|
|||
std::ostream &operator<<(std::ostream &stream, const IndexMask &mask);
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Inline Utilities
|
||||
/** \name Utilities
|
||||
* \{ */
|
||||
|
||||
inline const std::array<int16_t, max_segment_size> &get_static_indices_array()
|
||||
|
@ -439,6 +439,13 @@ inline void masked_fill(MutableSpan<T> data, const T &value, const IndexMask &ma
|
|||
mask.foreach_index_optimized<int64_t>([&](const int64_t i) { data[i] = value; });
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill masked indices of \a r_mask with the index of that item in the mask such that
|
||||
* `r_map[mask[i]] == i` for the whole mask. The size of `r_map` needs to be at least
|
||||
* `mask.min_array_size()`.
|
||||
*/
|
||||
template<typename T> void build_reverse_map(const IndexMask &mask, MutableSpan<T> r_map);
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #RawMaskIterator Inline Methods
|
||||
* \{ */
|
||||
|
|
|
@ -197,8 +197,10 @@ BVHTreeOverlap *BLI_bvhtree_overlap(const BVHTree *tree1,
|
|||
unsigned int *r_overlap_num,
|
||||
BVHTree_OverlapCallback callback,
|
||||
void *userdata);
|
||||
/** Compute overlaps of the tree with itself. This is faster than BLI_bvhtree_overlap
|
||||
* because it only tests and returns each symmetrical pair once. */
|
||||
/**
|
||||
* Compute overlaps of the tree with itself. This is faster than #BLI_bvhtree_overlap
|
||||
* because it only tests and returns each symmetrical pair once.
|
||||
*/
|
||||
BVHTreeOverlap *BLI_bvhtree_overlap_self(const BVHTree *tree,
|
||||
unsigned int *r_overlap_num,
|
||||
BVHTree_OverlapCallback callback,
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
/* SPDX-FileCopyrightText: 2008 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
* \ingroup bli
|
||||
*/
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uintptr_t key;
|
||||
void *val;
|
||||
} SmallHashEntry;
|
||||
|
||||
/**
|
||||
* How much stack space to use before dynamically allocating memory.
|
||||
* set to match one of the values in 'hashsizes' to avoid too many mallocs.
|
||||
*/
|
||||
#define SMSTACKSIZE 131
|
||||
typedef struct SmallHash {
|
||||
unsigned int nbuckets;
|
||||
unsigned int nentries;
|
||||
unsigned int cursize;
|
||||
|
||||
SmallHashEntry *buckets;
|
||||
SmallHashEntry buckets_stack[SMSTACKSIZE];
|
||||
} SmallHash;
|
||||
|
||||
typedef struct {
|
||||
const SmallHash *sh;
|
||||
unsigned int i;
|
||||
} SmallHashIter;
|
||||
|
||||
void BLI_smallhash_init_ex(SmallHash *sh, unsigned int nentries_reserve) ATTR_NONNULL(1);
|
||||
void BLI_smallhash_init(SmallHash *sh) ATTR_NONNULL(1);
|
||||
/**
|
||||
* \note does *not* free *sh itself! only the direct data!
|
||||
*/
|
||||
void BLI_smallhash_release(SmallHash *sh) ATTR_NONNULL(1);
|
||||
void BLI_smallhash_insert(SmallHash *sh, uintptr_t key, void *item) ATTR_NONNULL(1);
|
||||
/**
|
||||
* Inserts a new value to a key that may already be in #GHash.
|
||||
*
|
||||
* Avoids #BLI_smallhash_remove, #BLI_smallhash_insert calls (double lookups)
|
||||
*
|
||||
* \returns true if a new key has been added.
|
||||
*/
|
||||
bool BLI_smallhash_reinsert(SmallHash *sh, uintptr_t key, void *item) ATTR_NONNULL(1);
|
||||
bool BLI_smallhash_remove(SmallHash *sh, uintptr_t key) ATTR_NONNULL(1);
|
||||
void *BLI_smallhash_lookup(const SmallHash *sh, uintptr_t key)
|
||||
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
|
||||
void **BLI_smallhash_lookup_p(const SmallHash *sh, uintptr_t key)
|
||||
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
|
||||
bool BLI_smallhash_haskey(const SmallHash *sh, uintptr_t key) ATTR_NONNULL(1);
|
||||
int BLI_smallhash_len(const SmallHash *sh) ATTR_NONNULL(1);
|
||||
void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key)
|
||||
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
|
||||
void **BLI_smallhash_iternext_p(SmallHashIter *iter, uintptr_t *key)
|
||||
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
|
||||
void *BLI_smallhash_iternew(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
|
||||
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
|
||||
void **BLI_smallhash_iternew_p(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
|
||||
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
|
||||
// void BLI_smallhash_print(SmallHash *sh); /* UNUSED. */
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
* Measure how well the hash function performs
|
||||
* (1.0 is perfect - no stepping needed).
|
||||
*
|
||||
* Smaller is better!
|
||||
*/
|
||||
double BLI_smallhash_calc_quality(SmallHash *sh);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,67 +0,0 @@
|
|||
/* SPDX-FileCopyrightText: 2012 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
struct ListBase;
|
||||
|
||||
/** \file
|
||||
* \ingroup bli
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct VoronoiSite {
|
||||
float co[2];
|
||||
float color[3];
|
||||
} VoronoiSite;
|
||||
|
||||
typedef struct VoronoiEdge {
|
||||
struct VoronoiEdge *next, *prev;
|
||||
|
||||
/* start and end points */
|
||||
float start[2], end[2];
|
||||
|
||||
/* this fields are used during diagram computation only */
|
||||
|
||||
/* directional vector, from "start", points to "end", normal of |left, right| */
|
||||
float direction[2];
|
||||
|
||||
/* point on Voronoi place on the left side of edge */
|
||||
float left[2];
|
||||
/* point on Voronoi place on the right side of edge */
|
||||
float right[2];
|
||||
|
||||
/* Directional coefficients satisfying equation `y = f * x + g` (edge lies on this line). */
|
||||
float f, g;
|
||||
|
||||
/* some edges consist of two parts,
|
||||
* so we add the pointer to another part to connect them at the end of an algorithm */
|
||||
struct VoronoiEdge *neighbor;
|
||||
} VoronoiEdge;
|
||||
|
||||
typedef struct VoronoiTriangulationPoint {
|
||||
float co[2];
|
||||
float color[3];
|
||||
int power;
|
||||
} VoronoiTriangulationPoint;
|
||||
|
||||
void BLI_voronoi_compute(
|
||||
const VoronoiSite *sites, int sites_total, int width, int height, struct ListBase *edges);
|
||||
|
||||
void BLI_voronoi_triangulate(const VoronoiSite *sites,
|
||||
int sites_total,
|
||||
struct ListBase *edges,
|
||||
int width,
|
||||
int height,
|
||||
VoronoiTriangulationPoint **r_triangulated_points,
|
||||
int *r_triangulated_points_total,
|
||||
int (**r_triangles)[3],
|
||||
int *r_triangles_total);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -19,13 +19,7 @@ extern "C" {
|
|||
|
||||
/* All input coordinates must be in bounding box 0.0 - 1.0. */
|
||||
|
||||
float BLI_voxel_sample_nearest(const float *data, const int res[3], const float co[3]);
|
||||
float BLI_voxel_sample_trilinear(const float *data, const int res[3], const float co[3]);
|
||||
float BLI_voxel_sample_triquadratic(const float *data, const int res[3], const float co[3]);
|
||||
float BLI_voxel_sample_tricubic(const float *data,
|
||||
const int res[3],
|
||||
const float co[3],
|
||||
int bspline);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -134,7 +134,6 @@ set(SRC
|
|||
intern/serialize.cc
|
||||
intern/session_uuid.c
|
||||
intern/smaa_textures.c
|
||||
intern/smallhash.c
|
||||
intern/sort.c
|
||||
intern/sort_utils.c
|
||||
intern/stack.c
|
||||
|
@ -160,7 +159,6 @@ set(SRC
|
|||
intern/uvproject.c
|
||||
intern/vector.cc
|
||||
intern/virtual_array.cc
|
||||
intern/voronoi_2d.c
|
||||
intern/voxel.c
|
||||
intern/winstuff.cc
|
||||
intern/winstuff_dir.cc
|
||||
|
@ -342,7 +340,6 @@ set(SRC
|
|||
BLI_shared_cache.hh
|
||||
BLI_simd.h
|
||||
BLI_smaa_textures.h
|
||||
BLI_smallhash.h
|
||||
BLI_sort.h
|
||||
BLI_sort.hh
|
||||
BLI_sort_utils.h
|
||||
|
@ -382,7 +379,6 @@ set(SRC
|
|||
BLI_vector_set_slots.hh
|
||||
BLI_virtual_array.hh
|
||||
BLI_virtual_vector_array.hh
|
||||
BLI_voronoi_2d.h
|
||||
BLI_voxel.h
|
||||
BLI_winstuff.h
|
||||
BLI_winstuff_com.hh
|
||||
|
|
|
@ -35,16 +35,12 @@
|
|||
|
||||
/**
|
||||
* Next prime after `2^n` (skipping 2 & 3).
|
||||
*
|
||||
* \note Also used by: `BLI_smallhash`.
|
||||
*/
|
||||
extern const uint BLI_ghash_hash_sizes[]; /* Quiet warning, this is only used by smallhash.c */
|
||||
const uint BLI_ghash_hash_sizes[] = {
|
||||
static const uint hashsizes[] = {
|
||||
5, 11, 17, 37, 67, 131, 257, 521, 1031,
|
||||
2053, 4099, 8209, 16411, 32771, 65537, 131101, 262147, 524309,
|
||||
1048583, 2097169, 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459,
|
||||
};
|
||||
#define hashsizes BLI_ghash_hash_sizes
|
||||
|
||||
#ifdef GHASH_USE_MODULO_BUCKETS
|
||||
# define GHASH_MAX_SIZE 27
|
||||
|
|
|
@ -20,6 +20,19 @@
|
|||
|
||||
namespace blender::index_mask {
|
||||
|
||||
template<typename T> void build_reverse_map(const IndexMask &mask, MutableSpan<T> r_map)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
/* Catch errors with asserts in debug builds. */
|
||||
r_map.fill(-1);
|
||||
#endif
|
||||
BLI_assert(r_map.size() >= mask.min_array_size());
|
||||
mask.foreach_index_optimized<T>(GrainSize(4096),
|
||||
[&](const T src, const T dst) { r_map[src] = dst; });
|
||||
}
|
||||
|
||||
template void build_reverse_map<int>(const IndexMask &mask, MutableSpan<int> r_map);
|
||||
|
||||
std::array<int16_t, max_segment_size> build_static_indices_array()
|
||||
{
|
||||
std::array<int16_t, max_segment_size> data;
|
||||
|
|
|
@ -2253,7 +2253,7 @@ static void propagate_windings_and_in_output_volume(PatchesInfo &pinfo,
|
|||
}
|
||||
|
||||
/**
|
||||
* Given an array of winding numbers, where the ith entry is a cell's winding
|
||||
* Given an array of winding numbers, where the `i-th` entry is a cell's winding
|
||||
* number with respect to input shape (mesh part) i, return true if the
|
||||
* cell should be included in the output of the boolean operation.
|
||||
* Intersection: all the winding numbers must be nonzero.
|
||||
|
|
|
@ -896,14 +896,14 @@ bool BLI_path_parent_dir_until_exists(char *dir)
|
|||
/**
|
||||
* Looks for a sequence of "#" characters in the last slash-separated component of `path`,
|
||||
* returning the indexes of the first and one past the last character in the sequence in
|
||||
* `char_start` and `char_end` respectively.
|
||||
* `r_char_start` and `r_char_end` respectively.
|
||||
*
|
||||
* \param char_start: The first `#` character.
|
||||
* \param char_end: The last `#` character +1.
|
||||
* \param r_char_start: The first `#` character.
|
||||
* \param r_char_end: The last `#` character +1.
|
||||
*
|
||||
* \return true if a frame sequence range was found.
|
||||
*/
|
||||
static bool path_frame_chars_find_range(const char *path, int *char_start, int *char_end)
|
||||
static bool path_frame_chars_find_range(const char *path, int *r_char_start, int *r_char_end)
|
||||
{
|
||||
uint ch_sta, ch_end, i;
|
||||
/* Insert current frame: `file###` -> `file001`. */
|
||||
|
@ -925,13 +925,13 @@ static bool path_frame_chars_find_range(const char *path, int *char_start, int *
|
|||
}
|
||||
|
||||
if (ch_end) {
|
||||
*char_start = ch_sta;
|
||||
*char_end = ch_end;
|
||||
*r_char_start = ch_sta;
|
||||
*r_char_end = ch_end;
|
||||
return true;
|
||||
}
|
||||
|
||||
*char_start = -1;
|
||||
*char_end = -1;
|
||||
*r_char_start = -1;
|
||||
*r_char_end = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,399 +0,0 @@
|
|||
/* SPDX-FileCopyrightText: 2008 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup bli
|
||||
*
|
||||
* A light stack-friendly hash library, it uses stack space for relatively small,
|
||||
* fixed size hash tables but falls back to heap memory once the stack limits reached
|
||||
* (#SMSTACKSIZE).
|
||||
*
|
||||
* based on a doubling hashing approach (non-chaining) which uses more buckets than entries
|
||||
* stepping over buckets when two keys share the same hash so any key can find a free bucket.
|
||||
*
|
||||
* See: https://en.wikipedia.org/wiki/Double_hashing
|
||||
*
|
||||
* \warning This should _only_ be used for small hashes
|
||||
* where allocating a hash every time is unacceptable.
|
||||
* Otherwise #GHash should be used instead.
|
||||
*
|
||||
* #SmallHashEntry.key
|
||||
* - `SMHASH_KEY_UNUSED` means the key in the cell has not been initialized.
|
||||
*
|
||||
* #SmallHashEntry.val
|
||||
* - `SMHASH_CELL_UNUSED` means this cell is inside a key series.
|
||||
* - `SMHASH_CELL_FREE` means this cell terminates a key series.
|
||||
*
|
||||
* Note that the values and keys are often pointers or index values,
|
||||
* use the maximum values to avoid real pointers colliding with magic numbers.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "BLI_sys_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLI_smallhash.h"
|
||||
|
||||
#include "BLI_strict_flags.h"
|
||||
|
||||
#define SMHASH_KEY_UNUSED ((uintptr_t)(UINTPTR_MAX - 0))
|
||||
#define SMHASH_CELL_FREE ((void *)(UINTPTR_MAX - 1))
|
||||
#define SMHASH_CELL_UNUSED ((void *)(UINTPTR_MAX - 2))
|
||||
|
||||
/* typically this re-assigns 'h' */
|
||||
#define SMHASH_NEXT(h, hoff) \
|
||||
(CHECK_TYPE_INLINE(&(h), uint *), \
|
||||
CHECK_TYPE_INLINE(&(hoff), uint *), \
|
||||
((h) + (((hoff) = ((hoff)*2) + 1), (hoff))))
|
||||
|
||||
/* nothing uses BLI_smallhash_remove yet */
|
||||
// #define USE_REMOVE
|
||||
|
||||
BLI_INLINE bool smallhash_val_is_used(const void *val)
|
||||
{
|
||||
#ifdef USE_REMOVE
|
||||
return !ELEM(val, SMHASH_CELL_FREE, SMHASH_CELL_UNUSED);
|
||||
#else
|
||||
return (val != SMHASH_CELL_FREE);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern const uint BLI_ghash_hash_sizes[];
|
||||
#define hashsizes BLI_ghash_hash_sizes
|
||||
|
||||
BLI_INLINE uint smallhash_key(const uintptr_t key)
|
||||
{
|
||||
return (uint)key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the number of items in the smallhash is large enough to require more buckets.
|
||||
*/
|
||||
BLI_INLINE bool smallhash_test_expand_buckets(const uint nentries, const uint nbuckets)
|
||||
{
|
||||
/* (approx * 1.5) */
|
||||
return (nentries + (nentries >> 1)) > nbuckets;
|
||||
}
|
||||
|
||||
BLI_INLINE void smallhash_init_empty(SmallHash *sh)
|
||||
{
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < sh->nbuckets; i++) {
|
||||
sh->buckets[i].key = SMHASH_KEY_UNUSED;
|
||||
sh->buckets[i].val = SMHASH_CELL_FREE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase initial bucket size to match a reserved amount.
|
||||
*/
|
||||
BLI_INLINE void smallhash_buckets_reserve(SmallHash *sh, const uint nentries_reserve)
|
||||
{
|
||||
while (smallhash_test_expand_buckets(nentries_reserve, sh->nbuckets)) {
|
||||
sh->nbuckets = hashsizes[++sh->cursize];
|
||||
}
|
||||
}
|
||||
|
||||
BLI_INLINE SmallHashEntry *smallhash_lookup(const SmallHash *sh, const uintptr_t key)
|
||||
{
|
||||
SmallHashEntry *e;
|
||||
uint h = smallhash_key(key);
|
||||
uint hoff = 1;
|
||||
|
||||
BLI_assert(key != SMHASH_KEY_UNUSED);
|
||||
|
||||
/* NOTE: there are always more buckets than entries,
|
||||
* so we know there will always be a free bucket if the key isn't found. */
|
||||
for (e = &sh->buckets[h % sh->nbuckets]; e->val != SMHASH_CELL_FREE;
|
||||
h = SMHASH_NEXT(h, hoff), e = &sh->buckets[h % sh->nbuckets])
|
||||
{
|
||||
if (e->key == key) {
|
||||
/* should never happen because unused keys are zero'd */
|
||||
BLI_assert(e->val != SMHASH_CELL_UNUSED);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BLI_INLINE SmallHashEntry *smallhash_lookup_first_free(SmallHash *sh, const uintptr_t key)
|
||||
{
|
||||
SmallHashEntry *e;
|
||||
uint h = smallhash_key(key);
|
||||
uint hoff = 1;
|
||||
|
||||
for (e = &sh->buckets[h % sh->nbuckets]; smallhash_val_is_used(e->val);
|
||||
h = SMHASH_NEXT(h, hoff), e = &sh->buckets[h % sh->nbuckets])
|
||||
{
|
||||
/* pass */
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
BLI_INLINE void smallhash_resize_buckets(SmallHash *sh, const uint nbuckets)
|
||||
{
|
||||
SmallHashEntry *buckets_old = sh->buckets;
|
||||
const uint nbuckets_old = sh->nbuckets;
|
||||
const bool was_alloc = (buckets_old != sh->buckets_stack);
|
||||
uint i = 0;
|
||||
|
||||
BLI_assert(sh->nbuckets != nbuckets);
|
||||
if (nbuckets <= SMSTACKSIZE) {
|
||||
const size_t size = sizeof(*buckets_old) * nbuckets_old;
|
||||
buckets_old = alloca(size);
|
||||
memcpy(buckets_old, sh->buckets, size);
|
||||
|
||||
sh->buckets = sh->buckets_stack;
|
||||
}
|
||||
else {
|
||||
sh->buckets = MEM_mallocN(sizeof(*sh->buckets) * nbuckets, __func__);
|
||||
}
|
||||
|
||||
sh->nbuckets = nbuckets;
|
||||
|
||||
smallhash_init_empty(sh);
|
||||
|
||||
for (i = 0; i < nbuckets_old; i++) {
|
||||
if (smallhash_val_is_used(buckets_old[i].val)) {
|
||||
SmallHashEntry *e = smallhash_lookup_first_free(sh, buckets_old[i].key);
|
||||
e->key = buckets_old[i].key;
|
||||
e->val = buckets_old[i].val;
|
||||
}
|
||||
}
|
||||
|
||||
if (was_alloc) {
|
||||
MEM_freeN(buckets_old);
|
||||
}
|
||||
}
|
||||
|
||||
void BLI_smallhash_init_ex(SmallHash *sh, const uint nentries_reserve)
|
||||
{
|
||||
/* assume 'sh' is uninitialized */
|
||||
|
||||
sh->nentries = 0;
|
||||
sh->cursize = 2;
|
||||
sh->nbuckets = hashsizes[sh->cursize];
|
||||
|
||||
sh->buckets = sh->buckets_stack;
|
||||
|
||||
if (nentries_reserve) {
|
||||
smallhash_buckets_reserve(sh, nentries_reserve);
|
||||
|
||||
if (sh->nbuckets > SMSTACKSIZE) {
|
||||
sh->buckets = MEM_mallocN(sizeof(*sh->buckets) * sh->nbuckets, __func__);
|
||||
}
|
||||
}
|
||||
|
||||
smallhash_init_empty(sh);
|
||||
}
|
||||
|
||||
void BLI_smallhash_init(SmallHash *sh)
|
||||
{
|
||||
BLI_smallhash_init_ex(sh, 0);
|
||||
}
|
||||
|
||||
void BLI_smallhash_release(SmallHash *sh)
|
||||
{
|
||||
if (sh->buckets != sh->buckets_stack) {
|
||||
MEM_freeN(sh->buckets);
|
||||
}
|
||||
}
|
||||
|
||||
void BLI_smallhash_insert(SmallHash *sh, uintptr_t key, void *item)
|
||||
{
|
||||
SmallHashEntry *e;
|
||||
|
||||
BLI_assert(key != SMHASH_KEY_UNUSED);
|
||||
BLI_assert(smallhash_val_is_used(item));
|
||||
BLI_assert(BLI_smallhash_haskey(sh, key) == false);
|
||||
|
||||
if (UNLIKELY(smallhash_test_expand_buckets(++sh->nentries, sh->nbuckets))) {
|
||||
smallhash_resize_buckets(sh, hashsizes[++sh->cursize]);
|
||||
}
|
||||
|
||||
e = smallhash_lookup_first_free(sh, key);
|
||||
e->key = key;
|
||||
e->val = item;
|
||||
}
|
||||
|
||||
bool BLI_smallhash_reinsert(SmallHash *sh, uintptr_t key, void *item)
|
||||
{
|
||||
SmallHashEntry *e = smallhash_lookup(sh, key);
|
||||
if (e) {
|
||||
e->val = item;
|
||||
return false;
|
||||
}
|
||||
|
||||
BLI_smallhash_insert(sh, key, item);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE_REMOVE
|
||||
bool BLI_smallhash_remove(SmallHash *sh, uintptr_t key)
|
||||
{
|
||||
SmallHashEntry *e = smallhash_lookup(sh, key);
|
||||
|
||||
if (e) {
|
||||
e->key = SMHASH_KEY_UNUSED;
|
||||
e->val = SMHASH_CELL_UNUSED;
|
||||
sh->nentries--;
|
||||
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void *BLI_smallhash_lookup(const SmallHash *sh, uintptr_t key)
|
||||
{
|
||||
SmallHashEntry *e = smallhash_lookup(sh, key);
|
||||
|
||||
return e ? e->val : NULL;
|
||||
}
|
||||
|
||||
void **BLI_smallhash_lookup_p(const SmallHash *sh, uintptr_t key)
|
||||
{
|
||||
SmallHashEntry *e = smallhash_lookup(sh, key);
|
||||
|
||||
return e ? &e->val : NULL;
|
||||
}
|
||||
|
||||
bool BLI_smallhash_haskey(const SmallHash *sh, uintptr_t key)
|
||||
{
|
||||
SmallHashEntry *e = smallhash_lookup(sh, key);
|
||||
|
||||
return (e != NULL);
|
||||
}
|
||||
|
||||
int BLI_smallhash_len(const SmallHash *sh)
|
||||
{
|
||||
return (int)sh->nentries;
|
||||
}
|
||||
|
||||
BLI_INLINE SmallHashEntry *smallhash_iternext(SmallHashIter *iter, uintptr_t *key)
|
||||
{
|
||||
while (iter->i < iter->sh->nbuckets) {
|
||||
if (smallhash_val_is_used(iter->sh->buckets[iter->i].val)) {
|
||||
if (key) {
|
||||
*key = iter->sh->buckets[iter->i].key;
|
||||
}
|
||||
|
||||
return &iter->sh->buckets[iter->i++];
|
||||
}
|
||||
|
||||
iter->i++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key)
|
||||
{
|
||||
SmallHashEntry *e = smallhash_iternext(iter, key);
|
||||
|
||||
return e ? e->val : NULL;
|
||||
}
|
||||
|
||||
void **BLI_smallhash_iternext_p(SmallHashIter *iter, uintptr_t *key)
|
||||
{
|
||||
SmallHashEntry *e = smallhash_iternext(iter, key);
|
||||
|
||||
return e ? &e->val : NULL;
|
||||
}
|
||||
|
||||
void *BLI_smallhash_iternew(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
|
||||
{
|
||||
iter->sh = sh;
|
||||
iter->i = 0;
|
||||
|
||||
return BLI_smallhash_iternext(iter, key);
|
||||
}
|
||||
|
||||
void **BLI_smallhash_iternew_p(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
|
||||
{
|
||||
iter->sh = sh;
|
||||
iter->i = 0;
|
||||
|
||||
return BLI_smallhash_iternext_p(iter, key);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Debugging & Introspection
|
||||
* \{ */
|
||||
|
||||
/* NOTE(@ideasman42): useful for debugging but may not be intended for general use. */
|
||||
#if 0
|
||||
void BLI_smallhash_print(SmallHash *sh)
|
||||
{
|
||||
uint i, linecol = 79, c = 0;
|
||||
|
||||
printf("{");
|
||||
for (i = 0; i < sh->nbuckets; i++) {
|
||||
if (sh->buckets[i].val == SMHASH_CELL_UNUSED) {
|
||||
printf("--u-");
|
||||
}
|
||||
else if (sh->buckets[i].val == SMHASH_CELL_FREE) {
|
||||
printf("--f-");
|
||||
}
|
||||
else {
|
||||
printf("%2x", (uint)sh->buckets[i].key);
|
||||
}
|
||||
|
||||
if (i != sh->nbuckets - 1) {
|
||||
printf(", ");
|
||||
}
|
||||
|
||||
c += 6;
|
||||
|
||||
if (c >= linecol) {
|
||||
printf("\n ");
|
||||
c = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
double BLI_smallhash_calc_quality(SmallHash *sh)
|
||||
{
|
||||
uint64_t sum = 0;
|
||||
uint i;
|
||||
|
||||
if (sh->nentries == 0) {
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
for (i = 0; i < sh->nbuckets; i++) {
|
||||
if (sh->buckets[i].key != SMHASH_KEY_UNUSED) {
|
||||
uint64_t count = 0;
|
||||
SmallHashEntry *e, *e_final = &sh->buckets[i];
|
||||
uint h = smallhash_key(e_final->key);
|
||||
uint hoff = 1;
|
||||
|
||||
for (e = &sh->buckets[h % sh->nbuckets]; e != e_final;
|
||||
h = SMHASH_NEXT(h, hoff), e = &sh->buckets[h % sh->nbuckets])
|
||||
{
|
||||
count += 1;
|
||||
}
|
||||
|
||||
sum += count;
|
||||
}
|
||||
}
|
||||
return ((double)(sh->nentries + sum) / (double)sh->nentries);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** \} */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue