Merge branch 'master' into asset-browser-grid-view
This commit is contained in:
commit
9bac0894f6
|
@ -79,4 +79,6 @@ mark_as_advanced(
|
|||
|
||||
unset(_ffmpeg_SEARCH_DIRS)
|
||||
unset(_ffmpeg_LIBRARIES)
|
||||
unset(_ffmpeg_INCLUDE_DIR)
|
||||
# In cmake version 3.21 and up, we can instead use the NO_CACHE option for
|
||||
# find_path so we don't need to clear it from the cache here.
|
||||
unset(_ffmpeg_INCLUDE_DIR CACHE)
|
||||
|
|
|
@ -72,6 +72,7 @@ FIND_PATH(OSL_SHADER_DIR
|
|||
/usr/include/OSL/
|
||||
PATH_SUFFIXES
|
||||
share/OSL/shaders
|
||||
shaders
|
||||
)
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set OSL_FOUND to TRUE if
|
||||
|
@ -95,6 +96,7 @@ ENDIF()
|
|||
|
||||
MARK_AS_ADVANCED(
|
||||
OSL_INCLUDE_DIR
|
||||
OSL_SHADER_DIR
|
||||
)
|
||||
FOREACH(COMPONENT ${_osl_FIND_COMPONENTS})
|
||||
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
|
||||
|
|
|
@ -83,12 +83,14 @@ ENDIF()
|
|||
MARK_AS_ADVANCED(
|
||||
OPENCOLORIO_INCLUDE_DIR
|
||||
OPENCOLORIO_LIBRARY
|
||||
OPENCOLORIO_OPENCOLORIO_LIBRARY
|
||||
OPENCOLORIO_TINYXML_LIBRARY
|
||||
OPENCOLORIO_YAML-CPP_LIBRARY
|
||||
OPENCOLORIO_VERSION
|
||||
)
|
||||
|
||||
FOREACH(COMPONENT ${_opencolorio_FIND_COMPONENTS})
|
||||
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
|
||||
MARK_AS_ADVANCED(OPENCOLORIO_${UPPERCOMPONENT}_LIBRARY)
|
||||
ENDFOREACH()
|
||||
|
||||
UNSET(COMPONENT)
|
||||
UNSET(UPPERCOMPONENT)
|
||||
UNSET(_opencolorio_FIND_COMPONENTS)
|
||||
|
|
|
@ -29,14 +29,6 @@ ENDIF()
|
|||
# Old versions (before 2.0?) do not have any version string, just assuming this should be fine though.
|
||||
SET(_openexr_libs_ver_init "2.0")
|
||||
|
||||
SET(_openexr_FIND_COMPONENTS
|
||||
Half
|
||||
Iex
|
||||
IlmImf
|
||||
IlmThread
|
||||
Imath
|
||||
)
|
||||
|
||||
SET(_openexr_SEARCH_DIRS
|
||||
${OPENEXR_ROOT_DIR}
|
||||
/opt/lib/openexr
|
||||
|
@ -89,6 +81,24 @@ UNSET(_openexr_libs_ver_init)
|
|||
|
||||
STRING(REGEX REPLACE "([0-9]+)[.]([0-9]+).*" "\\1_\\2" _openexr_libs_ver ${OPENEXR_VERSION})
|
||||
|
||||
# Different library names in 3.0, and Imath and Half moved out.
|
||||
IF(OPENEXR_VERSION VERSION_GREATER_EQUAL "3.0.0")
|
||||
SET(_openexr_FIND_COMPONENTS
|
||||
Iex
|
||||
IlmThread
|
||||
OpenEXR
|
||||
OpenEXRCore
|
||||
)
|
||||
ELSE()
|
||||
SET(_openexr_FIND_COMPONENTS
|
||||
Half
|
||||
Iex
|
||||
IlmImf
|
||||
IlmThread
|
||||
Imath
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
SET(_openexr_LIBRARIES)
|
||||
FOREACH(COMPONENT ${_openexr_FIND_COMPONENTS})
|
||||
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
|
||||
|
@ -107,6 +117,57 @@ ENDFOREACH()
|
|||
|
||||
UNSET(_openexr_libs_ver)
|
||||
|
||||
IF(OPENEXR_VERSION VERSION_GREATER_EQUAL "3.0.0")
|
||||
# For OpenEXR 3.x, we also need to find the now separate Imath library.
|
||||
# For simplicity we add it to the OpenEXR includes and libraries, as we
|
||||
# have no direct dependency on Imath and it's simpler to support both
|
||||
# 2.x and 3.x this way.
|
||||
|
||||
# Find include directory
|
||||
FIND_PATH(IMATH_INCLUDE_DIR
|
||||
NAMES
|
||||
Imath/ImathMath.h
|
||||
HINTS
|
||||
${_openexr_SEARCH_DIRS}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
)
|
||||
|
||||
# Find version
|
||||
FIND_FILE(_imath_config
|
||||
NAMES
|
||||
ImathConfig.h
|
||||
PATHS
|
||||
${IMATH_INCLUDE_DIR}/Imath
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
# Find line with version, extract string, and format for library suffix.
|
||||
FILE(STRINGS "${_imath_config}" _imath_build_specification
|
||||
REGEX "^[ \t]*#define[ \t]+IMATH_VERSION_STRING[ \t]+\"[.0-9]+\".*$")
|
||||
STRING(REGEX REPLACE ".*#define[ \t]+IMATH_VERSION_STRING[ \t]+\"([.0-9]+)\".*"
|
||||
"\\1" _imath_libs_ver ${_imath_build_specification})
|
||||
STRING(REGEX REPLACE "([0-9]+)[.]([0-9]+).*" "\\1_\\2" _imath_libs_ver ${_imath_libs_ver})
|
||||
|
||||
# Find library, with or without version number.
|
||||
FIND_LIBRARY(IMATH_LIBRARY
|
||||
NAMES
|
||||
Imath-${_imath_libs_ver} Imath
|
||||
NAMES_PER_DIR
|
||||
HINTS
|
||||
${_openexr_SEARCH_DIRS}
|
||||
PATH_SUFFIXES
|
||||
lib64 lib
|
||||
)
|
||||
LIST(APPEND _openexr_LIBRARIES "${IMATH_LIBRARY}")
|
||||
|
||||
# In cmake version 3.21 and up, we can instead use the NO_CACHE option for
|
||||
# FIND_FILE so we don't need to clear it from the cache here.
|
||||
UNSET(_imath_config CACHE)
|
||||
UNSET(_imath_libs_ver)
|
||||
UNSET(_imath_build_specification)
|
||||
ENDIF()
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set OPENEXR_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
|
@ -115,13 +176,25 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenEXR DEFAULT_MSG
|
|||
|
||||
IF(OPENEXR_FOUND)
|
||||
SET(OPENEXR_LIBRARIES ${_openexr_LIBRARIES})
|
||||
# Both include paths are needed because of dummy OSL headers mixing #include <OpenEXR/foo.h> and #include <foo.h> :(
|
||||
SET(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR} ${OPENEXR_INCLUDE_DIR}/OpenEXR)
|
||||
# Both include paths are needed because of dummy OSL headers mixing
|
||||
# #include <OpenEXR/foo.h> and #include <foo.h>, as well as Alembic
|
||||
# include <half.h> directly.
|
||||
SET(OPENEXR_INCLUDE_DIRS
|
||||
${OPENEXR_INCLUDE_DIR}
|
||||
${OPENEXR_INCLUDE_DIR}/OpenEXR)
|
||||
|
||||
IF(OPENEXR_VERSION VERSION_GREATER_EQUAL "3.0.0")
|
||||
LIST(APPEND OPENEXR_INCLUDE_DIRS
|
||||
${IMATH_INCLUDE_DIR}
|
||||
${IMATH_INCLUDE_DIR}/Imath)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
OPENEXR_INCLUDE_DIR
|
||||
OPENEXR_VERSION
|
||||
IMATH_INCLUDE_DIR
|
||||
IMATH_LIBRARY
|
||||
)
|
||||
FOREACH(COMPONENT ${_openexr_FIND_COMPONENTS})
|
||||
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
|
||||
|
|
|
@ -106,6 +106,7 @@ ENDIF()
|
|||
|
||||
MARK_AS_ADVANCED(
|
||||
OPENIMAGEDENOISE_INCLUDE_DIR
|
||||
OPENIMAGEDENOISE_LIBRARY
|
||||
)
|
||||
|
||||
FOREACH(COMPONENT ${_openimagedenoise_FIND_COMPONENTS})
|
||||
|
|
|
@ -44,6 +44,8 @@ FIND_LIBRARY(OPENIMAGEIO_LIBRARY
|
|||
lib64 lib
|
||||
)
|
||||
|
||||
set(_openimageio_LIBRARIES ${OPENIMAGEIO_LIBRARY})
|
||||
|
||||
FIND_FILE(OPENIMAGEIO_IDIFF
|
||||
NAMES
|
||||
idiff
|
||||
|
@ -53,14 +55,47 @@ FIND_FILE(OPENIMAGEIO_IDIFF
|
|||
bin
|
||||
)
|
||||
|
||||
# Additionally find util library if needed. In old versions this library was
|
||||
# included in libOpenImageIO and linking to both would duplicate symbols. In
|
||||
# new versions we need to link to both.
|
||||
FIND_FILE(_openimageio_export
|
||||
NAMES
|
||||
export.h
|
||||
PATHS
|
||||
${OPENIMAGEIO_INCLUDE_DIR}/OpenImageIO
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
# Use existence of OIIO_UTIL_API to check if it's a separate lib.
|
||||
FILE(STRINGS "${_openimageio_export}" _openimageio_util_define
|
||||
REGEX "^[ \t]*#[ \t]*define[ \t]+OIIO_UTIL_API.*$")
|
||||
|
||||
IF(_openimageio_util_define)
|
||||
FIND_LIBRARY(OPENIMAGEIO_UTIL_LIBRARY
|
||||
NAMES
|
||||
OpenImageIO_Util
|
||||
HINTS
|
||||
${_openimageio_SEARCH_DIRS}
|
||||
PATH_SUFFIXES
|
||||
lib64 lib
|
||||
)
|
||||
|
||||
LIST(APPEND _openimageio_LIBRARIES ${OPENIMAGEIO_UTIL_LIBRARY})
|
||||
ENDIF()
|
||||
|
||||
# In cmake version 3.21 and up, we can instead use the NO_CACHE option for
|
||||
# FIND_FILE so we don't need to clear it from the cache here.
|
||||
UNSET(_openimageio_export CACHE)
|
||||
UNSET(_openimageio_util_define)
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set OPENIMAGEIO_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenImageIO DEFAULT_MSG
|
||||
OPENIMAGEIO_LIBRARY OPENIMAGEIO_INCLUDE_DIR)
|
||||
_openimageio_LIBRARIES OPENIMAGEIO_INCLUDE_DIR)
|
||||
|
||||
IF(OPENIMAGEIO_FOUND)
|
||||
SET(OPENIMAGEIO_LIBRARIES ${OPENIMAGEIO_LIBRARY})
|
||||
SET(OPENIMAGEIO_LIBRARIES ${_openimageio_LIBRARIES})
|
||||
SET(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO_INCLUDE_DIR})
|
||||
IF(EXISTS ${OPENIMAGEIO_INCLUDE_DIR}/OpenImageIO/pugixml.hpp)
|
||||
SET(OPENIMAGEIO_PUGIXML_FOUND TRUE)
|
||||
|
@ -74,7 +109,9 @@ ENDIF()
|
|||
MARK_AS_ADVANCED(
|
||||
OPENIMAGEIO_INCLUDE_DIR
|
||||
OPENIMAGEIO_LIBRARY
|
||||
OPENIMAGEIO_UTIL_LIBRARY
|
||||
OPENIMAGEIO_IDIFF
|
||||
)
|
||||
|
||||
UNSET(_openimageio_SEARCH_DIRS)
|
||||
UNSET(_openimageio_LIBRARIES)
|
||||
|
|
|
@ -345,6 +345,7 @@ if(WITH_BOOST)
|
|||
find_package(IcuLinux)
|
||||
endif()
|
||||
mark_as_advanced(Boost_DIR) # why doesn't boost do this?
|
||||
mark_as_advanced(Boost_INCLUDE_DIR) # why doesn't boost do this?
|
||||
endif()
|
||||
|
||||
set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS})
|
||||
|
|
|
@ -32,7 +32,8 @@ typedef map<string, ConvertNode *> ProxyMap;
|
|||
|
||||
void BlenderSync::find_shader(BL::ID &id, array<Node *> &used_shaders, Shader *default_shader)
|
||||
{
|
||||
Shader *shader = (id) ? shader_map.find(id) : default_shader;
|
||||
Shader *synced_shader = (id) ? shader_map.find(id) : nullptr;
|
||||
Shader *shader = (synced_shader) ? synced_shader : default_shader;
|
||||
|
||||
used_shaders.push_back_slow(shader);
|
||||
shader->tag_used(scene);
|
||||
|
|
|
@ -817,28 +817,28 @@ void ShaderManager::init_xyz_transforms()
|
|||
Transform xyz_to_rgb;
|
||||
|
||||
if (config->hasRole("aces_interchange")) {
|
||||
/* Standard OpenColorIO role, defined as ACES2065-1. */
|
||||
const Transform xyz_E_to_aces = make_transform(1.0498110175f,
|
||||
0.0f,
|
||||
-0.0000974845f,
|
||||
0.0f,
|
||||
-0.4959030231f,
|
||||
1.3733130458f,
|
||||
0.0982400361f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.9912520182f,
|
||||
0.0f);
|
||||
const Transform xyz_D65_to_E = make_transform(
|
||||
1.0521111f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.9184170f, 0.0f);
|
||||
|
||||
/* Standard OpenColorIO role, defined as ACES AP0 (ACES2065-1). */
|
||||
Transform aces_to_rgb;
|
||||
if (!to_scene_linear_transform(config, "aces_interchange", aces_to_rgb)) {
|
||||
return;
|
||||
}
|
||||
|
||||
xyz_to_rgb = aces_to_rgb * xyz_E_to_aces * xyz_D65_to_E;
|
||||
/* This is the OpenColorIO builtin transform:
|
||||
* UTILITY - ACES-AP0_to_CIE-XYZ-D65_BFD. */
|
||||
const Transform ACES_AP0_to_xyz_D65 = make_transform(0.938280f,
|
||||
-0.004451f,
|
||||
0.016628f,
|
||||
0.000000f,
|
||||
0.337369f,
|
||||
0.729522f,
|
||||
-0.066890f,
|
||||
0.000000f,
|
||||
0.001174f,
|
||||
-0.003711f,
|
||||
1.091595f,
|
||||
0.000000f);
|
||||
const Transform xyz_to_aces = transform_inverse(ACES_AP0_to_xyz_D65);
|
||||
xyz_to_rgb = aces_to_rgb * xyz_to_aces;
|
||||
}
|
||||
else if (config->hasRole("XYZ")) {
|
||||
/* Custom role used before the standard existed. */
|
||||
|
|
|
@ -110,9 +110,11 @@ class GHOST_SharedOpenGLResource {
|
|||
struct SharedData {
|
||||
HANDLE device;
|
||||
GLuint fbo;
|
||||
HANDLE render_buf{nullptr};
|
||||
HANDLE render_target{nullptr};
|
||||
} m_shared;
|
||||
|
||||
enum RenderTarget { TARGET_RENDERBUF, TARGET_TEX2D };
|
||||
|
||||
public:
|
||||
GHOST_SharedOpenGLResource(ID3D11Device *device,
|
||||
ID3D11DeviceContext *device_ctx,
|
||||
|
@ -179,37 +181,64 @@ class GHOST_SharedOpenGLResource {
|
|||
}
|
||||
|
||||
if (m_is_initialized) {
|
||||
if (m_shared.render_buf) {
|
||||
wglDXUnregisterObjectNV(m_shared.device, m_shared.render_buf);
|
||||
if (m_shared.render_target
|
||||
#if 1
|
||||
/* TODO: #wglDXUnregisterObjectNV() causes an access violation on AMD when the shared
|
||||
* resource is a GL texture. Since there is currently no good alternative, just skip
|
||||
* unregistering the shared resource. */
|
||||
&& !m_use_gl_texture2d
|
||||
#endif
|
||||
) {
|
||||
wglDXUnregisterObjectNV(m_shared.device, m_shared.render_target);
|
||||
}
|
||||
if (m_shared.device) {
|
||||
wglDXCloseDeviceNV(m_shared.device);
|
||||
}
|
||||
glDeleteFramebuffers(1, &m_shared.fbo);
|
||||
glDeleteRenderbuffers(1, &m_gl_render_buf);
|
||||
if (m_use_gl_texture2d) {
|
||||
glDeleteTextures(1, &m_gl_render_target);
|
||||
}
|
||||
else {
|
||||
glDeleteRenderbuffers(1, &m_gl_render_target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void reregisterSharedObject()
|
||||
/* Returns true if the shared object was successfully registered, false otherwise. */
|
||||
bool reregisterSharedObject(RenderTarget target)
|
||||
{
|
||||
if (m_shared.render_buf) {
|
||||
wglDXUnregisterObjectNV(m_shared.device, m_shared.render_buf);
|
||||
if (m_shared.render_target) {
|
||||
wglDXUnregisterObjectNV(m_shared.device, m_shared.render_target);
|
||||
}
|
||||
|
||||
if (!m_render_target_tex) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_shared.render_buf = wglDXRegisterObjectNV(m_shared.device,
|
||||
m_render_target_tex,
|
||||
m_gl_render_buf,
|
||||
GL_RENDERBUFFER,
|
||||
WGL_ACCESS_READ_WRITE_NV);
|
||||
if (target == TARGET_TEX2D) {
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RGBA8,
|
||||
m_cur_width,
|
||||
m_cur_height,
|
||||
0,
|
||||
GL_RGBA,
|
||||
GL_UNSIGNED_BYTE,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
if (!m_shared.render_buf) {
|
||||
m_shared.render_target = wglDXRegisterObjectNV(m_shared.device,
|
||||
m_render_target_tex,
|
||||
m_gl_render_target,
|
||||
(target == TARGET_TEX2D) ? GL_TEXTURE_2D :
|
||||
GL_RENDERBUFFER,
|
||||
WGL_ACCESS_READ_WRITE_NV);
|
||||
if (!m_shared.render_target) {
|
||||
fprintf(stderr, "Error registering shared object using wglDXRegisterObjectNV()\n");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GHOST_TSuccess initialize()
|
||||
|
@ -221,16 +250,33 @@ class GHOST_SharedOpenGLResource {
|
|||
}
|
||||
|
||||
/* Build the renderbuffer. */
|
||||
glGenRenderbuffers(1, &m_gl_render_buf);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_gl_render_buf);
|
||||
glGenRenderbuffers(1, &m_gl_render_target);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_gl_render_target);
|
||||
|
||||
reregisterSharedObject();
|
||||
if (!reregisterSharedObject(TARGET_RENDERBUF)) {
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
if (m_gl_render_target) {
|
||||
glDeleteRenderbuffers(1, &m_gl_render_target);
|
||||
}
|
||||
/* Fall back to texture 2d. */
|
||||
m_use_gl_texture2d = true;
|
||||
glGenTextures(1, &m_gl_render_target);
|
||||
glBindTexture(GL_TEXTURE_2D, m_gl_render_target);
|
||||
|
||||
reregisterSharedObject(TARGET_TEX2D);
|
||||
}
|
||||
|
||||
/* Build the framebuffer */
|
||||
glGenFramebuffers(1, &m_shared.fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_shared.fbo);
|
||||
glFramebufferRenderbuffer(
|
||||
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_gl_render_buf);
|
||||
if (m_use_gl_texture2d) {
|
||||
glFramebufferTexture2D(
|
||||
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_gl_render_target, 0);
|
||||
}
|
||||
else {
|
||||
glFramebufferRenderbuffer(
|
||||
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_gl_render_target);
|
||||
}
|
||||
m_is_initialized = true;
|
||||
|
||||
return GHOST_kSuccess;
|
||||
|
@ -245,7 +291,7 @@ class GHOST_SharedOpenGLResource {
|
|||
if ((m_cur_width != width) || (m_cur_height != height)) {
|
||||
m_cur_width = width;
|
||||
m_cur_height = height;
|
||||
reregisterSharedObject();
|
||||
reregisterSharedObject(m_use_gl_texture2d ? TARGET_TEX2D : TARGET_RENDERBUF);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,18 +339,19 @@ class GHOST_SharedOpenGLResource {
|
|||
private:
|
||||
void beginGLOnly()
|
||||
{
|
||||
wglDXLockObjectsNV(m_shared.device, 1, &m_shared.render_buf);
|
||||
wglDXLockObjectsNV(m_shared.device, 1, &m_shared.render_target);
|
||||
}
|
||||
void endGLOnly()
|
||||
{
|
||||
wglDXUnlockObjectsNV(m_shared.device, 1, &m_shared.render_buf);
|
||||
wglDXUnlockObjectsNV(m_shared.device, 1, &m_shared.render_target);
|
||||
}
|
||||
|
||||
ID3D11Device *m_device;
|
||||
ID3D11DeviceContext *m_device_ctx;
|
||||
GLuint m_gl_render_buf;
|
||||
GLuint m_gl_render_target;
|
||||
unsigned int m_cur_width, m_cur_height;
|
||||
bool m_is_initialized{false};
|
||||
bool m_use_gl_texture2d{false};
|
||||
};
|
||||
|
||||
GHOST_SharedOpenGLResource *GHOST_ContextD3D::createSharedOpenGLResource(
|
||||
|
|
|
@ -7,6 +7,7 @@ set(INC
|
|||
../guardedalloc
|
||||
../../source/blender/blenlib
|
||||
../../source/blender/gpu
|
||||
../../source/blender/gpu/intern
|
||||
../../source/blender/makesdna
|
||||
)
|
||||
|
||||
|
@ -20,6 +21,7 @@ set(SRC
|
|||
|
||||
ocio_capi.h
|
||||
ocio_impl.h
|
||||
ocio_shader_shared.hh
|
||||
)
|
||||
|
||||
set(LIB
|
||||
|
@ -56,8 +58,38 @@ if(WITH_OPENCOLORIO)
|
|||
)
|
||||
endif()
|
||||
|
||||
data_to_c_simple(gpu_shader_display_transform.glsl SRC)
|
||||
data_to_c_simple(gpu_shader_display_transform_vertex.glsl SRC)
|
||||
set(GLSL_SRC
|
||||
gpu_shader_display_transform_vert.glsl
|
||||
gpu_shader_display_transform_frag.glsl
|
||||
|
||||
ocio_shader_shared.hh
|
||||
)
|
||||
|
||||
set(GLSL_C)
|
||||
foreach(GLSL_FILE ${GLSL_SRC})
|
||||
data_to_c_simple(${GLSL_FILE} GLSL_C)
|
||||
endforeach()
|
||||
|
||||
blender_add_lib(bf_ocio_shaders "${GLSL_C}" "" "" "")
|
||||
|
||||
list(APPEND LIB
|
||||
bf_ocio_shaders
|
||||
)
|
||||
|
||||
set(GLSL_SOURCE_CONTENT "")
|
||||
foreach(GLSL_FILE ${GLSL_SRC})
|
||||
get_filename_component(GLSL_FILE_NAME ${GLSL_FILE} NAME)
|
||||
string(REPLACE "." "_" GLSL_FILE_NAME_UNDERSCORES ${GLSL_FILE_NAME})
|
||||
string(APPEND GLSL_SOURCE_CONTENT "SHADER_SOURCE\(datatoc_${GLSL_FILE_NAME_UNDERSCORES}, \"${GLSL_FILE_NAME}\", \"${GLSL_FILE}\"\)\n")
|
||||
endforeach()
|
||||
|
||||
set(glsl_source_list_file "${CMAKE_CURRENT_BINARY_DIR}/glsl_ocio_source_list.h")
|
||||
file(GENERATE OUTPUT ${glsl_source_list_file} CONTENT "${GLSL_SOURCE_CONTENT}")
|
||||
list(APPEND SRC ${glsl_source_list_file})
|
||||
list(APPEND INC ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
target_include_directories(bf_ocio_shaders PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
endif()
|
||||
|
||||
|
||||
|
|
|
@ -1,39 +1,10 @@
|
|||
/* Blender OpenColorIO implementation */
|
||||
|
||||
uniform sampler2D image_texture;
|
||||
uniform sampler2D overlay_texture;
|
||||
|
||||
uniform float dither;
|
||||
uniform float scale;
|
||||
uniform float exponent;
|
||||
uniform bool predivide;
|
||||
uniform bool overlay;
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Curve Mapping Implementation
|
||||
* \{ */
|
||||
|
||||
#ifdef USE_CURVE_MAPPING
|
||||
uniform sampler1D curve_mapping_texture;
|
||||
|
||||
layout(std140) uniform OCIO_GPUCurveMappingParameters
|
||||
{
|
||||
/* Curve mapping parameters
|
||||
*
|
||||
* See documentation for OCIO_CurveMappingSettings to get fields descriptions.
|
||||
* (this ones pretty much copies stuff from C structure.)
|
||||
*/
|
||||
vec4 curve_mapping_mintable;
|
||||
vec4 curve_mapping_range;
|
||||
vec4 curve_mapping_ext_in_x;
|
||||
vec4 curve_mapping_ext_in_y;
|
||||
vec4 curve_mapping_ext_out_x;
|
||||
vec4 curve_mapping_ext_out_y;
|
||||
vec4 curve_mapping_first_x;
|
||||
vec4 curve_mapping_first_y;
|
||||
vec4 curve_mapping_last_x;
|
||||
vec4 curve_mapping_last_y;
|
||||
vec4 curve_mapping_black;
|
||||
vec4 curve_mapping_bwmul;
|
||||
int curve_mapping_lut_size;
|
||||
int curve_mapping_use_extend_extrapolate;
|
||||
};
|
||||
|
||||
float read_curve_mapping(int table, int index)
|
||||
{
|
||||
|
@ -43,27 +14,27 @@ float read_curve_mapping(int table, int index)
|
|||
float curvemap_calc_extend(int table, float x, vec2 first, vec2 last)
|
||||
{
|
||||
if (x <= first[0]) {
|
||||
if (curve_mapping_use_extend_extrapolate == 0) {
|
||||
if (curve_mapping.use_extend_extrapolate == 0) {
|
||||
/* horizontal extrapolation */
|
||||
return first[1];
|
||||
}
|
||||
else {
|
||||
float fac = (curve_mapping_ext_in_x[table] != 0.0) ?
|
||||
((x - first[0]) / curve_mapping_ext_in_x[table]) :
|
||||
float fac = (curve_mapping.ext_in_x[table] != 0.0) ?
|
||||
((x - first[0]) / curve_mapping.ext_in_x[table]) :
|
||||
10000.0;
|
||||
return first[1] + curve_mapping_ext_in_y[table] * fac;
|
||||
return first[1] + curve_mapping.ext_in_y[table] * fac;
|
||||
}
|
||||
}
|
||||
else if (x >= last[0]) {
|
||||
if (curve_mapping_use_extend_extrapolate == 0) {
|
||||
if (curve_mapping.use_extend_extrapolate == 0) {
|
||||
/* horizontal extrapolation */
|
||||
return last[1];
|
||||
}
|
||||
else {
|
||||
float fac = (curve_mapping_ext_out_x[table] != 0.0) ?
|
||||
((x - last[0]) / curve_mapping_ext_out_x[table]) :
|
||||
float fac = (curve_mapping.ext_out_x[table] != 0.0) ?
|
||||
((x - last[0]) / curve_mapping.ext_out_x[table]) :
|
||||
-10000.0;
|
||||
return last[1] + curve_mapping_ext_out_y[table] * fac;
|
||||
return last[1] + curve_mapping.ext_out_y[table] * fac;
|
||||
}
|
||||
}
|
||||
return 0.0;
|
||||
|
@ -71,10 +42,10 @@ float curvemap_calc_extend(int table, float x, vec2 first, vec2 last)
|
|||
|
||||
float curvemap_evaluateF(int table, float value)
|
||||
{
|
||||
float mintable_ = curve_mapping_mintable[table];
|
||||
float range = curve_mapping_range[table];
|
||||
float mintable_ = curve_mapping.mintable[table];
|
||||
float range = curve_mapping.range[table];
|
||||
float mintable = 0.0;
|
||||
int CM_TABLE = curve_mapping_lut_size - 1;
|
||||
int CM_TABLE = curve_mapping.lut_size - 1;
|
||||
|
||||
float fi;
|
||||
int i;
|
||||
|
@ -87,8 +58,8 @@ float curvemap_evaluateF(int table, float value)
|
|||
if (fi < 0.0 || fi > float(CM_TABLE)) {
|
||||
return curvemap_calc_extend(table,
|
||||
value,
|
||||
vec2(curve_mapping_first_x[table], curve_mapping_first_y[table]),
|
||||
vec2(curve_mapping_last_x[table], curve_mapping_last_y[table]));
|
||||
vec2(curve_mapping.first_x[table], curve_mapping.first_y[table]),
|
||||
vec2(curve_mapping.last_x[table], curve_mapping.last_y[table]));
|
||||
}
|
||||
else {
|
||||
if (i < 0) {
|
||||
|
@ -106,7 +77,7 @@ float curvemap_evaluateF(int table, float value)
|
|||
|
||||
vec4 curvemapping_evaluate_premulRGBF(vec4 col)
|
||||
{
|
||||
col.rgb = (col.rgb - curve_mapping_black.rgb) * curve_mapping_bwmul.rgb;
|
||||
col.rgb = (col.rgb - curve_mapping.black.rgb) * curve_mapping.bwmul.rgb;
|
||||
|
||||
vec4 result;
|
||||
result.r = curvemap_evaluateF(0, col.r);
|
||||
|
@ -115,8 +86,15 @@ vec4 curvemapping_evaluate_premulRGBF(vec4 col)
|
|||
result.a = col.a;
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* USE_CURVE_MAPPING */
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Dithering
|
||||
* \{ */
|
||||
|
||||
/* Using a triangle distribution which gives a more final uniform noise.
|
||||
* See Banding in Games:A Noisy Rant(revision 5) Mikkel Gjøl, Playdead (slide 27) */
|
||||
/* GPUs are rounding before writing to framebuffer so we center the distribution around 0.0. */
|
||||
|
@ -135,23 +113,33 @@ float dither_random_value(vec2 co)
|
|||
|
||||
vec2 round_to_pixel(sampler2D tex, vec2 uv)
|
||||
{
|
||||
vec2 size = textureSize(tex, 0);
|
||||
return vec2(ivec2(uv * size)) / size;
|
||||
vec2 size = vec2(textureSize(tex, 0));
|
||||
return floor(uv * size) / size;
|
||||
}
|
||||
|
||||
vec4 apply_dither(vec4 col, vec2 uv)
|
||||
{
|
||||
col.rgb += dither_random_value(uv) * 0.0033 * dither;
|
||||
col.rgb += dither_random_value(uv) * 0.0033 * parameters.dither;
|
||||
return col;
|
||||
}
|
||||
|
||||
vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay, vec2 noise_uv)
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Main Processing
|
||||
* \{ */
|
||||
|
||||
/* Prototypes: Implementation is generaterd and defined after. */
|
||||
vec4 OCIO_to_scene_linear(vec4 pixel);
|
||||
vec4 OCIO_to_display(vec4 pixel);
|
||||
|
||||
vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay)
|
||||
{
|
||||
#ifdef USE_CURVE_MAPPING
|
||||
col = curvemapping_evaluate_premulRGBF(col);
|
||||
#endif
|
||||
|
||||
if (predivide) {
|
||||
if (parameters.use_predivide) {
|
||||
if (col.a > 0.0 && col.a < 1.0) {
|
||||
col.rgb *= 1.0 / col.a;
|
||||
}
|
||||
|
@ -166,7 +154,7 @@ vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay, vec2 noise_uv)
|
|||
col = OCIO_to_scene_linear(col);
|
||||
|
||||
/* Apply exposure in scene linear. */
|
||||
col.rgb *= scale;
|
||||
col.rgb *= parameters.scale;
|
||||
|
||||
/* Convert to display space. */
|
||||
col = OCIO_to_display(col);
|
||||
|
@ -177,34 +165,31 @@ vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay, vec2 noise_uv)
|
|||
* i.e: The linear color space w.r.t. display chromaticity and radiometry.
|
||||
* We separate the colormanagement process into two steps to be able to
|
||||
* merge UI using alpha blending in the correct color space. */
|
||||
if (overlay) {
|
||||
col.rgb = pow(col.rgb, vec3(exponent * 2.2));
|
||||
if (parameters.use_overlay) {
|
||||
col.rgb = pow(col.rgb, vec3(parameters.exponent * 2.2));
|
||||
col = clamp(col, 0.0, 1.0);
|
||||
col *= 1.0 - col_overlay.a;
|
||||
col += col_overlay; /* Assumed unassociated alpha. */
|
||||
col.rgb = pow(col.rgb, vec3(1.0 / 2.2));
|
||||
}
|
||||
else {
|
||||
col.rgb = pow(col.rgb, vec3(exponent));
|
||||
col.rgb = pow(col.rgb, vec3(parameters.exponent));
|
||||
}
|
||||
|
||||
if (dither > 0.0) {
|
||||
if (parameters.dither > 0.0) {
|
||||
vec2 noise_uv = round_to_pixel(image_texture, texCoord_interp.st);
|
||||
col = apply_dither(col, noise_uv);
|
||||
}
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
in vec2 texCoord_interp;
|
||||
out vec4 fragColor;
|
||||
/** \} */
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 col = texture(image_texture, texCoord_interp.st);
|
||||
vec4 col_overlay = texture(overlay_texture, texCoord_interp.st);
|
||||
vec2 noise_uv = round_to_pixel(image_texture, texCoord_interp.st);
|
||||
|
||||
fragColor = OCIO_ProcessColor(col, col_overlay, noise_uv);
|
||||
fragColor = OCIO_ProcessColor(col, col_overlay);
|
||||
}
|
|
@ -1,10 +1,4 @@
|
|||
|
||||
uniform mat4 ModelViewProjectionMatrix;
|
||||
|
||||
in vec2 texCoord;
|
||||
in vec2 pos;
|
||||
out vec2 texCoord_interp;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = ModelViewProjectionMatrix * vec4(pos.xy, 0.0f, 1.0f);
|
|
@ -320,16 +320,18 @@ void OCIOImpl::configGetXYZtoRGB(OCIO_ConstConfigRcPtr *config_, float xyz_to_rg
|
|||
}
|
||||
|
||||
if (config->hasRole("aces_interchange")) {
|
||||
/* Standard OpenColorIO role, defined as ACES2065-1. */
|
||||
const float xyz_E_to_aces[3][3] = {{1.0498110175f, -0.4959030231f, 0.0f},
|
||||
{0.0f, 1.3733130458f, 0.0f},
|
||||
{-0.0000974845f, 0.0982400361f, 0.9912520182f}};
|
||||
const float xyz_D65_to_E[3][3] = {
|
||||
{1.0521111f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.9184170f}};
|
||||
|
||||
/* Standard OpenColorIO role, defined as ACES AP0 (ACES2065-1). */
|
||||
float aces_to_rgb[3][3];
|
||||
if (to_scene_linear_matrix(config, "aces_interchange", aces_to_rgb)) {
|
||||
mul_m3_series(xyz_to_rgb, aces_to_rgb, xyz_E_to_aces, xyz_D65_to_E);
|
||||
/* This is the OpenColorIO builtin transform:
|
||||
* UTILITY - ACES-AP0_to_CIE-XYZ-D65_BFD. */
|
||||
const float ACES_AP0_to_xyz_D65[3][3] = {{0.938280f, 0.337369f, 0.001174f},
|
||||
{-0.004451f, 0.729522f, -0.003711f},
|
||||
{0.016628f, -0.066890f, 1.091595f}};
|
||||
float xyz_to_aces[3][3];
|
||||
invert_m3_m3(xyz_to_aces, ACES_AP0_to_xyz_D65);
|
||||
|
||||
mul_m3_m3m3(xyz_to_rgb, aces_to_rgb, xyz_to_aces);
|
||||
}
|
||||
}
|
||||
else if (config->hasRole("XYZ")) {
|
||||
|
|
|
@ -21,14 +21,14 @@
|
|||
#include "GPU_shader.h"
|
||||
#include "GPU_uniform_buffer.h"
|
||||
|
||||
#include "gpu_shader_create_info.hh"
|
||||
|
||||
using namespace OCIO_NAMESPACE;
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "ocio_impl.h"
|
||||
|
||||
extern "C" char datatoc_gpu_shader_display_transform_glsl[];
|
||||
extern "C" char datatoc_gpu_shader_display_transform_vertex_glsl[];
|
||||
#include "ocio_shader_shared.hh"
|
||||
|
||||
/* **** OpenGL drawing routines using GLSL for color space transform ***** */
|
||||
|
||||
|
@ -39,41 +39,19 @@ enum OCIO_GPUTextureSlots {
|
|||
TEXTURE_SLOT_LUTS_OFFSET = 3,
|
||||
};
|
||||
|
||||
/* Curve mapping parameters
|
||||
*
|
||||
* See documentation for OCIO_CurveMappingSettings to get fields descriptions.
|
||||
* (this ones pretty much copies stuff from C structure.)
|
||||
*/
|
||||
struct OCIO_GPUCurveMappingParameters {
|
||||
float curve_mapping_mintable[4];
|
||||
float curve_mapping_range[4];
|
||||
float curve_mapping_ext_in_x[4];
|
||||
float curve_mapping_ext_in_y[4];
|
||||
float curve_mapping_ext_out_x[4];
|
||||
float curve_mapping_ext_out_y[4];
|
||||
float curve_mapping_first_x[4];
|
||||
float curve_mapping_first_y[4];
|
||||
float curve_mapping_last_x[4];
|
||||
float curve_mapping_last_y[4];
|
||||
float curve_mapping_black[4];
|
||||
float curve_mapping_bwmul[4];
|
||||
int curve_mapping_lut_size;
|
||||
int curve_mapping_use_extend_extrapolate;
|
||||
int _pad[2];
|
||||
/** WARNING: Needs to be 16byte aligned. Used as UBO data. */
|
||||
enum OCIO_GPUUniformBufSlots {
|
||||
UNIFORMBUF_SLOT_DISPLAY = 0,
|
||||
UNIFORMBUF_SLOT_CURVEMAP = 1,
|
||||
UNIFORMBUF_SLOT_LUTS = 2,
|
||||
};
|
||||
|
||||
struct OCIO_GPUShader {
|
||||
/* GPU shader. */
|
||||
struct GPUShader *shader = nullptr;
|
||||
|
||||
/** Uniform locations. */
|
||||
int scale_loc = 0;
|
||||
int exponent_loc = 0;
|
||||
int dither_loc = 0;
|
||||
int overlay_loc = 0;
|
||||
int predivide_loc = 0;
|
||||
int ubo_bind = 0;
|
||||
/** Uniform parameters. */
|
||||
OCIO_GPUParameters parameters = {};
|
||||
GPUUniformBuf *parameters_buffer = nullptr;
|
||||
|
||||
/* Destructor. */
|
||||
~OCIO_GPUShader()
|
||||
|
@ -81,6 +59,9 @@ struct OCIO_GPUShader {
|
|||
if (shader) {
|
||||
GPU_shader_free(shader);
|
||||
}
|
||||
if (parameters_buffer) {
|
||||
GPU_uniformbuf_free(parameters_buffer);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -103,6 +84,7 @@ struct OCIO_GPUTextures {
|
|||
|
||||
/* Uniforms */
|
||||
std::vector<OCIO_GPUUniform> uniforms;
|
||||
GPUUniformBuf *uniforms_buffer = nullptr;
|
||||
|
||||
/* Destructor. */
|
||||
~OCIO_GPUTextures()
|
||||
|
@ -113,6 +95,9 @@ struct OCIO_GPUTextures {
|
|||
if (dummy) {
|
||||
GPU_texture_free(dummy);
|
||||
}
|
||||
if (uniforms_buffer) {
|
||||
GPU_uniformbuf_free(uniforms_buffer);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -165,97 +150,134 @@ static bool createGPUShader(OCIO_GPUShader &shader,
|
|||
const GpuShaderDescRcPtr &shaderdesc_to_display,
|
||||
const bool use_curve_mapping)
|
||||
{
|
||||
std::ostringstream os;
|
||||
using namespace blender::gpu::shader;
|
||||
|
||||
std::string source;
|
||||
source += shaderdesc_to_scene_linear->getShaderText();
|
||||
source += "\n";
|
||||
source += shaderdesc_to_display->getShaderText();
|
||||
source += "\n";
|
||||
|
||||
{
|
||||
/* Fragment shader */
|
||||
|
||||
/* Work around OpenColorIO not supporting latest GLSL yet. */
|
||||
os << "#define texture2D texture\n";
|
||||
os << "#define texture3D texture\n";
|
||||
|
||||
if (use_curve_mapping) {
|
||||
os << "#define USE_CURVE_MAPPING\n";
|
||||
/* Replace all uniform declarations by a comment.
|
||||
* This avoids double declarations from the backend. */
|
||||
size_t index = 0;
|
||||
while (true) {
|
||||
index = source.find("uniform ", index);
|
||||
if (index == -1) {
|
||||
break;
|
||||
}
|
||||
source.replace(index, 2, "//");
|
||||
index += 2;
|
||||
}
|
||||
|
||||
os << shaderdesc_to_scene_linear->getShaderText() << "\n";
|
||||
os << shaderdesc_to_display->getShaderText() << "\n";
|
||||
|
||||
os << datatoc_gpu_shader_display_transform_glsl;
|
||||
}
|
||||
|
||||
shader.shader = GPU_shader_create(datatoc_gpu_shader_display_transform_vertex_glsl,
|
||||
os.str().c_str(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
"OCIOShader");
|
||||
StageInterfaceInfo iface("OCIO_Interface", "");
|
||||
iface.smooth(Type::VEC2, "texCoord_interp");
|
||||
|
||||
if (shader.shader == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
shader.scale_loc = GPU_shader_get_uniform(shader.shader, "scale");
|
||||
shader.exponent_loc = GPU_shader_get_uniform(shader.shader, "exponent");
|
||||
shader.dither_loc = GPU_shader_get_uniform(shader.shader, "dither");
|
||||
shader.overlay_loc = GPU_shader_get_uniform(shader.shader, "overlay");
|
||||
shader.predivide_loc = GPU_shader_get_uniform(shader.shader, "predivide");
|
||||
shader.ubo_bind = GPU_shader_get_uniform_block_binding(shader.shader,
|
||||
"OCIO_GPUCurveMappingParameters");
|
||||
|
||||
GPU_shader_bind(shader.shader);
|
||||
|
||||
/* Set texture bind point uniform once. This is saved by the shader. */
|
||||
GPUShader *sh = shader.shader;
|
||||
GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "image_texture"), TEXTURE_SLOT_IMAGE);
|
||||
GPU_shader_uniform_int(sh, GPU_shader_get_uniform(sh, "overlay_texture"), TEXTURE_SLOT_OVERLAY);
|
||||
ShaderCreateInfo info("OCIO_Display");
|
||||
/* Work around OpenColorIO not supporting latest GLSL yet. */
|
||||
info.define("texture2D", "texture");
|
||||
info.define("texture3D", "texture");
|
||||
info.typedef_source("ocio_shader_shared.hh");
|
||||
info.sampler(TEXTURE_SLOT_IMAGE, ImageType::FLOAT_2D, "image_texture");
|
||||
info.sampler(TEXTURE_SLOT_OVERLAY, ImageType::FLOAT_2D, "overlay_texture");
|
||||
info.uniform_buf(UNIFORMBUF_SLOT_DISPLAY, "OCIO_GPUParameters", "parameters");
|
||||
info.push_constant(Type::MAT4, "ModelViewProjectionMatrix");
|
||||
info.vertex_in(0, Type::VEC2, "pos");
|
||||
info.vertex_in(1, Type::VEC2, "texCoord");
|
||||
info.vertex_out(iface);
|
||||
info.fragment_out(0, Type::VEC4, "fragColor");
|
||||
info.vertex_source("gpu_shader_display_transform_vert.glsl");
|
||||
info.fragment_source("gpu_shader_display_transform_frag.glsl");
|
||||
info.fragment_source_generated = source;
|
||||
|
||||
if (use_curve_mapping) {
|
||||
GPU_shader_uniform_int(
|
||||
sh, GPU_shader_get_uniform(sh, "curve_mapping_texture"), TEXTURE_SLOT_CURVE_MAPPING);
|
||||
info.define("USE_CURVE_MAPPING");
|
||||
info.uniform_buf(UNIFORMBUF_SLOT_CURVEMAP, "OCIO_GPUCurveMappingParameters", "curve_mapping");
|
||||
info.sampler(TEXTURE_SLOT_CURVE_MAPPING, ImageType::FLOAT_1D, "curve_mapping_texture");
|
||||
}
|
||||
|
||||
/* Set LUT textures. */
|
||||
for (int i = 0; i < textures.luts.size(); i++) {
|
||||
GPU_shader_uniform_int(sh,
|
||||
GPU_shader_get_uniform(sh, textures.luts[i].sampler_name.c_str()),
|
||||
TEXTURE_SLOT_LUTS_OFFSET + i);
|
||||
int slot = TEXTURE_SLOT_LUTS_OFFSET;
|
||||
for (OCIO_GPULutTexture &texture : textures.luts) {
|
||||
ImageType type = GPU_texture_dimensions(texture.texture) == 2 ? ImageType::FLOAT_2D :
|
||||
ImageType::FLOAT_3D;
|
||||
info.sampler(slot++, type, texture.sampler_name.c_str());
|
||||
}
|
||||
|
||||
/* Set uniforms. */
|
||||
for (OCIO_GPUUniform &uniform : textures.uniforms) {
|
||||
const GpuShaderDesc::UniformData &data = uniform.data;
|
||||
const char *name = uniform.name.c_str();
|
||||
/* Set LUT uniforms. */
|
||||
if (!textures.uniforms.empty()) {
|
||||
/* NOTE: For simplicity, we pad everything to size of vec4 avoiding sorting and alignment
|
||||
* issues. It is unlikely that this becomes a real issue. */
|
||||
size_t ubo_size = textures.uniforms.size() * sizeof(float) * 4;
|
||||
void *ubo_data_buf = malloc(ubo_size);
|
||||
|
||||
if (data.m_getDouble) {
|
||||
GPU_shader_uniform_1f(sh, name, (float)data.m_getDouble());
|
||||
}
|
||||
else if (data.m_getBool) {
|
||||
GPU_shader_uniform_1f(sh, name, (float)(data.m_getBool() ? 1.0f : 0.0f));
|
||||
}
|
||||
else if (data.m_getFloat3) {
|
||||
GPU_shader_uniform_3f(sh,
|
||||
name,
|
||||
(float)data.m_getFloat3()[0],
|
||||
(float)data.m_getFloat3()[1],
|
||||
(float)data.m_getFloat3()[2]);
|
||||
}
|
||||
else if (data.m_vectorFloat.m_getSize && data.m_vectorFloat.m_getVector) {
|
||||
GPU_shader_uniform_vector(sh,
|
||||
GPU_shader_get_uniform(sh, name),
|
||||
(int)data.m_vectorFloat.m_getSize(),
|
||||
1,
|
||||
(float *)data.m_vectorFloat.m_getVector());
|
||||
}
|
||||
else if (data.m_vectorInt.m_getSize && data.m_vectorInt.m_getVector) {
|
||||
GPU_shader_uniform_vector_int(sh,
|
||||
GPU_shader_get_uniform(sh, name),
|
||||
(int)data.m_vectorInt.m_getSize(),
|
||||
1,
|
||||
(int *)data.m_vectorInt.m_getVector());
|
||||
uint32_t *ubo_data = reinterpret_cast<uint32_t *>(ubo_data_buf);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "struct OCIO_GPULutParameters {\n";
|
||||
|
||||
int index = 0;
|
||||
for (OCIO_GPUUniform &uniform : textures.uniforms) {
|
||||
index += 1;
|
||||
const GpuShaderDesc::UniformData &data = uniform.data;
|
||||
const char *name = uniform.name.c_str();
|
||||
char prefix = ' ';
|
||||
int vec_len;
|
||||
switch (data.m_type) {
|
||||
case UNIFORM_DOUBLE: {
|
||||
vec_len = 1;
|
||||
float value = float(data.m_getDouble());
|
||||
memcpy(ubo_data, &value, sizeof(float));
|
||||
break;
|
||||
}
|
||||
case UNIFORM_BOOL: {
|
||||
prefix = 'b';
|
||||
vec_len = 1;
|
||||
int value = int(data.m_getBool());
|
||||
memcpy(ubo_data, &value, sizeof(int));
|
||||
break;
|
||||
}
|
||||
case UNIFORM_FLOAT3:
|
||||
vec_len = 3;
|
||||
memcpy(ubo_data, data.m_getFloat3().data(), sizeof(float) * 3);
|
||||
break;
|
||||
case UNIFORM_VECTOR_FLOAT:
|
||||
vec_len = data.m_vectorFloat.m_getSize();
|
||||
memcpy(ubo_data, data.m_vectorFloat.m_getVector(), sizeof(float) * vec_len);
|
||||
break;
|
||||
case UNIFORM_VECTOR_INT:
|
||||
prefix = 'i';
|
||||
vec_len = data.m_vectorInt.m_getSize();
|
||||
memcpy(ubo_data, data.m_vectorInt.m_getVector(), sizeof(int) * vec_len);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
/* Align every member to 16bytes. */
|
||||
ubo_data += 4;
|
||||
/* Use a generic variable name because some GLSL compilers can interpret the preprocessor
|
||||
* define as recursive. */
|
||||
ss << " " << prefix << "vec4 var" << index << ";\n";
|
||||
/* Use a define to keep the generated code working. */
|
||||
blender::StringRef suffix = blender::StringRefNull("xyzw").substr(0, vec_len);
|
||||
ss << "#define " << name << " lut_parameters.var" << index << "." << suffix << "\n";
|
||||
}
|
||||
ss << "};\n";
|
||||
info.typedef_source_generated = ss.str();
|
||||
|
||||
info.uniform_buf(UNIFORMBUF_SLOT_LUTS, "OCIO_GPULutParameters", "lut_parameters");
|
||||
|
||||
textures.uniforms_buffer = GPU_uniformbuf_create_ex(
|
||||
ubo_size, ubo_data_buf, "OCIO_LutParameters");
|
||||
|
||||
free(ubo_data_buf);
|
||||
}
|
||||
|
||||
return true;
|
||||
shader.shader = GPU_shader_create_from_info(reinterpret_cast<GPUShaderCreateInfo *>(&info));
|
||||
|
||||
return (shader.shader != nullptr);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -438,27 +460,65 @@ static void updateGPUCurveMapping(OCIO_GPUCurveMappping &curvemap,
|
|||
/* Update uniforms. */
|
||||
OCIO_GPUCurveMappingParameters data;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
data.curve_mapping_range[i] = curve_mapping_settings->range[i];
|
||||
data.curve_mapping_mintable[i] = curve_mapping_settings->mintable[i];
|
||||
data.curve_mapping_ext_in_x[i] = curve_mapping_settings->ext_in_x[i];
|
||||
data.curve_mapping_ext_in_y[i] = curve_mapping_settings->ext_in_y[i];
|
||||
data.curve_mapping_ext_out_x[i] = curve_mapping_settings->ext_out_x[i];
|
||||
data.curve_mapping_ext_out_y[i] = curve_mapping_settings->ext_out_y[i];
|
||||
data.curve_mapping_first_x[i] = curve_mapping_settings->first_x[i];
|
||||
data.curve_mapping_first_y[i] = curve_mapping_settings->first_y[i];
|
||||
data.curve_mapping_last_x[i] = curve_mapping_settings->last_x[i];
|
||||
data.curve_mapping_last_y[i] = curve_mapping_settings->last_y[i];
|
||||
data.range[i] = curve_mapping_settings->range[i];
|
||||
data.mintable[i] = curve_mapping_settings->mintable[i];
|
||||
data.ext_in_x[i] = curve_mapping_settings->ext_in_x[i];
|
||||
data.ext_in_y[i] = curve_mapping_settings->ext_in_y[i];
|
||||
data.ext_out_x[i] = curve_mapping_settings->ext_out_x[i];
|
||||
data.ext_out_y[i] = curve_mapping_settings->ext_out_y[i];
|
||||
data.first_x[i] = curve_mapping_settings->first_x[i];
|
||||
data.first_y[i] = curve_mapping_settings->first_y[i];
|
||||
data.last_x[i] = curve_mapping_settings->last_x[i];
|
||||
data.last_y[i] = curve_mapping_settings->last_y[i];
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
data.curve_mapping_black[i] = curve_mapping_settings->black[i];
|
||||
data.curve_mapping_bwmul[i] = curve_mapping_settings->bwmul[i];
|
||||
data.black[i] = curve_mapping_settings->black[i];
|
||||
data.bwmul[i] = curve_mapping_settings->bwmul[i];
|
||||
}
|
||||
data.curve_mapping_lut_size = curve_mapping_settings->lut_size;
|
||||
data.curve_mapping_use_extend_extrapolate = curve_mapping_settings->use_extend_extrapolate;
|
||||
data.lut_size = curve_mapping_settings->lut_size;
|
||||
data.use_extend_extrapolate = curve_mapping_settings->use_extend_extrapolate;
|
||||
|
||||
GPU_uniformbuf_update(curvemap.buffer, &data);
|
||||
}
|
||||
|
||||
static void updateGPUDisplayParameters(OCIO_GPUShader &shader,
|
||||
float scale,
|
||||
float exponent,
|
||||
float dither,
|
||||
bool use_predivide,
|
||||
bool use_overlay)
|
||||
{
|
||||
bool do_update = false;
|
||||
if (shader.parameters_buffer == nullptr) {
|
||||
shader.parameters_buffer = GPU_uniformbuf_create(sizeof(OCIO_GPUParameters));
|
||||
do_update = true;
|
||||
}
|
||||
OCIO_GPUParameters &data = shader.parameters;
|
||||
if (data.scale != scale) {
|
||||
data.scale = scale;
|
||||
do_update = true;
|
||||
}
|
||||
if (data.exponent != exponent) {
|
||||
data.exponent = exponent;
|
||||
do_update = true;
|
||||
}
|
||||
if (data.dither != dither) {
|
||||
data.dither = dither;
|
||||
do_update = true;
|
||||
}
|
||||
if (data.use_predivide != use_predivide) {
|
||||
data.use_predivide = use_predivide;
|
||||
do_update = true;
|
||||
}
|
||||
if (data.use_overlay != use_overlay) {
|
||||
data.use_overlay = use_overlay;
|
||||
do_update = true;
|
||||
}
|
||||
if (do_update) {
|
||||
GPU_uniformbuf_update(shader.parameters_buffer, &data);
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -609,7 +669,7 @@ bool OCIOImpl::gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config,
|
|||
/* Update and bind curve mapping data. */
|
||||
if (curve_mapping_settings) {
|
||||
updateGPUCurveMapping(curvemap, curve_mapping_settings);
|
||||
GPU_uniformbuf_bind(curvemap.buffer, shader.ubo_bind);
|
||||
GPU_uniformbuf_bind(curvemap.buffer, UNIFORMBUF_SLOT_CURVEMAP);
|
||||
GPU_texture_bind(curvemap.texture, TEXTURE_SLOT_CURVE_MAPPING);
|
||||
}
|
||||
|
||||
|
@ -623,17 +683,16 @@ bool OCIOImpl::gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config,
|
|||
GPU_texture_bind(textures.luts[i].texture, TEXTURE_SLOT_LUTS_OFFSET + i);
|
||||
}
|
||||
|
||||
if (textures.uniforms_buffer) {
|
||||
GPU_uniformbuf_bind(textures.uniforms_buffer, UNIFORMBUF_SLOT_LUTS);
|
||||
}
|
||||
|
||||
updateGPUDisplayParameters(shader, scale, exponent, dither, use_predivide, use_overlay);
|
||||
GPU_uniformbuf_bind(shader.parameters_buffer, UNIFORMBUF_SLOT_DISPLAY);
|
||||
|
||||
/* TODO(fclem): remove remains of IMM. */
|
||||
immBindShader(shader.shader);
|
||||
|
||||
/* Bind Shader and set uniforms. */
|
||||
// GPU_shader_bind(shader.shader);
|
||||
GPU_shader_uniform_float(shader.shader, shader.scale_loc, scale);
|
||||
GPU_shader_uniform_float(shader.shader, shader.exponent_loc, exponent);
|
||||
GPU_shader_uniform_float(shader.shader, shader.dither_loc, dither);
|
||||
GPU_shader_uniform_int(shader.shader, shader.overlay_loc, use_overlay);
|
||||
GPU_shader_uniform_int(shader.shader, shader.predivide_loc, use_predivide);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Copyright 2022 Blender Foundation. All rights reserved. */
|
||||
|
||||
#ifndef GPU_SHADER
|
||||
# include "GPU_shader_shared_utils.h"
|
||||
#endif
|
||||
|
||||
struct OCIO_GPUCurveMappingParameters {
|
||||
/* Curve mapping parameters
|
||||
*
|
||||
* See documentation for OCIO_CurveMappingSettings to get fields descriptions.
|
||||
* (this ones pretty much copies stuff from C structure.)
|
||||
*/
|
||||
float4 mintable;
|
||||
float4 range;
|
||||
float4 ext_in_x;
|
||||
float4 ext_in_y;
|
||||
float4 ext_out_x;
|
||||
float4 ext_out_y;
|
||||
float4 first_x;
|
||||
float4 first_y;
|
||||
float4 last_x;
|
||||
float4 last_y;
|
||||
float4 black;
|
||||
float4 bwmul;
|
||||
int lut_size;
|
||||
int use_extend_extrapolate;
|
||||
int _pad0;
|
||||
int _pad1;
|
||||
};
|
||||
|
||||
struct OCIO_GPUParameters {
|
||||
float dither;
|
||||
float scale;
|
||||
float exponent;
|
||||
bool1 use_predivide;
|
||||
bool1 use_overlay;
|
||||
int _pad0;
|
||||
int _pad1;
|
||||
int _pad2;
|
||||
};
|
|
@ -66,6 +66,8 @@ if(WITH_OPENSUBDIV)
|
|||
internal/evaluator/evaluator_capi.cc
|
||||
internal/evaluator/evaluator_impl.cc
|
||||
internal/evaluator/evaluator_impl.h
|
||||
internal/evaluator/gl_compute_evaluator.cc
|
||||
internal/evaluator/gl_compute_evaluator.h
|
||||
internal/evaluator/patch_map.cc
|
||||
internal/evaluator/patch_map.h
|
||||
|
||||
|
@ -104,6 +106,8 @@ if(WITH_OPENSUBDIV)
|
|||
add_definitions(-DNOMINMAX)
|
||||
add_definitions(-D_USE_MATH_DEFINES)
|
||||
endif()
|
||||
|
||||
data_to_c_simple(internal/evaluator/shaders/glsl_compute_kernel.glsl SRC)
|
||||
else()
|
||||
list(APPEND SRC
|
||||
stub/opensubdiv_stub.cc
|
||||
|
|
|
@ -20,13 +20,11 @@
|
|||
#define OPENSUBDIV_EVAL_OUTPUT_GPU_H_
|
||||
|
||||
#include "internal/evaluator/eval_output.h"
|
||||
#include "internal/evaluator/gl_compute_evaluator.h"
|
||||
|
||||
#include <opensubdiv/osd/glComputeEvaluator.h>
|
||||
#include <opensubdiv/osd/glPatchTable.h>
|
||||
#include <opensubdiv/osd/glVertexBuffer.h>
|
||||
|
||||
using OpenSubdiv::Osd::GLComputeEvaluator;
|
||||
using OpenSubdiv::Osd::GLStencilTableSSBO;
|
||||
using OpenSubdiv::Osd::GLVertexBuffer;
|
||||
|
||||
namespace blender {
|
||||
|
|
|
@ -0,0 +1,647 @@
|
|||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "gl_compute_evaluator.h"
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <opensubdiv/far/error.h>
|
||||
#include <opensubdiv/far/patchDescriptor.h>
|
||||
#include <opensubdiv/far/stencilTable.h>
|
||||
#include <opensubdiv/osd/glslPatchShaderSource.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using OpenSubdiv::Far::LimitStencilTable;
|
||||
using OpenSubdiv::Far::StencilTable;
|
||||
using OpenSubdiv::Osd::BufferDescriptor;
|
||||
using OpenSubdiv::Osd::PatchArray;
|
||||
using OpenSubdiv::Osd::PatchArrayVector;
|
||||
|
||||
extern "C" char datatoc_glsl_compute_kernel_glsl[];
|
||||
|
||||
namespace blender {
|
||||
namespace opensubdiv {
|
||||
|
||||
template<class T> GLuint createSSBO(std::vector<T> const &src)
|
||||
{
|
||||
if (src.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLuint devicePtr = 0;
|
||||
|
||||
#if defined(GL_ARB_direct_state_access)
|
||||
if (GLEW_ARB_direct_state_access) {
|
||||
glCreateBuffers(1, &devicePtr);
|
||||
glNamedBufferData(devicePtr, src.size() * sizeof(T), &src.at(0), GL_STATIC_DRAW);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
GLint prev = 0;
|
||||
glGetIntegerv(GL_SHADER_STORAGE_BUFFER_BINDING, &prev);
|
||||
glGenBuffers(1, &devicePtr);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, devicePtr);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, src.size() * sizeof(T), &src.at(0), GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, prev);
|
||||
}
|
||||
|
||||
return devicePtr;
|
||||
}
|
||||
|
||||
GLStencilTableSSBO::GLStencilTableSSBO(StencilTable const *stencilTable)
|
||||
{
|
||||
_numStencils = stencilTable->GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createSSBO(stencilTable->GetSizes());
|
||||
_offsets = createSSBO(stencilTable->GetOffsets());
|
||||
_indices = createSSBO(stencilTable->GetControlIndices());
|
||||
_weights = createSSBO(stencilTable->GetWeights());
|
||||
_duWeights = _dvWeights = 0;
|
||||
_duuWeights = _duvWeights = _dvvWeights = 0;
|
||||
}
|
||||
else {
|
||||
_sizes = _offsets = _indices = _weights = 0;
|
||||
_duWeights = _dvWeights = 0;
|
||||
_duuWeights = _duvWeights = _dvvWeights = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GLStencilTableSSBO::GLStencilTableSSBO(LimitStencilTable const *limitStencilTable)
|
||||
{
|
||||
_numStencils = limitStencilTable->GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createSSBO(limitStencilTable->GetSizes());
|
||||
_offsets = createSSBO(limitStencilTable->GetOffsets());
|
||||
_indices = createSSBO(limitStencilTable->GetControlIndices());
|
||||
_weights = createSSBO(limitStencilTable->GetWeights());
|
||||
_duWeights = createSSBO(limitStencilTable->GetDuWeights());
|
||||
_dvWeights = createSSBO(limitStencilTable->GetDvWeights());
|
||||
_duuWeights = createSSBO(limitStencilTable->GetDuuWeights());
|
||||
_duvWeights = createSSBO(limitStencilTable->GetDuvWeights());
|
||||
_dvvWeights = createSSBO(limitStencilTable->GetDvvWeights());
|
||||
}
|
||||
else {
|
||||
_sizes = _offsets = _indices = _weights = 0;
|
||||
_duWeights = _dvWeights = 0;
|
||||
_duuWeights = _duvWeights = _dvvWeights = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GLStencilTableSSBO::~GLStencilTableSSBO()
|
||||
{
|
||||
if (_sizes)
|
||||
glDeleteBuffers(1, &_sizes);
|
||||
if (_offsets)
|
||||
glDeleteBuffers(1, &_offsets);
|
||||
if (_indices)
|
||||
glDeleteBuffers(1, &_indices);
|
||||
if (_weights)
|
||||
glDeleteBuffers(1, &_weights);
|
||||
if (_duWeights)
|
||||
glDeleteBuffers(1, &_duWeights);
|
||||
if (_dvWeights)
|
||||
glDeleteBuffers(1, &_dvWeights);
|
||||
if (_duuWeights)
|
||||
glDeleteBuffers(1, &_duuWeights);
|
||||
if (_duvWeights)
|
||||
glDeleteBuffers(1, &_duvWeights);
|
||||
if (_dvvWeights)
|
||||
glDeleteBuffers(1, &_dvvWeights);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
GLComputeEvaluator::GLComputeEvaluator() : _workGroupSize(64), _patchArraysSSBO(0)
|
||||
{
|
||||
memset(&_stencilKernel, 0, sizeof(_stencilKernel));
|
||||
memset(&_patchKernel, 0, sizeof(_patchKernel));
|
||||
}
|
||||
|
||||
GLComputeEvaluator::~GLComputeEvaluator()
|
||||
{
|
||||
if (_patchArraysSSBO) {
|
||||
glDeleteBuffers(1, &_patchArraysSSBO);
|
||||
}
|
||||
}
|
||||
|
||||
static GLuint compileKernel(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc,
|
||||
BufferDescriptor const &dvDesc,
|
||||
BufferDescriptor const &duuDesc,
|
||||
BufferDescriptor const &duvDesc,
|
||||
BufferDescriptor const &dvvDesc,
|
||||
const char *kernelDefine,
|
||||
int workGroupSize)
|
||||
{
|
||||
GLuint program = glCreateProgram();
|
||||
|
||||
GLuint shader = glCreateShader(GL_COMPUTE_SHADER);
|
||||
|
||||
std::string patchBasisShaderSource =
|
||||
OpenSubdiv::Osd::GLSLPatchShaderSource::GetPatchBasisShaderSource();
|
||||
const char *patchBasisShaderSourceDefine = "#define OSD_PATCH_BASIS_GLSL\n";
|
||||
|
||||
std::ostringstream defines;
|
||||
defines << "#define LENGTH " << srcDesc.length << "\n"
|
||||
<< "#define SRC_STRIDE " << srcDesc.stride << "\n"
|
||||
<< "#define DST_STRIDE " << dstDesc.stride << "\n"
|
||||
<< "#define WORK_GROUP_SIZE " << workGroupSize << "\n"
|
||||
<< kernelDefine << "\n"
|
||||
<< patchBasisShaderSourceDefine << "\n";
|
||||
|
||||
bool deriv1 = (duDesc.length > 0 || dvDesc.length > 0);
|
||||
bool deriv2 = (duuDesc.length > 0 || duvDesc.length > 0 || dvvDesc.length > 0);
|
||||
if (deriv1) {
|
||||
defines << "#define OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES\n";
|
||||
}
|
||||
if (deriv2) {
|
||||
defines << "#define OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES\n";
|
||||
}
|
||||
|
||||
std::string defineStr = defines.str();
|
||||
|
||||
const char *shaderSources[4] = {"#version 430\n", 0, 0, 0};
|
||||
|
||||
shaderSources[1] = defineStr.c_str();
|
||||
shaderSources[2] = patchBasisShaderSource.c_str();
|
||||
shaderSources[3] = datatoc_glsl_compute_kernel_glsl;
|
||||
glShaderSource(shader, 4, shaderSources, NULL);
|
||||
glCompileShader(shader);
|
||||
glAttachShader(program, shader);
|
||||
|
||||
GLint linked = 0;
|
||||
glLinkProgram(program);
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &linked);
|
||||
|
||||
if (linked == GL_FALSE) {
|
||||
char buffer[1024];
|
||||
glGetShaderInfoLog(shader, 1024, NULL, buffer);
|
||||
OpenSubdiv::Far::Error(OpenSubdiv::Far::FAR_RUNTIME_ERROR, buffer);
|
||||
|
||||
glGetProgramInfoLog(program, 1024, NULL, buffer);
|
||||
OpenSubdiv::Far::Error(OpenSubdiv::Far::FAR_RUNTIME_ERROR, buffer);
|
||||
|
||||
glDeleteProgram(program);
|
||||
return 0;
|
||||
}
|
||||
|
||||
glDeleteShader(shader);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
bool GLComputeEvaluator::Compile(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc,
|
||||
BufferDescriptor const &dvDesc,
|
||||
BufferDescriptor const &duuDesc,
|
||||
BufferDescriptor const &duvDesc,
|
||||
BufferDescriptor const &dvvDesc)
|
||||
{
|
||||
|
||||
// create a stencil kernel
|
||||
if (!_stencilKernel.Compile(
|
||||
srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, _workGroupSize)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// create a patch kernel
|
||||
if (!_patchKernel.Compile(
|
||||
srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, _workGroupSize)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// create a patch arrays buffer
|
||||
if (!_patchArraysSSBO) {
|
||||
glGenBuffers(1, &_patchArraysSSBO);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void GLComputeEvaluator::Synchronize(void * /*kernel*/)
|
||||
{
|
||||
// XXX: this is currently just for the performance measuring purpose.
|
||||
// need to be reimplemented by fence and sync.
|
||||
glFinish();
|
||||
}
|
||||
|
||||
int GLComputeEvaluator::GetDispatchSize(int count) const
|
||||
{
|
||||
return (count + _workGroupSize - 1) / _workGroupSize;
|
||||
}
|
||||
|
||||
void GLComputeEvaluator::DispatchCompute(int totalDispatchSize) const
|
||||
{
|
||||
int maxWorkGroupCount[2] = {0, 0};
|
||||
|
||||
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &maxWorkGroupCount[0]);
|
||||
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &maxWorkGroupCount[1]);
|
||||
|
||||
const GLuint maxResX = static_cast<GLuint>(maxWorkGroupCount[0]);
|
||||
|
||||
const int dispatchSize = GetDispatchSize(totalDispatchSize);
|
||||
GLuint dispatchRX = static_cast<GLuint>(dispatchSize);
|
||||
GLuint dispatchRY = 1u;
|
||||
if (dispatchRX > maxResX) {
|
||||
/* Since there are some limitations with regards to the maximum work group size (could be as
|
||||
* low as 64k elements per call), we split the number elements into a "2d" number, with the
|
||||
* final index being computed as `res_x + res_y * max_work_group_size`. Even with a maximum
|
||||
* work group size of 64k, that still leaves us with roughly `64k * 64k = 4` billion elements
|
||||
* total, which should be enough. If not, we could also use the 3rd dimension. */
|
||||
/* TODO(fclem): We could dispatch fewer groups if we compute the prime factorization and
|
||||
* get the smallest rect fitting the requirements. */
|
||||
dispatchRX = dispatchRY = std::ceil(std::sqrt(dispatchSize));
|
||||
/* Avoid a completely empty dispatch line caused by rounding. */
|
||||
if ((dispatchRX * (dispatchRY - 1)) >= dispatchSize) {
|
||||
dispatchRY -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* X and Y dimensions may have different limits so the above computation may not be right, but
|
||||
* even with the standard 64k minimum on all dimensions we still have a lot of room. Therefore,
|
||||
* we presume it all fits. */
|
||||
assert(dispatchRY < static_cast<GLuint>(maxWorkGroupCount[1]));
|
||||
|
||||
glDispatchCompute(dispatchRX, dispatchRY, 1);
|
||||
}
|
||||
|
||||
bool GLComputeEvaluator::EvalStencils(GLuint srcBuffer,
|
||||
BufferDescriptor const &srcDesc,
|
||||
GLuint dstBuffer,
|
||||
BufferDescriptor const &dstDesc,
|
||||
GLuint duBuffer,
|
||||
BufferDescriptor const &duDesc,
|
||||
GLuint dvBuffer,
|
||||
BufferDescriptor const &dvDesc,
|
||||
GLuint sizesBuffer,
|
||||
GLuint offsetsBuffer,
|
||||
GLuint indicesBuffer,
|
||||
GLuint weightsBuffer,
|
||||
GLuint duWeightsBuffer,
|
||||
GLuint dvWeightsBuffer,
|
||||
int start,
|
||||
int end) const
|
||||
{
|
||||
|
||||
return EvalStencils(srcBuffer,
|
||||
srcDesc,
|
||||
dstBuffer,
|
||||
dstDesc,
|
||||
duBuffer,
|
||||
duDesc,
|
||||
dvBuffer,
|
||||
dvDesc,
|
||||
0,
|
||||
BufferDescriptor(),
|
||||
0,
|
||||
BufferDescriptor(),
|
||||
0,
|
||||
BufferDescriptor(),
|
||||
sizesBuffer,
|
||||
offsetsBuffer,
|
||||
indicesBuffer,
|
||||
weightsBuffer,
|
||||
duWeightsBuffer,
|
||||
dvWeightsBuffer,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
start,
|
||||
end);
|
||||
}
|
||||
|
||||
bool GLComputeEvaluator::EvalStencils(GLuint srcBuffer,
|
||||
BufferDescriptor const &srcDesc,
|
||||
GLuint dstBuffer,
|
||||
BufferDescriptor const &dstDesc,
|
||||
GLuint duBuffer,
|
||||
BufferDescriptor const &duDesc,
|
||||
GLuint dvBuffer,
|
||||
BufferDescriptor const &dvDesc,
|
||||
GLuint duuBuffer,
|
||||
BufferDescriptor const &duuDesc,
|
||||
GLuint duvBuffer,
|
||||
BufferDescriptor const &duvDesc,
|
||||
GLuint dvvBuffer,
|
||||
BufferDescriptor const &dvvDesc,
|
||||
GLuint sizesBuffer,
|
||||
GLuint offsetsBuffer,
|
||||
GLuint indicesBuffer,
|
||||
GLuint weightsBuffer,
|
||||
GLuint duWeightsBuffer,
|
||||
GLuint dvWeightsBuffer,
|
||||
GLuint duuWeightsBuffer,
|
||||
GLuint duvWeightsBuffer,
|
||||
GLuint dvvWeightsBuffer,
|
||||
int start,
|
||||
int end) const
|
||||
{
|
||||
|
||||
if (!_stencilKernel.program)
|
||||
return false;
|
||||
int count = end - start;
|
||||
if (count <= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, srcBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, dstBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, duBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, dvBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, duuBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, duvBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 12, dvvBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, sizesBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, offsetsBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, indicesBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, weightsBuffer);
|
||||
if (duWeightsBuffer)
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 8, duWeightsBuffer);
|
||||
if (dvWeightsBuffer)
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 9, dvWeightsBuffer);
|
||||
if (duuWeightsBuffer)
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 13, duuWeightsBuffer);
|
||||
if (duvWeightsBuffer)
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 14, duvWeightsBuffer);
|
||||
if (dvvWeightsBuffer)
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 15, dvvWeightsBuffer);
|
||||
|
||||
glUseProgram(_stencilKernel.program);
|
||||
|
||||
glUniform1i(_stencilKernel.uniformStart, start);
|
||||
glUniform1i(_stencilKernel.uniformEnd, end);
|
||||
glUniform1i(_stencilKernel.uniformSrcOffset, srcDesc.offset);
|
||||
glUniform1i(_stencilKernel.uniformDstOffset, dstDesc.offset);
|
||||
if (_stencilKernel.uniformDuDesc > 0) {
|
||||
glUniform3i(_stencilKernel.uniformDuDesc, duDesc.offset, duDesc.length, duDesc.stride);
|
||||
}
|
||||
if (_stencilKernel.uniformDvDesc > 0) {
|
||||
glUniform3i(_stencilKernel.uniformDvDesc, dvDesc.offset, dvDesc.length, dvDesc.stride);
|
||||
}
|
||||
if (_stencilKernel.uniformDuuDesc > 0) {
|
||||
glUniform3i(_stencilKernel.uniformDuuDesc, duuDesc.offset, duuDesc.length, duuDesc.stride);
|
||||
}
|
||||
if (_stencilKernel.uniformDuvDesc > 0) {
|
||||
glUniform3i(_stencilKernel.uniformDuvDesc, duvDesc.offset, duvDesc.length, duvDesc.stride);
|
||||
}
|
||||
if (_stencilKernel.uniformDvvDesc > 0) {
|
||||
glUniform3i(_stencilKernel.uniformDvvDesc, dvvDesc.offset, dvvDesc.length, dvvDesc.stride);
|
||||
}
|
||||
|
||||
DispatchCompute(count);
|
||||
|
||||
glUseProgram(0);
|
||||
|
||||
glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GLComputeEvaluator::EvalPatches(GLuint srcBuffer,
|
||||
BufferDescriptor const &srcDesc,
|
||||
GLuint dstBuffer,
|
||||
BufferDescriptor const &dstDesc,
|
||||
GLuint duBuffer,
|
||||
BufferDescriptor const &duDesc,
|
||||
GLuint dvBuffer,
|
||||
BufferDescriptor const &dvDesc,
|
||||
int numPatchCoords,
|
||||
GLuint patchCoordsBuffer,
|
||||
const PatchArrayVector &patchArrays,
|
||||
GLuint patchIndexBuffer,
|
||||
GLuint patchParamsBuffer) const
|
||||
{
|
||||
|
||||
return EvalPatches(srcBuffer,
|
||||
srcDesc,
|
||||
dstBuffer,
|
||||
dstDesc,
|
||||
duBuffer,
|
||||
duDesc,
|
||||
dvBuffer,
|
||||
dvDesc,
|
||||
0,
|
||||
BufferDescriptor(),
|
||||
0,
|
||||
BufferDescriptor(),
|
||||
0,
|
||||
BufferDescriptor(),
|
||||
numPatchCoords,
|
||||
patchCoordsBuffer,
|
||||
patchArrays,
|
||||
patchIndexBuffer,
|
||||
patchParamsBuffer);
|
||||
}
|
||||
|
||||
bool GLComputeEvaluator::EvalPatches(GLuint srcBuffer,
|
||||
BufferDescriptor const &srcDesc,
|
||||
GLuint dstBuffer,
|
||||
BufferDescriptor const &dstDesc,
|
||||
GLuint duBuffer,
|
||||
BufferDescriptor const &duDesc,
|
||||
GLuint dvBuffer,
|
||||
BufferDescriptor const &dvDesc,
|
||||
GLuint duuBuffer,
|
||||
BufferDescriptor const &duuDesc,
|
||||
GLuint duvBuffer,
|
||||
BufferDescriptor const &duvDesc,
|
||||
GLuint dvvBuffer,
|
||||
BufferDescriptor const &dvvDesc,
|
||||
int numPatchCoords,
|
||||
GLuint patchCoordsBuffer,
|
||||
const PatchArrayVector &patchArrays,
|
||||
GLuint patchIndexBuffer,
|
||||
GLuint patchParamsBuffer) const
|
||||
{
|
||||
|
||||
if (!_patchKernel.program)
|
||||
return false;
|
||||
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, srcBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, dstBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, duBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, dvBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, duuBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, duvBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 12, dvvBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, patchCoordsBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, patchIndexBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, patchParamsBuffer);
|
||||
|
||||
glUseProgram(_patchKernel.program);
|
||||
|
||||
glUniform1i(_patchKernel.uniformSrcOffset, srcDesc.offset);
|
||||
glUniform1i(_patchKernel.uniformDstOffset, dstDesc.offset);
|
||||
|
||||
int patchArraySize = sizeof(PatchArray);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, _patchArraysSSBO);
|
||||
glBufferData(
|
||||
GL_SHADER_STORAGE_BUFFER, patchArrays.size() * patchArraySize, NULL, GL_STATIC_DRAW);
|
||||
for (int i = 0; i < (int)patchArrays.size(); ++i) {
|
||||
glBufferSubData(
|
||||
GL_SHADER_STORAGE_BUFFER, i * patchArraySize, sizeof(PatchArray), &patchArrays[i]);
|
||||
}
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, _patchArraysSSBO);
|
||||
|
||||
if (_patchKernel.uniformDuDesc > 0) {
|
||||
glUniform3i(_patchKernel.uniformDuDesc, duDesc.offset, duDesc.length, duDesc.stride);
|
||||
}
|
||||
if (_patchKernel.uniformDvDesc > 0) {
|
||||
glUniform3i(_patchKernel.uniformDvDesc, dvDesc.offset, dvDesc.length, dvDesc.stride);
|
||||
}
|
||||
if (_patchKernel.uniformDuuDesc > 0) {
|
||||
glUniform3i(_patchKernel.uniformDuuDesc, duuDesc.offset, duuDesc.length, duuDesc.stride);
|
||||
}
|
||||
if (_patchKernel.uniformDuvDesc > 0) {
|
||||
glUniform3i(_patchKernel.uniformDuvDesc, duvDesc.offset, duvDesc.length, duvDesc.stride);
|
||||
}
|
||||
if (_patchKernel.uniformDvvDesc > 0) {
|
||||
glUniform3i(_patchKernel.uniformDvvDesc, dvvDesc.offset, dvvDesc.length, dvvDesc.stride);
|
||||
}
|
||||
|
||||
DispatchCompute(numPatchCoords);
|
||||
|
||||
glUseProgram(0);
|
||||
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, 0);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, 0);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, 0);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, 0);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, 0);
|
||||
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, 0);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, 0);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 12, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
GLComputeEvaluator::_StencilKernel::_StencilKernel() : program(0)
|
||||
{
|
||||
}
|
||||
GLComputeEvaluator::_StencilKernel::~_StencilKernel()
|
||||
{
|
||||
if (program) {
|
||||
glDeleteProgram(program);
|
||||
}
|
||||
}
|
||||
|
||||
bool GLComputeEvaluator::_StencilKernel::Compile(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc,
|
||||
BufferDescriptor const &dvDesc,
|
||||
BufferDescriptor const &duuDesc,
|
||||
BufferDescriptor const &duvDesc,
|
||||
BufferDescriptor const &dvvDesc,
|
||||
int workGroupSize)
|
||||
{
|
||||
// create stencil kernel
|
||||
if (program) {
|
||||
glDeleteProgram(program);
|
||||
}
|
||||
|
||||
const char *kernelDefine = "#define OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_STENCILS\n";
|
||||
|
||||
program = compileKernel(
|
||||
srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, kernelDefine, workGroupSize);
|
||||
if (program == 0)
|
||||
return false;
|
||||
|
||||
// cache uniform locations (TODO: use uniform block)
|
||||
uniformStart = glGetUniformLocation(program, "batchStart");
|
||||
uniformEnd = glGetUniformLocation(program, "batchEnd");
|
||||
uniformSrcOffset = glGetUniformLocation(program, "srcOffset");
|
||||
uniformDstOffset = glGetUniformLocation(program, "dstOffset");
|
||||
uniformDuDesc = glGetUniformLocation(program, "duDesc");
|
||||
uniformDvDesc = glGetUniformLocation(program, "dvDesc");
|
||||
uniformDuuDesc = glGetUniformLocation(program, "duuDesc");
|
||||
uniformDuvDesc = glGetUniformLocation(program, "duvDesc");
|
||||
uniformDvvDesc = glGetUniformLocation(program, "dvvDesc");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
GLComputeEvaluator::_PatchKernel::_PatchKernel() : program(0)
|
||||
{
|
||||
}
|
||||
GLComputeEvaluator::_PatchKernel::~_PatchKernel()
|
||||
{
|
||||
if (program) {
|
||||
glDeleteProgram(program);
|
||||
}
|
||||
}
|
||||
|
||||
bool GLComputeEvaluator::_PatchKernel::Compile(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc,
|
||||
BufferDescriptor const &dvDesc,
|
||||
BufferDescriptor const &duuDesc,
|
||||
BufferDescriptor const &duvDesc,
|
||||
BufferDescriptor const &dvvDesc,
|
||||
int workGroupSize)
|
||||
{
|
||||
// create stencil kernel
|
||||
if (program) {
|
||||
glDeleteProgram(program);
|
||||
}
|
||||
|
||||
const char *kernelDefine = "#define OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_PATCHES\n";
|
||||
|
||||
program = compileKernel(
|
||||
srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, kernelDefine, workGroupSize);
|
||||
if (program == 0)
|
||||
return false;
|
||||
|
||||
// cache uniform locations
|
||||
uniformSrcOffset = glGetUniformLocation(program, "srcOffset");
|
||||
uniformDstOffset = glGetUniformLocation(program, "dstOffset");
|
||||
uniformPatchArray = glGetUniformLocation(program, "patchArray");
|
||||
uniformDuDesc = glGetUniformLocation(program, "duDesc");
|
||||
uniformDvDesc = glGetUniformLocation(program, "dvDesc");
|
||||
uniformDuuDesc = glGetUniformLocation(program, "duuDesc");
|
||||
uniformDuvDesc = glGetUniformLocation(program, "duvDesc");
|
||||
uniformDvvDesc = glGetUniformLocation(program, "dvvDesc");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace opensubdiv
|
||||
} // namespace blender
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,316 @@
|
|||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
layout(local_size_x=WORK_GROUP_SIZE, local_size_y=1, local_size_z=1) in;
|
||||
layout(std430) buffer;
|
||||
|
||||
// source and destination buffers
|
||||
|
||||
uniform int srcOffset = 0;
|
||||
uniform int dstOffset = 0;
|
||||
layout(binding=0) buffer src_buffer { float srcVertexBuffer[]; };
|
||||
layout(binding=1) buffer dst_buffer { float dstVertexBuffer[]; };
|
||||
|
||||
// derivative buffers (if needed)
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
|
||||
uniform ivec3 duDesc;
|
||||
uniform ivec3 dvDesc;
|
||||
layout(binding=2) buffer du_buffer { float duBuffer[]; };
|
||||
layout(binding=3) buffer dv_buffer { float dvBuffer[]; };
|
||||
#endif
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
|
||||
uniform ivec3 duuDesc;
|
||||
uniform ivec3 duvDesc;
|
||||
uniform ivec3 dvvDesc;
|
||||
layout(binding=10) buffer duu_buffer { float duuBuffer[]; };
|
||||
layout(binding=11) buffer duv_buffer { float duvBuffer[]; };
|
||||
layout(binding=12) buffer dvv_buffer { float dvvBuffer[]; };
|
||||
#endif
|
||||
|
||||
// stencil buffers
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_STENCILS)
|
||||
|
||||
uniform int batchStart = 0;
|
||||
uniform int batchEnd = 0;
|
||||
layout(binding=4) buffer stencilSizes { int _sizes[]; };
|
||||
layout(binding=5) buffer stencilOffsets { int _offsets[]; };
|
||||
layout(binding=6) buffer stencilIndices { int _indices[]; };
|
||||
layout(binding=7) buffer stencilWeights { float _weights[]; };
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
|
||||
layout(binding=8) buffer stencilDuWeights { float _duWeights[]; };
|
||||
layout(binding=9) buffer stencilDvWeights { float _dvWeights[]; };
|
||||
#endif
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
|
||||
layout(binding=13) buffer stencilDuuWeights { float _duuWeights[]; };
|
||||
layout(binding=14) buffer stencilDuvWeights { float _duvWeights[]; };
|
||||
layout(binding=15) buffer stencilDvvWeights { float _dvvWeights[]; };
|
||||
#endif
|
||||
|
||||
uint getGlobalInvocationIndex()
|
||||
{
|
||||
uint invocations_per_row = gl_WorkGroupSize.x * gl_NumWorkGroups.x;
|
||||
return gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * invocations_per_row;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// patch buffers
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_PATCHES)
|
||||
|
||||
layout(binding=4) buffer patchArray_buffer { OsdPatchArray patchArrayBuffer[]; };
|
||||
layout(binding=5) buffer patchCoord_buffer { OsdPatchCoord patchCoords[]; };
|
||||
layout(binding=6) buffer patchIndex_buffer { int patchIndexBuffer[]; };
|
||||
layout(binding=7) buffer patchParam_buffer { OsdPatchParam patchParamBuffer[]; };
|
||||
|
||||
OsdPatchCoord GetPatchCoord(int coordIndex)
|
||||
{
|
||||
return patchCoords[coordIndex];
|
||||
}
|
||||
|
||||
OsdPatchArray GetPatchArray(int arrayIndex)
|
||||
{
|
||||
return patchArrayBuffer[arrayIndex];
|
||||
}
|
||||
|
||||
OsdPatchParam GetPatchParam(int patchIndex)
|
||||
{
|
||||
return patchParamBuffer[patchIndex];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
struct Vertex {
|
||||
float vertexData[LENGTH];
|
||||
};
|
||||
|
||||
void clear(out Vertex v) {
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
v.vertexData[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Vertex readVertex(int index) {
|
||||
Vertex v;
|
||||
int vertexIndex = srcOffset + index * SRC_STRIDE;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
v.vertexData[i] = srcVertexBuffer[vertexIndex + i];
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
void writeVertex(int index, Vertex v) {
|
||||
int vertexIndex = dstOffset + index * DST_STRIDE;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
dstVertexBuffer[vertexIndex + i] = v.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void addWithWeight(inout Vertex v, const Vertex src, float weight) {
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
v.vertexData[i] += weight * src.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
|
||||
void writeDu(int index, Vertex du) {
|
||||
int duIndex = duDesc.x + index * duDesc.z;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
duBuffer[duIndex + i] = du.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeDv(int index, Vertex dv) {
|
||||
int dvIndex = dvDesc.x + index * dvDesc.z;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
dvBuffer[dvIndex + i] = dv.vertexData[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
|
||||
void writeDuu(int index, Vertex duu) {
|
||||
int duuIndex = duuDesc.x + index * duuDesc.z;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
duuBuffer[duuIndex + i] = duu.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeDuv(int index, Vertex duv) {
|
||||
int duvIndex = duvDesc.x + index * duvDesc.z;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
duvBuffer[duvIndex + i] = duv.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeDvv(int index, Vertex dvv) {
|
||||
int dvvIndex = dvvDesc.x + index * dvvDesc.z;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
dvvBuffer[dvvIndex + i] = dvv.vertexData[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_STENCILS)
|
||||
|
||||
void main() {
|
||||
int current = int(getGlobalInvocationIndex()) + batchStart;
|
||||
|
||||
if (current>=batchEnd) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vertex dst;
|
||||
clear(dst);
|
||||
|
||||
int offset = _offsets[current],
|
||||
size = _sizes[current];
|
||||
|
||||
for (int stencil = 0; stencil < size; ++stencil) {
|
||||
int vindex = offset + stencil;
|
||||
addWithWeight(
|
||||
dst, readVertex(_indices[vindex]), _weights[vindex]);
|
||||
}
|
||||
|
||||
writeVertex(current, dst);
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
|
||||
Vertex du, dv;
|
||||
clear(du);
|
||||
clear(dv);
|
||||
for (int i=0; i<size; ++i) {
|
||||
// expects the compiler optimizes readVertex out here.
|
||||
Vertex src = readVertex(_indices[offset+i]);
|
||||
addWithWeight(du, src, _duWeights[offset+i]);
|
||||
addWithWeight(dv, src, _dvWeights[offset+i]);
|
||||
}
|
||||
|
||||
if (duDesc.y > 0) { // length
|
||||
writeDu(current, du);
|
||||
}
|
||||
if (dvDesc.y > 0) {
|
||||
writeDv(current, dv);
|
||||
}
|
||||
#endif
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
|
||||
Vertex duu, duv, dvv;
|
||||
clear(duu);
|
||||
clear(duv);
|
||||
clear(dvv);
|
||||
for (int i=0; i<size; ++i) {
|
||||
// expects the compiler optimizes readVertex out here.
|
||||
Vertex src = readVertex(_indices[offset+i]);
|
||||
addWithWeight(duu, src, _duuWeights[offset+i]);
|
||||
addWithWeight(duv, src, _duvWeights[offset+i]);
|
||||
addWithWeight(dvv, src, _dvvWeights[offset+i]);
|
||||
}
|
||||
|
||||
if (duuDesc.y > 0) { // length
|
||||
writeDuu(current, duu);
|
||||
}
|
||||
if (duvDesc.y > 0) {
|
||||
writeDuv(current, duv);
|
||||
}
|
||||
if (dvvDesc.y > 0) {
|
||||
writeDvv(current, dvv);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_PATCHES)
|
||||
|
||||
// PERFORMANCE: stride could be constant, but not as significant as length
|
||||
|
||||
void main() {
|
||||
|
||||
int current = int(gl_GlobalInvocationID.x);
|
||||
|
||||
OsdPatchCoord coord = GetPatchCoord(current);
|
||||
OsdPatchArray array = GetPatchArray(coord.arrayIndex);
|
||||
OsdPatchParam param = GetPatchParam(coord.patchIndex);
|
||||
|
||||
int patchType = OsdPatchParamIsRegular(param) ? array.regDesc : array.desc;
|
||||
|
||||
float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
|
||||
int nPoints = OsdEvaluatePatchBasis(patchType, param,
|
||||
coord.s, coord.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
|
||||
|
||||
Vertex dst, du, dv, duu, duv, dvv;
|
||||
clear(dst);
|
||||
clear(du);
|
||||
clear(dv);
|
||||
clear(duu);
|
||||
clear(duv);
|
||||
clear(dvv);
|
||||
|
||||
int indexBase = array.indexBase + array.stride *
|
||||
(coord.patchIndex - array.primitiveIdBase);
|
||||
|
||||
for (int cv = 0; cv < nPoints; ++cv) {
|
||||
int index = patchIndexBuffer[indexBase + cv];
|
||||
addWithWeight(dst, readVertex(index), wP[cv]);
|
||||
addWithWeight(du, readVertex(index), wDu[cv]);
|
||||
addWithWeight(dv, readVertex(index), wDv[cv]);
|
||||
addWithWeight(duu, readVertex(index), wDuu[cv]);
|
||||
addWithWeight(duv, readVertex(index), wDuv[cv]);
|
||||
addWithWeight(dvv, readVertex(index), wDvv[cv]);
|
||||
}
|
||||
writeVertex(current, dst);
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
|
||||
if (duDesc.y > 0) { // length
|
||||
writeDu(current, du);
|
||||
}
|
||||
if (dvDesc.y > 0) {
|
||||
writeDv(current, dv);
|
||||
}
|
||||
#endif
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
|
||||
if (duuDesc.y > 0) { // length
|
||||
writeDuu(current, duu);
|
||||
}
|
||||
if (duvDesc.y > 0) { // length
|
||||
writeDuv(current, duv);
|
||||
}
|
||||
if (dvvDesc.y > 0) {
|
||||
writeDvv(current, dvv);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
|
@ -9,7 +9,7 @@
|
|||
#
|
||||
# See ocio-license.txt for details.
|
||||
|
||||
ocio_profile_version: 1
|
||||
ocio_profile_version: 2
|
||||
|
||||
search_path: "luts:filmic"
|
||||
strictparsing: true
|
||||
|
@ -100,8 +100,7 @@ colorspaces:
|
|||
from_reference: !<GroupTransform>
|
||||
children:
|
||||
- !<FileTransform> {src: srgb_to_xyz.spimtx, interpolation: linear}
|
||||
- !<FileTransform> {src: xyz_D65_to_E.spimtx, interpolation: linear}
|
||||
- !<FileTransform> {src: xyz_to_aces.spimtx, interpolation: linear}
|
||||
- !<BuiltinTransform> {style: "UTILITY - ACES-AP0_to_CIE-XYZ-D65_BFD", direction: inverse}
|
||||
|
||||
- !<ColorSpace>
|
||||
name: nuke_rec709
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit e1d44bf37501eb19a057777bd0b0ba4484773531
|
||||
Subproject commit 089aef61debbece2baff6516e33fc7491629b1d0
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "DNA_curves_types.h"
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
* \brief Low-level operations for curves.
|
||||
* \brief Low-level operations for curves that cannot be defined in the C++ header yet.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -23,14 +25,10 @@ void *BKE_curves_add(struct Main *bmain, const char *name);
|
|||
|
||||
struct BoundBox *BKE_curves_boundbox_get(struct Object *ob);
|
||||
|
||||
void BKE_curves_update_customdata_pointers(struct Curves *curves);
|
||||
bool BKE_curves_customdata_required(struct Curves *curves, struct CustomDataLayer *layer);
|
||||
|
||||
/* Depsgraph */
|
||||
|
||||
struct Curves *BKE_curves_new_for_eval(const struct Curves *curves_src,
|
||||
int totpoint,
|
||||
int totcurve);
|
||||
struct Curves *BKE_curves_copy_for_eval(struct Curves *curves_src, bool reference);
|
||||
|
||||
void BKE_curves_data_update(struct Depsgraph *depsgraph,
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BKE_curves.h"
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
* \brief Low-level operations for curves.
|
||||
*/
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "BLI_float4x4.hh"
|
||||
#include "BLI_index_mask.hh"
|
||||
#include "BLI_math_vec_types.hh"
|
||||
#include "BLI_span.hh"
|
||||
#include "BLI_task.hh"
|
||||
#include "BLI_vector.hh"
|
||||
#include "BLI_virtual_array.hh"
|
||||
|
||||
#include "BKE_attribute_access.hh"
|
||||
|
||||
#include "FN_generic_virtual_array.hh"
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
/**
|
||||
* Contains derived data, caches, and other information not saved in files, besides a few pointers
|
||||
* to arrays that are kept in the non-runtime struct to avoid dereferencing this whenever they are
|
||||
* accessed.
|
||||
*/
|
||||
class CurvesGeometryRuntime {
|
||||
public:
|
||||
/** Cache of evaluated positions. */
|
||||
mutable Vector<float3> evaluated_position_cache;
|
||||
mutable std::mutex position_cache_mutex;
|
||||
mutable bool position_cache_dirty = true;
|
||||
|
||||
/** Direction of the spline at each evaluated point. */
|
||||
mutable Vector<float3> evaluated_tangents_cache;
|
||||
mutable std::mutex tangent_cache_mutex;
|
||||
mutable bool tangent_cache_dirty = true;
|
||||
|
||||
/** Normal direction vectors for each evaluated point. */
|
||||
mutable Vector<float3> evaluated_normals_cache;
|
||||
mutable std::mutex normal_cache_mutex;
|
||||
mutable bool normal_cache_dirty = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* A C++ class that wraps the DNA struct for better encapsulation and ease of use. It inherits
|
||||
* directly from the struct rather than storing a pointer to avoid more complicated ownership
|
||||
* handling.
|
||||
*/
|
||||
class CurvesGeometry : public ::CurvesGeometry {
|
||||
public:
|
||||
CurvesGeometry();
|
||||
/**
|
||||
* Create curves with the given size. Only the position attribute is created, along with the
|
||||
* offsets.
|
||||
*/
|
||||
CurvesGeometry(int point_size, int curve_size);
|
||||
CurvesGeometry(const CurvesGeometry &other);
|
||||
CurvesGeometry &operator=(const CurvesGeometry &other);
|
||||
~CurvesGeometry();
|
||||
|
||||
static CurvesGeometry &wrap(::CurvesGeometry &dna_struct)
|
||||
{
|
||||
CurvesGeometry *geometry = reinterpret_cast<CurvesGeometry *>(&dna_struct);
|
||||
return *geometry;
|
||||
}
|
||||
static const CurvesGeometry &wrap(const ::CurvesGeometry &dna_struct)
|
||||
{
|
||||
const CurvesGeometry *geometry = reinterpret_cast<const CurvesGeometry *>(&dna_struct);
|
||||
return *geometry;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Accessors.
|
||||
*/
|
||||
|
||||
int points_size() const;
|
||||
int curves_size() const;
|
||||
|
||||
/**
|
||||
* The total number of points in the evaluated poly curve.
|
||||
* This can depend on the resolution attribute if it exists.
|
||||
*/
|
||||
int evaluated_points_size() const;
|
||||
|
||||
/**
|
||||
* Access a range of indices of point data for a specific curve.
|
||||
*/
|
||||
IndexRange range_for_curve(int index) const;
|
||||
|
||||
/** The type (#CurveType) of each curve, or potentially a single if all are the same type. */
|
||||
VArray<int8_t> curve_types() const;
|
||||
/** Mutable access to curve types. Call #tag_topology_changed after changing any type. */
|
||||
MutableSpan<int8_t> curve_types();
|
||||
|
||||
MutableSpan<float3> positions();
|
||||
Span<float3> positions() const;
|
||||
|
||||
/**
|
||||
* Calculate the largest and smallest position values, only including control points
|
||||
* (rather than evaluated points). The existing values of `min` and `max` are taken into account.
|
||||
*
|
||||
* \return Whether there are any points. If the curve is empty, the inputs will be unaffected.
|
||||
*/
|
||||
bool bounds_min_max(float3 &min, float3 &max) const;
|
||||
|
||||
/**
|
||||
* The index of the first point in every curve. The size of this span is one larger than the
|
||||
* number of curves. Consider using #range_for_curve rather than using the offsets directly.
|
||||
*/
|
||||
Span<int> offsets() const;
|
||||
MutableSpan<int> offsets();
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Operations.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Change the number of elements. New values for existing attributes should be properly
|
||||
* initialized afterwards.
|
||||
*/
|
||||
void resize(int point_size, int curve_size);
|
||||
|
||||
/** Call after deforming the position attribute. */
|
||||
void tag_positions_changed();
|
||||
/**
|
||||
* Call after any operation that changes the topology
|
||||
* (number of points, evaluated points, or the total count).
|
||||
*/
|
||||
void tag_topology_changed();
|
||||
/** Call after changing the "tilt" or "up" attributes. */
|
||||
void tag_normals_changed();
|
||||
|
||||
void translate(const float3 &translation);
|
||||
void transform(const float4x4 &matrix);
|
||||
|
||||
void update_customdata_pointers();
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Attributes.
|
||||
*/
|
||||
|
||||
fn::GVArray adapt_domain(const fn::GVArray &varray,
|
||||
AttributeDomain from,
|
||||
AttributeDomain to) const;
|
||||
};
|
||||
|
||||
Curves *curves_new_nomain(int point_size, int curves_size);
|
||||
|
||||
} // namespace blender::bke
|
|
@ -90,7 +90,6 @@ typedef enum VolumeGridType {
|
|||
VOLUME_GRID_INT,
|
||||
VOLUME_GRID_INT64,
|
||||
VOLUME_GRID_MASK,
|
||||
VOLUME_GRID_STRING,
|
||||
VOLUME_GRID_VECTOR_FLOAT,
|
||||
VOLUME_GRID_VECTOR_DOUBLE,
|
||||
VOLUME_GRID_VECTOR_INT,
|
||||
|
@ -204,8 +203,6 @@ auto BKE_volume_grid_type_operation(const VolumeGridType grid_type, OpType &&op)
|
|||
return op.template operator()<openvdb::Vec3IGrid>();
|
||||
case VOLUME_GRID_VECTOR_DOUBLE:
|
||||
return op.template operator()<openvdb::Vec3dGrid>();
|
||||
case VOLUME_GRID_STRING:
|
||||
return op.template operator()<openvdb::StringGrid>();
|
||||
case VOLUME_GRID_MASK:
|
||||
return op.template operator()<openvdb::MaskGrid>();
|
||||
case VOLUME_GRID_POINTS:
|
||||
|
|
|
@ -103,6 +103,7 @@ set(SRC
|
|||
intern/cryptomatte.cc
|
||||
intern/curve.cc
|
||||
intern/curves.cc
|
||||
intern/curves_geometry.cc
|
||||
intern/curve_bevel.c
|
||||
intern/curve_convert.c
|
||||
intern/curve_decimate.c
|
||||
|
@ -341,6 +342,7 @@ set(SRC
|
|||
BKE_cryptomatte.hh
|
||||
BKE_curve.h
|
||||
BKE_curves.h
|
||||
BKE_curves.hh
|
||||
BKE_curve_to_mesh.hh
|
||||
BKE_curveprofile.h
|
||||
BKE_customdata.h
|
||||
|
|
|
@ -207,6 +207,16 @@ class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider {
|
|||
void foreach_domain(const FunctionRef<void(AttributeDomain)> callback) const final;
|
||||
};
|
||||
|
||||
template<typename T> GVArray make_array_read_attribute(const void *data, const int domain_size)
|
||||
{
|
||||
return VArray<T>::ForSpan(Span<T>((const T *)data, domain_size));
|
||||
}
|
||||
|
||||
template<typename T> GVMutableArray make_array_write_attribute(void *data, const int domain_size)
|
||||
{
|
||||
return VMutableArray<T>::ForSpan(MutableSpan<T>((T *)data, domain_size));
|
||||
}
|
||||
|
||||
/**
|
||||
* This provider is used to provide access to builtin attributes. It supports making internal types
|
||||
* available as different types. For example, the vertex position attribute is stored as part of
|
||||
|
|
|
@ -147,7 +147,7 @@ static void brush_make_local(Main *bmain, ID *id, const int flags)
|
|||
/* NOTE: assert below ensures that the comment above is valid, and that that exception is
|
||||
* acceptable for the time being. */
|
||||
BKE_lib_id_make_local(bmain, &brush->clone.image->id, 0);
|
||||
BLI_assert(brush->clone.image->id.lib == NULL && brush->clone.image->id.newid == NULL);
|
||||
BLI_assert(!ID_IS_LINKED(brush->clone.image) && brush->clone.image->id.newid == NULL);
|
||||
}
|
||||
|
||||
if (force_local) {
|
||||
|
|
|
@ -550,9 +550,8 @@ void BKE_camera_view_frame(const Scene *scene, const Camera *camera, float r_vec
|
|||
#define CAMERA_VIEWFRAME_NUM_PLANES 4
|
||||
|
||||
typedef struct CameraViewFrameData {
|
||||
float plane_tx[CAMERA_VIEWFRAME_NUM_PLANES][4]; /* 4 planes */
|
||||
float normal_tx[CAMERA_VIEWFRAME_NUM_PLANES][3];
|
||||
float dist_vals_sq[CAMERA_VIEWFRAME_NUM_PLANES]; /* distance squared (signed) */
|
||||
float plane_tx[CAMERA_VIEWFRAME_NUM_PLANES][4]; /* 4 planes normalized */
|
||||
float dist_vals[CAMERA_VIEWFRAME_NUM_PLANES]; /* distance (signed) */
|
||||
unsigned int tot;
|
||||
|
||||
/* Ortho camera only. */
|
||||
|
@ -569,8 +568,8 @@ static void camera_to_frame_view_cb(const float co[3], void *user_data)
|
|||
CameraViewFrameData *data = (CameraViewFrameData *)user_data;
|
||||
|
||||
for (uint i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
|
||||
const float nd = dist_signed_squared_to_plane_v3(co, data->plane_tx[i]);
|
||||
CLAMP_MAX(data->dist_vals_sq[i], nd);
|
||||
const float nd = plane_point_side_v3(data->plane_tx[i], co);
|
||||
CLAMP_MAX(data->dist_vals[i], nd);
|
||||
}
|
||||
|
||||
if (data->is_ortho) {
|
||||
|
@ -625,10 +624,11 @@ static void camera_frame_fit_data_init(const Scene *scene,
|
|||
/* Rotate planes and get normals from them */
|
||||
for (uint i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
|
||||
mul_m4_v4(camera_rotmat_transposed_inversed, data->plane_tx[i]);
|
||||
normalize_v3_v3(data->normal_tx[i], data->plane_tx[i]);
|
||||
/* Normalize. */
|
||||
data->plane_tx[i][3] /= normalize_v3(data->plane_tx[i]);
|
||||
}
|
||||
|
||||
copy_v4_fl(data->dist_vals_sq, FLT_MAX);
|
||||
copy_v4_fl(data->dist_vals, FLT_MAX);
|
||||
data->tot = 0;
|
||||
data->is_ortho = params->is_ortho;
|
||||
if (params->is_ortho) {
|
||||
|
@ -653,14 +653,9 @@ static bool camera_frame_fit_calc_from_data(CameraParams *params,
|
|||
const float *cam_axis_x = data->camera_rotmat[0];
|
||||
const float *cam_axis_y = data->camera_rotmat[1];
|
||||
const float *cam_axis_z = data->camera_rotmat[2];
|
||||
float dists[CAMERA_VIEWFRAME_NUM_PLANES];
|
||||
const float *dists = data->dist_vals;
|
||||
float scale_diff;
|
||||
|
||||
/* apply the dist-from-plane's to the transformed plane points */
|
||||
for (int i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
|
||||
dists[i] = sqrtf_signed(data->dist_vals_sq[i]);
|
||||
}
|
||||
|
||||
if ((dists[0] + dists[2]) > (dists[1] + dists[3])) {
|
||||
scale_diff = (dists[1] + dists[3]) *
|
||||
(BLI_rctf_size_x(¶ms->viewplane) / BLI_rctf_size_y(¶ms->viewplane));
|
||||
|
@ -687,8 +682,8 @@ static bool camera_frame_fit_calc_from_data(CameraParams *params,
|
|||
/* apply the dist-from-plane's to the transformed plane points */
|
||||
for (int i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
|
||||
float co[3];
|
||||
mul_v3_v3fl(co, data->normal_tx[i], sqrtf_signed(data->dist_vals_sq[i]));
|
||||
plane_from_point_normal_v3(plane_tx[i], co, data->normal_tx[i]);
|
||||
mul_v3_v3fl(co, data->plane_tx[i], data->dist_vals[i]);
|
||||
plane_from_point_normal_v3(plane_tx[i], co, data->plane_tx[i]);
|
||||
}
|
||||
|
||||
if ((!isect_plane_plane_v3(plane_tx[0], plane_tx[2], plane_isect_1, plane_isect_1_no)) ||
|
||||
|
|
|
@ -14,16 +14,18 @@
|
|||
#include "DNA_material_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BLI_bounds.hh"
|
||||
#include "BLI_index_range.hh"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_base.h"
|
||||
#include "BLI_math_vector.hh"
|
||||
#include "BLI_rand.hh"
|
||||
#include "BLI_span.hh"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_anim_data.h"
|
||||
#include "BKE_curves.h"
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_idtype.h"
|
||||
|
@ -44,11 +46,12 @@ using blender::float3;
|
|||
using blender::IndexRange;
|
||||
using blender::MutableSpan;
|
||||
using blender::RandomNumberGenerator;
|
||||
using blender::Span;
|
||||
|
||||
static const char *ATTR_POSITION = "position";
|
||||
static const char *ATTR_RADIUS = "radius";
|
||||
|
||||
static void curves_random(Curves *curves);
|
||||
static void update_custom_data_pointers(Curves &curves);
|
||||
|
||||
static void curves_init_data(ID *id)
|
||||
{
|
||||
|
@ -57,50 +60,38 @@ static void curves_init_data(ID *id)
|
|||
|
||||
MEMCPY_STRUCT_AFTER(curves, DNA_struct_default_get(Curves), id);
|
||||
|
||||
CustomData_reset(&curves->geometry.point_data);
|
||||
CustomData_reset(&curves->geometry.curve_data);
|
||||
|
||||
CustomData_add_layer_named(&curves->geometry.point_data,
|
||||
CD_PROP_FLOAT3,
|
||||
CD_CALLOC,
|
||||
nullptr,
|
||||
curves->geometry.point_size,
|
||||
ATTR_POSITION);
|
||||
CustomData_add_layer_named(&curves->geometry.point_data,
|
||||
CD_PROP_FLOAT,
|
||||
CD_CALLOC,
|
||||
nullptr,
|
||||
curves->geometry.point_size,
|
||||
ATTR_RADIUS);
|
||||
|
||||
BKE_curves_update_customdata_pointers(curves);
|
||||
new (&curves->geometry) blender::bke::CurvesGeometry();
|
||||
|
||||
curves_random(curves);
|
||||
}
|
||||
|
||||
static void curves_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
|
||||
{
|
||||
using namespace blender;
|
||||
|
||||
Curves *curves_dst = (Curves *)id_dst;
|
||||
const Curves *curves_src = (const Curves *)id_src;
|
||||
curves_dst->mat = static_cast<Material **>(MEM_dupallocN(curves_src->mat));
|
||||
|
||||
curves_dst->geometry.point_size = curves_src->geometry.point_size;
|
||||
curves_dst->geometry.curve_size = curves_src->geometry.curve_size;
|
||||
const bke::CurvesGeometry &src = bke::CurvesGeometry::wrap(curves_src->geometry);
|
||||
bke::CurvesGeometry &dst = bke::CurvesGeometry::wrap(curves_dst->geometry);
|
||||
|
||||
/* We need special handling here because the generic ID management code has already done a
|
||||
* shallow copy from the source to the destination, and because the copy-on-write functionality
|
||||
* isn't supported more generically yet. */
|
||||
|
||||
dst.point_size = src.point_size;
|
||||
dst.curve_size = src.curve_size;
|
||||
|
||||
const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
|
||||
CustomData_copy(&curves_src->geometry.point_data,
|
||||
&curves_dst->geometry.point_data,
|
||||
CD_MASK_ALL,
|
||||
alloc_type,
|
||||
curves_dst->geometry.point_size);
|
||||
CustomData_copy(&curves_src->geometry.curve_data,
|
||||
&curves_dst->geometry.curve_data,
|
||||
CD_MASK_ALL,
|
||||
alloc_type,
|
||||
curves_dst->geometry.curve_size);
|
||||
BKE_curves_update_customdata_pointers(curves_dst);
|
||||
CustomData_copy(&src.point_data, &dst.point_data, CD_MASK_ALL, alloc_type, dst.point_size);
|
||||
CustomData_copy(&src.curve_data, &dst.curve_data, CD_MASK_ALL, alloc_type, dst.curve_size);
|
||||
|
||||
curves_dst->geometry.offsets = static_cast<int *>(MEM_dupallocN(curves_src->geometry.offsets));
|
||||
dst.curve_offsets = static_cast<int *>(MEM_dupallocN(src.curve_offsets));
|
||||
|
||||
dst.runtime = MEM_new<bke::CurvesGeometryRuntime>(__func__);
|
||||
|
||||
dst.update_customdata_pointers();
|
||||
|
||||
curves_dst->batch_cache = nullptr;
|
||||
}
|
||||
|
@ -110,13 +101,10 @@ static void curves_free_data(ID *id)
|
|||
Curves *curves = (Curves *)id;
|
||||
BKE_animdata_free(&curves->id, false);
|
||||
|
||||
blender::bke::CurvesGeometry::wrap(curves->geometry).~CurvesGeometry();
|
||||
|
||||
BKE_curves_batch_cache_free(curves);
|
||||
|
||||
CustomData_free(&curves->geometry.point_data, curves->geometry.point_size);
|
||||
CustomData_free(&curves->geometry.curve_data, curves->geometry.curve_size);
|
||||
|
||||
MEM_SAFE_FREE(curves->geometry.offsets);
|
||||
|
||||
MEM_SAFE_FREE(curves->mat);
|
||||
}
|
||||
|
||||
|
@ -157,7 +145,7 @@ static void curves_blend_write(BlendWriter *writer, ID *id, const void *id_addre
|
|||
CD_MASK_ALL,
|
||||
&curves->id);
|
||||
|
||||
BLO_write_int32_array(writer, curves->geometry.curve_size + 1, curves->geometry.offsets);
|
||||
BLO_write_int32_array(writer, curves->geometry.curve_size + 1, curves->geometry.curve_offsets);
|
||||
|
||||
BLO_write_pointer_array(writer, curves->totcol, curves->mat);
|
||||
if (curves->adt) {
|
||||
|
@ -182,9 +170,11 @@ static void curves_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
/* Geometry */
|
||||
CustomData_blend_read(reader, &curves->geometry.point_data, curves->geometry.point_size);
|
||||
CustomData_blend_read(reader, &curves->geometry.curve_data, curves->geometry.curve_size);
|
||||
BKE_curves_update_customdata_pointers(curves);
|
||||
update_custom_data_pointers(*curves);
|
||||
|
||||
BLO_read_int32_array(reader, curves->geometry.curve_size + 1, &curves->geometry.offsets);
|
||||
BLO_read_int32_array(reader, curves->geometry.curve_size + 1, &curves->geometry.curve_offsets);
|
||||
|
||||
curves->geometry.runtime = MEM_new<blender::bke::CurvesGeometryRuntime>(__func__);
|
||||
|
||||
/* Materials */
|
||||
BLO_read_pointer_array(reader, (void **)&curves->mat);
|
||||
|
@ -236,34 +226,33 @@ IDTypeInfo IDType_ID_CV = {
|
|||
/*lib_override_apply_post */ nullptr,
|
||||
};
|
||||
|
||||
static void update_custom_data_pointers(Curves &curves)
|
||||
{
|
||||
blender::bke::CurvesGeometry::wrap(curves.geometry).update_customdata_pointers();
|
||||
}
|
||||
|
||||
static void curves_random(Curves *curves)
|
||||
{
|
||||
CurvesGeometry &geometry = curves->geometry;
|
||||
const int numpoints = 8;
|
||||
|
||||
geometry.curve_size = 500;
|
||||
blender::bke::CurvesGeometry &geometry = blender::bke::CurvesGeometry::wrap(curves->geometry);
|
||||
geometry = blender::bke::CurvesGeometry(500 * numpoints, 500);
|
||||
|
||||
geometry.curve_size = 500;
|
||||
geometry.point_size = geometry.curve_size * numpoints;
|
||||
MutableSpan<int> offsets = geometry.offsets();
|
||||
MutableSpan<float3> positions = geometry.positions();
|
||||
|
||||
curves->geometry.offsets = (int *)MEM_calloc_arrayN(
|
||||
curves->geometry.curve_size + 1, sizeof(int), __func__);
|
||||
CustomData_realloc(&geometry.point_data, geometry.point_size);
|
||||
CustomData_realloc(&geometry.curve_data, geometry.curve_size);
|
||||
BKE_curves_update_customdata_pointers(curves);
|
||||
|
||||
MutableSpan<int> offsets{geometry.offsets, geometry.curve_size + 1};
|
||||
MutableSpan<float3> positions{(float3 *)geometry.position, geometry.point_size};
|
||||
MutableSpan<float> radii{geometry.radius, geometry.point_size};
|
||||
float *radius_data = (float *)CustomData_add_layer_named(
|
||||
&geometry.point_data, CD_PROP_FLOAT, CD_DEFAULT, nullptr, geometry.point_size, "radius");
|
||||
MutableSpan<float> radii{radius_data, geometry.points_size()};
|
||||
|
||||
for (const int i : offsets.index_range()) {
|
||||
geometry.offsets[i] = numpoints * i;
|
||||
offsets[i] = numpoints * i;
|
||||
}
|
||||
|
||||
RandomNumberGenerator rng;
|
||||
|
||||
for (int i = 0; i < geometry.curve_size; i++) {
|
||||
const IndexRange curve_range(offsets[i], offsets[i + 1] - offsets[i]);
|
||||
const IndexRange curve_range = geometry.range_for_curve(i);
|
||||
MutableSpan<float3> curve_positions = positions.slice(curve_range);
|
||||
MutableSpan<float> curve_radii = radii.slice(curve_range);
|
||||
|
||||
|
@ -304,18 +293,13 @@ BoundBox *BKE_curves_boundbox_get(Object *ob)
|
|||
if (ob->runtime.bb == nullptr) {
|
||||
ob->runtime.bb = MEM_cnew<BoundBox>(__func__);
|
||||
|
||||
float min[3], max[3];
|
||||
INIT_MINMAX(min, max);
|
||||
blender::bke::CurvesGeometry &geometry = blender::bke::CurvesGeometry::wrap(curves->geometry);
|
||||
|
||||
float(*curves_co)[3] = curves->geometry.position;
|
||||
float *curves_radius = curves->geometry.radius;
|
||||
for (int a = 0; a < curves->geometry.point_size; a++) {
|
||||
float *co = curves_co[a];
|
||||
float radius = (curves_radius) ? curves_radius[a] : 0.0f;
|
||||
const float co_min[3] = {co[0] - radius, co[1] - radius, co[2] - radius};
|
||||
const float co_max[3] = {co[0] + radius, co[1] + radius, co[2] + radius};
|
||||
DO_MIN(co_min, min);
|
||||
DO_MAX(co_max, max);
|
||||
float3 min(FLT_MAX);
|
||||
float3 max(-FLT_MAX);
|
||||
if (!geometry.bounds_min_max(min, max)) {
|
||||
min = float3(-1);
|
||||
max = float3(1);
|
||||
}
|
||||
|
||||
BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
|
||||
|
@ -324,46 +308,11 @@ BoundBox *BKE_curves_boundbox_get(Object *ob)
|
|||
return ob->runtime.bb;
|
||||
}
|
||||
|
||||
void BKE_curves_update_customdata_pointers(Curves *curves)
|
||||
{
|
||||
curves->geometry.position = (float(*)[3])CustomData_get_layer_named(
|
||||
&curves->geometry.point_data, CD_PROP_FLOAT3, ATTR_POSITION);
|
||||
curves->geometry.radius = (float *)CustomData_get_layer_named(
|
||||
&curves->geometry.point_data, CD_PROP_FLOAT, ATTR_RADIUS);
|
||||
}
|
||||
|
||||
bool BKE_curves_customdata_required(Curves *UNUSED(curves), CustomDataLayer *layer)
|
||||
{
|
||||
return layer->type == CD_PROP_FLOAT3 && STREQ(layer->name, ATTR_POSITION);
|
||||
}
|
||||
|
||||
/* Dependency Graph */
|
||||
|
||||
Curves *BKE_curves_new_for_eval(const Curves *curves_src, int totpoint, int totcurve)
|
||||
{
|
||||
Curves *curves_dst = static_cast<Curves *>(BKE_id_new_nomain(ID_CV, nullptr));
|
||||
|
||||
STRNCPY(curves_dst->id.name, curves_src->id.name);
|
||||
curves_dst->mat = static_cast<Material **>(MEM_dupallocN(curves_src->mat));
|
||||
curves_dst->totcol = curves_src->totcol;
|
||||
|
||||
curves_dst->geometry.point_size = totpoint;
|
||||
curves_dst->geometry.curve_size = totcurve;
|
||||
CustomData_copy(&curves_src->geometry.point_data,
|
||||
&curves_dst->geometry.point_data,
|
||||
CD_MASK_ALL,
|
||||
CD_CALLOC,
|
||||
totpoint);
|
||||
CustomData_copy(&curves_src->geometry.curve_data,
|
||||
&curves_dst->geometry.curve_data,
|
||||
CD_MASK_ALL,
|
||||
CD_CALLOC,
|
||||
totcurve);
|
||||
BKE_curves_update_customdata_pointers(curves_dst);
|
||||
|
||||
return curves_dst;
|
||||
}
|
||||
|
||||
Curves *BKE_curves_copy_for_eval(Curves *curves_src, bool reference)
|
||||
{
|
||||
int flags = LIB_ID_COPY_LOCALIZE;
|
||||
|
@ -414,7 +363,7 @@ static Curves *curves_evaluate_modifiers(struct Depsgraph *depsgraph,
|
|||
CD_PROP_FLOAT3,
|
||||
ATTR_POSITION,
|
||||
curves->geometry.point_size);
|
||||
BKE_curves_update_customdata_pointers(curves);
|
||||
update_custom_data_pointers(*curves);
|
||||
|
||||
/* Created deformed coordinates array on demand. */
|
||||
mti->deformVerts(
|
||||
|
@ -457,3 +406,15 @@ void BKE_curves_batch_cache_free(Curves *curves)
|
|||
BKE_curves_batch_cache_free_cb(curves);
|
||||
}
|
||||
}
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
Curves *curves_new_nomain(const int point_size, const int curves_size)
|
||||
{
|
||||
Curves *curves = static_cast<Curves *>(BKE_id_new_nomain(ID_CV, nullptr));
|
||||
CurvesGeometry &geometry = CurvesGeometry::wrap(curves->geometry);
|
||||
geometry.resize(point_size, curves_size);
|
||||
return curves;
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
|
|
@ -0,0 +1,368 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_bounds.hh"
|
||||
|
||||
#include "DNA_curves_types.h"
|
||||
|
||||
#include "BKE_attribute_math.hh"
|
||||
#include "BKE_curves.hh"
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
static const std::string ATTR_POSITION = "position";
|
||||
static const std::string ATTR_RADIUS = "radius";
|
||||
static const std::string ATTR_CURVE_TYPE = "curve_type";
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Constructors/Destructor
|
||||
* \{ */
|
||||
|
||||
CurvesGeometry::CurvesGeometry() : CurvesGeometry(0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
CurvesGeometry::CurvesGeometry(const int point_size, const int curve_size)
|
||||
{
|
||||
this->point_size = point_size;
|
||||
this->curve_size = curve_size;
|
||||
CustomData_reset(&this->point_data);
|
||||
CustomData_reset(&this->curve_data);
|
||||
|
||||
CustomData_add_layer_named(&this->point_data,
|
||||
CD_PROP_FLOAT3,
|
||||
CD_DEFAULT,
|
||||
nullptr,
|
||||
this->point_size,
|
||||
ATTR_POSITION.c_str());
|
||||
|
||||
this->curve_offsets = (int *)MEM_calloc_arrayN(this->curve_size + 1, sizeof(int), __func__);
|
||||
|
||||
this->update_customdata_pointers();
|
||||
|
||||
this->runtime = MEM_new<CurvesGeometryRuntime>(__func__);
|
||||
}
|
||||
|
||||
/**
|
||||
* \note Expects `dst` to be initialized, since the original attributes must be freed.
|
||||
*/
|
||||
static void copy_curves_geometry(CurvesGeometry &dst, const CurvesGeometry &src)
|
||||
{
|
||||
CustomData_free(&dst.point_data, dst.point_size);
|
||||
CustomData_free(&dst.curve_data, dst.curve_size);
|
||||
dst.point_size = src.point_size;
|
||||
dst.curve_size = src.curve_size;
|
||||
CustomData_copy(&src.point_data, &dst.point_data, CD_MASK_ALL, CD_DUPLICATE, dst.point_size);
|
||||
CustomData_copy(&src.curve_data, &dst.curve_data, CD_MASK_ALL, CD_DUPLICATE, dst.curve_size);
|
||||
|
||||
MEM_SAFE_FREE(dst.curve_offsets);
|
||||
dst.curve_offsets = (int *)MEM_calloc_arrayN(dst.point_size + 1, sizeof(int), __func__);
|
||||
dst.offsets().copy_from(src.offsets());
|
||||
|
||||
dst.tag_topology_changed();
|
||||
|
||||
dst.update_customdata_pointers();
|
||||
}
|
||||
|
||||
CurvesGeometry::CurvesGeometry(const CurvesGeometry &other)
|
||||
: CurvesGeometry(other.point_size, other.curve_size)
|
||||
{
|
||||
copy_curves_geometry(*this, other);
|
||||
}
|
||||
|
||||
CurvesGeometry &CurvesGeometry::operator=(const CurvesGeometry &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
copy_curves_geometry(*this, other);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
CurvesGeometry::~CurvesGeometry()
|
||||
{
|
||||
CustomData_free(&this->point_data, this->point_size);
|
||||
CustomData_free(&this->curve_data, this->curve_size);
|
||||
MEM_SAFE_FREE(this->curve_offsets);
|
||||
MEM_delete(this->runtime);
|
||||
this->runtime = nullptr;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Accessors
|
||||
* \{ */
|
||||
|
||||
int CurvesGeometry::points_size() const
|
||||
{
|
||||
return this->point_size;
|
||||
}
|
||||
int CurvesGeometry::curves_size() const
|
||||
{
|
||||
return this->curve_size;
|
||||
}
|
||||
int CurvesGeometry::evaluated_points_size() const
|
||||
{
|
||||
/* TODO: Implement when there are evaluated points. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
IndexRange CurvesGeometry::range_for_curve(const int index) const
|
||||
{
|
||||
const int offset = this->curve_offsets[index];
|
||||
const int offset_next = this->curve_offsets[index + 1];
|
||||
return {offset, offset_next - offset};
|
||||
}
|
||||
|
||||
VArray<int8_t> CurvesGeometry::curve_types() const
|
||||
{
|
||||
if (const int8_t *data = (const int8_t *)CustomData_get_layer_named(
|
||||
&this->curve_data, CD_PROP_INT8, ATTR_CURVE_TYPE.c_str())) {
|
||||
return VArray<int8_t>::ForSpan({data, this->curve_size});
|
||||
}
|
||||
return VArray<int8_t>::ForSingle(CURVE_TYPE_CATMULL_ROM, this->curve_size);
|
||||
}
|
||||
|
||||
MutableSpan<int8_t> CurvesGeometry::curve_types()
|
||||
{
|
||||
int8_t *data = (int8_t *)CustomData_add_layer_named(&this->curve_data,
|
||||
CD_PROP_INT8,
|
||||
CD_CALLOC,
|
||||
nullptr,
|
||||
this->curve_size,
|
||||
ATTR_CURVE_TYPE.c_str());
|
||||
BLI_assert(data != nullptr);
|
||||
return {data, this->curve_size};
|
||||
}
|
||||
|
||||
MutableSpan<float3> CurvesGeometry::positions()
|
||||
{
|
||||
CustomData_duplicate_referenced_layer(&this->point_data, CD_PROP_FLOAT3, this->point_size);
|
||||
this->update_customdata_pointers();
|
||||
return {(float3 *)this->position, this->point_size};
|
||||
}
|
||||
Span<float3> CurvesGeometry::positions() const
|
||||
{
|
||||
return {(const float3 *)this->position, this->point_size};
|
||||
}
|
||||
|
||||
MutableSpan<int> CurvesGeometry::offsets()
|
||||
{
|
||||
return {this->curve_offsets, this->curve_size + 1};
|
||||
}
|
||||
Span<int> CurvesGeometry::offsets() const
|
||||
{
|
||||
return {this->curve_offsets, this->curve_size + 1};
|
||||
}
|
||||
|
||||
void CurvesGeometry::resize(const int point_size, const int curve_size)
|
||||
{
|
||||
if (point_size != this->point_size) {
|
||||
CustomData_realloc(&this->point_data, point_size);
|
||||
this->point_size = point_size;
|
||||
}
|
||||
if (curve_size != this->curve_size) {
|
||||
CustomData_realloc(&this->curve_data, curve_size);
|
||||
this->curve_size = curve_size;
|
||||
this->curve_offsets = (int *)MEM_reallocN(this->curve_offsets, sizeof(int) * (curve_size + 1));
|
||||
}
|
||||
this->tag_topology_changed();
|
||||
this->update_customdata_pointers();
|
||||
}
|
||||
|
||||
void CurvesGeometry::tag_positions_changed()
|
||||
{
|
||||
this->runtime->position_cache_dirty = true;
|
||||
this->runtime->tangent_cache_dirty = true;
|
||||
this->runtime->normal_cache_dirty = true;
|
||||
}
|
||||
void CurvesGeometry::tag_topology_changed()
|
||||
{
|
||||
this->runtime->position_cache_dirty = true;
|
||||
this->runtime->tangent_cache_dirty = true;
|
||||
this->runtime->normal_cache_dirty = true;
|
||||
}
|
||||
void CurvesGeometry::tag_normals_changed()
|
||||
{
|
||||
this->runtime->normal_cache_dirty = true;
|
||||
}
|
||||
|
||||
void CurvesGeometry::translate(const float3 &translation)
|
||||
{
|
||||
MutableSpan<float3> positions = this->positions();
|
||||
threading::parallel_for(positions.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (float3 &position : positions.slice(range)) {
|
||||
position += translation;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void CurvesGeometry::transform(const float4x4 &matrix)
|
||||
{
|
||||
MutableSpan<float3> positions = this->positions();
|
||||
threading::parallel_for(positions.index_range(), 1024, [&](const IndexRange range) {
|
||||
for (float3 &position : positions.slice(range)) {
|
||||
position = matrix * position;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static std::optional<bounds::MinMaxResult<float3>> curves_bounds(const CurvesGeometry &curves)
|
||||
{
|
||||
Span<float3> positions = curves.positions();
|
||||
if (curves.radius) {
|
||||
Span<float> radii{curves.radius, curves.points_size()};
|
||||
return bounds::min_max_with_radii(positions, radii);
|
||||
}
|
||||
return bounds::min_max(positions);
|
||||
}
|
||||
|
||||
bool CurvesGeometry::bounds_min_max(float3 &min, float3 &max) const
|
||||
{
|
||||
const std::optional<bounds::MinMaxResult<float3>> bounds = curves_bounds(*this);
|
||||
if (!bounds) {
|
||||
return false;
|
||||
}
|
||||
min = math::min(bounds->min, min);
|
||||
max = math::max(bounds->max, max);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CurvesGeometry::update_customdata_pointers()
|
||||
{
|
||||
this->position = (float(*)[3])CustomData_get_layer_named(
|
||||
&this->point_data, CD_PROP_FLOAT3, ATTR_POSITION.c_str());
|
||||
this->radius = (float *)CustomData_get_layer_named(
|
||||
&this->point_data, CD_PROP_FLOAT, ATTR_RADIUS.c_str());
|
||||
this->curve_type = (int8_t *)CustomData_get_layer_named(
|
||||
&this->point_data, CD_PROP_INT8, ATTR_CURVE_TYPE.c_str());
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Domain Interpolation
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Mix together all of a curve's control point values.
|
||||
*
|
||||
* \note Theoretically this interpolation does not need to compute all values at once.
|
||||
* However, doing that makes the implementation simpler, and this can be optimized in the future if
|
||||
* only some values are required.
|
||||
*/
|
||||
template<typename T>
|
||||
static void adapt_curve_domain_point_to_curve_impl(const CurvesGeometry &curves,
|
||||
const VArray<T> &old_values,
|
||||
MutableSpan<T> r_values)
|
||||
{
|
||||
attribute_math::DefaultMixer<T> mixer(r_values);
|
||||
for (const int i_curve : IndexRange(curves.curves_size())) {
|
||||
for (const int i_point : curves.range_for_curve(i_curve)) {
|
||||
mixer.mix_in(i_curve, old_values[i_point]);
|
||||
}
|
||||
}
|
||||
mixer.finalize();
|
||||
}
|
||||
|
||||
/**
|
||||
* A curve is selected if all of its control points were selected.
|
||||
*
|
||||
* \note Theoretically this interpolation does not need to compute all values at once.
|
||||
* However, doing that makes the implementation simpler, and this can be optimized in the future if
|
||||
* only some values are required.
|
||||
*/
|
||||
template<>
|
||||
void adapt_curve_domain_point_to_curve_impl(const CurvesGeometry &curves,
|
||||
const VArray<bool> &old_values,
|
||||
MutableSpan<bool> r_values)
|
||||
{
|
||||
r_values.fill(true);
|
||||
for (const int i_curve : IndexRange(curves.curves_size())) {
|
||||
for (const int i_point : curves.range_for_curve(i_curve)) {
|
||||
if (!old_values[i_point]) {
|
||||
r_values[i_curve] = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static GVArray adapt_curve_domain_point_to_curve(const CurvesGeometry &curves,
|
||||
const GVArray &varray)
|
||||
{
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(curves.curves_size());
|
||||
adapt_curve_domain_point_to_curve_impl<T>(curves, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the value from a curve to all of its points.
|
||||
*
|
||||
* \note Theoretically this interpolation does not need to compute all values at once.
|
||||
* However, doing that makes the implementation simpler, and this can be optimized in the future if
|
||||
* only some values are required.
|
||||
*/
|
||||
template<typename T>
|
||||
static void adapt_curve_domain_curve_to_point_impl(const CurvesGeometry &curves,
|
||||
const VArray<T> &old_values,
|
||||
MutableSpan<T> r_values)
|
||||
{
|
||||
for (const int i_curve : IndexRange(curves.curves_size())) {
|
||||
r_values.slice(curves.range_for_curve(i_curve)).fill(old_values[i_curve]);
|
||||
}
|
||||
}
|
||||
|
||||
static GVArray adapt_curve_domain_curve_to_point(const CurvesGeometry &curves,
|
||||
const GVArray &varray)
|
||||
{
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
Array<T> values(curves.points_size());
|
||||
adapt_curve_domain_curve_to_point_impl<T>(curves, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
});
|
||||
return new_varray;
|
||||
}
|
||||
|
||||
fn::GVArray CurvesGeometry::adapt_domain(const fn::GVArray &varray,
|
||||
const AttributeDomain from,
|
||||
const AttributeDomain to) const
|
||||
{
|
||||
if (!varray) {
|
||||
return {};
|
||||
}
|
||||
if (varray.is_empty()) {
|
||||
return {};
|
||||
}
|
||||
if (from == to) {
|
||||
return varray;
|
||||
}
|
||||
|
||||
if (from == ATTR_DOMAIN_POINT && to == ATTR_DOMAIN_CURVE) {
|
||||
return adapt_curve_domain_point_to_curve(*this, varray);
|
||||
}
|
||||
if (from == ATTR_DOMAIN_CURVE && to == ATTR_DOMAIN_POINT) {
|
||||
return adapt_curve_domain_curve_to_point(*this, varray);
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
return {};
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::bke
|
|
@ -439,18 +439,6 @@ class InstancePositionAttributeProvider final : public BuiltinAttributeProvider
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
static GVArray make_array_read_attribute(const void *data, const int domain_size)
|
||||
{
|
||||
return VArray<T>::ForSpan(Span<T>((const T *)data, domain_size));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static GVMutableArray make_array_write_attribute(void *data, const int domain_size)
|
||||
{
|
||||
return VMutableArray<T>::ForSpan(MutableSpan<T>((T *)data, domain_size));
|
||||
}
|
||||
|
||||
static ComponentAttributeProviders create_attribute_providers_for_instances()
|
||||
{
|
||||
static InstancePositionAttributeProvider position;
|
||||
|
|
|
@ -854,18 +854,6 @@ static GVMutableArray make_derived_write_attribute(void *data, const int domain_
|
|||
MutableSpan<StructT>((StructT *)data, domain_size));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static GVArray make_array_read_attribute(const void *data, const int domain_size)
|
||||
{
|
||||
return VArray<T>::ForSpan(Span<T>((const T *)data, domain_size));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static GVMutableArray make_array_write_attribute(void *data, const int domain_size)
|
||||
{
|
||||
return VMutableArray<T>::ForSpan(MutableSpan<T>((T *)data, domain_size));
|
||||
}
|
||||
|
||||
static float3 get_vertex_position(const MVert &vert)
|
||||
{
|
||||
return float3(vert.co);
|
||||
|
|
|
@ -117,18 +117,6 @@ int PointCloudComponent::attribute_domain_size(const AttributeDomain domain) con
|
|||
|
||||
namespace blender::bke {
|
||||
|
||||
template<typename T>
|
||||
static GVArray make_array_read_attribute(const void *data, const int domain_size)
|
||||
{
|
||||
return VArray<T>::ForSpan(Span<T>((const T *)data, domain_size));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static GVMutableArray make_array_write_attribute(void *data, const int domain_size)
|
||||
{
|
||||
return VMutableArray<T>::ForSpan(MutableSpan<T>((T *)data, domain_size));
|
||||
}
|
||||
|
||||
/**
|
||||
* In this function all the attribute providers for a point cloud component are created. Most data
|
||||
* in this function is statically allocated, because it does not change over time.
|
||||
|
|
|
@ -234,7 +234,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
|
|||
for (id = lb->first; id; id = id_next) {
|
||||
id_next = id->next;
|
||||
/* NOTE: in case we delete a library, we also delete all its datablocks! */
|
||||
if ((id->tag & tag) || (id->lib != NULL && (id->lib->id.tag & tag))) {
|
||||
if ((id->tag & tag) || (ID_IS_LINKED(id) && (id->lib->id.tag & tag))) {
|
||||
BLI_remlink(lb, id);
|
||||
BLI_addtail(&tagged_deleted_ids, id);
|
||||
/* Do not tag as no_main now, we want to unlink it first (lower-level ID management
|
||||
|
@ -290,7 +290,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
|
|||
for (id = lb->first; id; id = id_next) {
|
||||
id_next = id->next;
|
||||
/* NOTE: in case we delete a library, we also delete all its datablocks! */
|
||||
if ((id->tag & tag) || (id->lib != NULL && (id->lib->id.tag & tag))) {
|
||||
if ((id->tag & tag) || (ID_IS_LINKED(id) && (id->lib->id.tag & tag))) {
|
||||
id->tag |= tag;
|
||||
BKE_id_remapper_add(remapper, id, NULL);
|
||||
}
|
||||
|
|
|
@ -2127,7 +2127,7 @@ static void lib_override_library_main_resync_on_library_indirect_level(
|
|||
"ID override %s from library level %d still found as needing resync, when all "
|
||||
"IDs from that level should have been processed after tackling library level %d",
|
||||
id->name,
|
||||
id->lib != NULL ? id->lib->temp_index : 0,
|
||||
ID_IS_LINKED(id) ? id->lib->temp_index : 0,
|
||||
library_indirect_level);
|
||||
id->tag &= ~LIB_TAG_LIB_OVERRIDE_NEED_RESYNC;
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
#include "BKE_constraint.h"
|
||||
#include "BKE_crazyspace.h"
|
||||
#include "BKE_curve.h"
|
||||
#include "BKE_curves.h"
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_deform.h"
|
||||
#include "BKE_displist.h"
|
||||
#include "BKE_duplilist.h"
|
||||
|
@ -3936,7 +3936,7 @@ bool BKE_object_minmax_dupli(Depsgraph *depsgraph,
|
|||
|
||||
ListBase *lb = object_duplilist(depsgraph, scene, ob);
|
||||
LISTBASE_FOREACH (DupliObject *, dob, lb) {
|
||||
if ((use_hidden == false) && (dob->no_draw != 0)) {
|
||||
if (((use_hidden == false) && (dob->no_draw != 0)) || dob->ob_data == nullptr) {
|
||||
/* pass */
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -1331,9 +1331,6 @@ VolumeGridType BKE_volume_grid_type_openvdb(const openvdb::GridBase &grid)
|
|||
if (grid.isType<openvdb::Vec3dGrid>()) {
|
||||
return VOLUME_GRID_VECTOR_DOUBLE;
|
||||
}
|
||||
if (grid.isType<openvdb::StringGrid>()) {
|
||||
return VOLUME_GRID_STRING;
|
||||
}
|
||||
if (grid.isType<openvdb::MaskGrid>()) {
|
||||
return VOLUME_GRID_MASK;
|
||||
}
|
||||
|
@ -1369,7 +1366,6 @@ int BKE_volume_grid_channels(const VolumeGrid *grid)
|
|||
case VOLUME_GRID_VECTOR_DOUBLE:
|
||||
case VOLUME_GRID_VECTOR_INT:
|
||||
return 3;
|
||||
case VOLUME_GRID_STRING:
|
||||
case VOLUME_GRID_POINTS:
|
||||
case VOLUME_GRID_UNKNOWN:
|
||||
return 0;
|
||||
|
@ -1610,13 +1606,8 @@ struct CreateGridWithChangedResolutionOp {
|
|||
|
||||
template<typename GridType> typename openvdb::GridBase::Ptr operator()()
|
||||
{
|
||||
if constexpr (std::is_same_v<GridType, openvdb::StringGrid>) {
|
||||
return {};
|
||||
}
|
||||
else {
|
||||
return create_grid_with_changed_resolution(static_cast<const GridType &>(grid),
|
||||
resolution_factor);
|
||||
}
|
||||
return create_grid_with_changed_resolution(static_cast<const GridType &>(grid),
|
||||
resolution_factor);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -63,7 +63,6 @@ static void extract_dense_float_voxels(const VolumeGridType grid_type,
|
|||
case VOLUME_GRID_VECTOR_INT:
|
||||
return extract_dense_voxels<openvdb::Vec3IGrid, openvdb::Vec3f>(
|
||||
grid, bbox, reinterpret_cast<openvdb::Vec3f *>(r_voxels));
|
||||
case VOLUME_GRID_STRING:
|
||||
case VOLUME_GRID_POINTS:
|
||||
case VOLUME_GRID_UNKNOWN:
|
||||
/* Zero channels to copy. */
|
||||
|
|
|
@ -1,18 +1,4 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
|
|
|
@ -64,16 +64,6 @@ template<typename T> uint64_t vector_hash(const T &vec)
|
|||
return result;
|
||||
}
|
||||
|
||||
template<typename T, int Size> inline bool is_any_zero(const vec_struct_base<T, Size> &a)
|
||||
{
|
||||
for (int i = 0; i < Size; i++) {
|
||||
if (a[i] == T(0)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
|
||||
template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size> {
|
||||
|
@ -353,7 +343,9 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size>
|
|||
|
||||
friend vec_base operator/(const vec_base &a, const vec_base &b)
|
||||
{
|
||||
BLI_assert(!math::is_any_zero(b));
|
||||
for (int i = 0; i < Size; i++) {
|
||||
BLI_assert(b[i] != T(0));
|
||||
}
|
||||
BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] / b[i]);
|
||||
}
|
||||
|
||||
|
@ -365,7 +357,9 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size>
|
|||
|
||||
friend vec_base operator/(T a, const vec_base &b)
|
||||
{
|
||||
BLI_assert(!math::is_any_zero(b));
|
||||
for (int i = 0; i < Size; i++) {
|
||||
BLI_assert(b[i] != T(0));
|
||||
}
|
||||
BLI_VEC_OP_IMPL(ret, i, ret[i] = a / b[i]);
|
||||
}
|
||||
|
||||
|
@ -509,7 +503,9 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size>
|
|||
|
||||
BLI_INT_OP(T) friend vec_base operator%(const vec_base &a, const vec_base &b)
|
||||
{
|
||||
BLI_assert(!math::is_any_zero(b));
|
||||
for (int i = 0; i < Size; i++) {
|
||||
BLI_assert(b[i] != T(0));
|
||||
}
|
||||
BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] % b[i]);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,16 @@ template<typename T, int Size> inline bool is_zero(const vec_base<T, Size> &a)
|
|||
return true;
|
||||
}
|
||||
|
||||
template<typename T, int Size> inline bool is_any_zero(const vec_base<T, Size> &a)
|
||||
{
|
||||
for (int i = 0; i < Size; i++) {
|
||||
if (a[i] == T(0)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T, int Size> inline vec_base<T, Size> abs(const vec_base<T, Size> &a)
|
||||
{
|
||||
vec_base<T, Size> result;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Apache License, Version 2.0 */
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "testing/testing.h"
|
||||
|
||||
|
|
|
@ -146,4 +146,29 @@ TEST(math_vec_types, VectorTypeConversion)
|
|||
EXPECT_EQ(d[1], -1.0);
|
||||
}
|
||||
|
||||
TEST(math_vec_types, Divide)
|
||||
{
|
||||
float2 a(1.0f, 2.0f);
|
||||
float2 b(0.5f, 2.0f);
|
||||
float2 result = a / b;
|
||||
EXPECT_FLOAT_EQ(result.x, 2.0f);
|
||||
EXPECT_FLOAT_EQ(result.y, 1.0f);
|
||||
}
|
||||
|
||||
TEST(math_vec_types, DivideFloatByVector)
|
||||
{
|
||||
float a = 2.0f;
|
||||
float2 b(0.5f, 2.0f);
|
||||
float2 result = a / b;
|
||||
EXPECT_FLOAT_EQ(result.x, 4.0f);
|
||||
EXPECT_FLOAT_EQ(result.y, 1.0f);
|
||||
}
|
||||
|
||||
TEST(math_vec_types, DivideFloatByVectorSmall)
|
||||
{
|
||||
float2 result = 2.0f / float2(2.0f);
|
||||
EXPECT_FLOAT_EQ(result.x, 1.0f);
|
||||
EXPECT_FLOAT_EQ(result.y, 1.0f);
|
||||
}
|
||||
|
||||
} // namespace blender::tests
|
||||
|
|
|
@ -56,7 +56,7 @@ ID *do_versions_rename_id(Main *bmain,
|
|||
ListBase *lb = which_libbase(bmain, id_type);
|
||||
ID *id = nullptr;
|
||||
LISTBASE_FOREACH (ID *, idtest, lb) {
|
||||
if (idtest->lib == nullptr) {
|
||||
if (!ID_IS_LINKED(idtest)) {
|
||||
if (STREQ(idtest->name + 2, name_src)) {
|
||||
id = idtest;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "DNA_curves_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BKE_curves.h"
|
||||
#include "BKE_curves.hh"
|
||||
|
||||
#include "GPU_batch.h"
|
||||
#include "GPU_material.h"
|
||||
|
@ -133,7 +133,7 @@ static void curves_batch_cache_fill_segments_proc_pos(Curves *curves,
|
|||
{
|
||||
/* TODO: use hair radius layer if available. */
|
||||
const int curve_size = curves->geometry.curve_size;
|
||||
Span<int> offsets{curves->geometry.offsets, curves->geometry.curve_size + 1};
|
||||
Span<int> offsets{curves->geometry.curve_offsets, curves->geometry.curve_size + 1};
|
||||
|
||||
Span<float3> positions{(float3 *)curves->geometry.position, curves->geometry.point_size};
|
||||
|
||||
|
@ -216,7 +216,7 @@ static void curves_batch_cache_fill_strands_data(Curves *curves,
|
|||
GPUVertBufRaw *seg_step)
|
||||
{
|
||||
const int curve_size = curves->geometry.curve_size;
|
||||
Span<int> offsets{curves->geometry.offsets, curves->geometry.curve_size + 1};
|
||||
Span<int> offsets{curves->geometry.curve_offsets, curves->geometry.curve_size + 1};
|
||||
|
||||
for (const int i : IndexRange(curve_size)) {
|
||||
const IndexRange curve_range(offsets[i], offsets[i + 1] - offsets[i]);
|
||||
|
|
|
@ -592,6 +592,67 @@ void draw_subdiv_cache_free(DRWSubdivCache *cache)
|
|||
SUBDIV_COARSE_FACE_FLAG_ACTIVE) \
|
||||
<< SUBDIV_COARSE_FACE_FLAG_OFFSET)
|
||||
|
||||
static uint32_t compute_coarse_face_flag(BMFace *f, BMFace *efa_act)
|
||||
{
|
||||
if (f == nullptr) {
|
||||
/* May happen during mapped extraction. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t flag = 0;
|
||||
if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) {
|
||||
flag |= SUBDIV_COARSE_FACE_FLAG_SMOOTH;
|
||||
}
|
||||
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
|
||||
flag |= SUBDIV_COARSE_FACE_FLAG_SELECT;
|
||||
}
|
||||
if (f == efa_act) {
|
||||
flag |= SUBDIV_COARSE_FACE_FLAG_ACTIVE;
|
||||
}
|
||||
const int loopstart = BM_elem_index_get(f->l_first);
|
||||
return (uint)(loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET);
|
||||
}
|
||||
|
||||
static void draw_subdiv_cache_extra_coarse_face_data_bm(BMesh *bm,
|
||||
BMFace *efa_act,
|
||||
uint32_t *flags_data)
|
||||
{
|
||||
BMFace *f;
|
||||
BMIter iter;
|
||||
|
||||
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
|
||||
const int index = BM_elem_index_get(f);
|
||||
flags_data[index] = compute_coarse_face_flag(f, efa_act);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_subdiv_cache_extra_coarse_face_data_mesh(Mesh *mesh, uint32_t *flags_data)
|
||||
{
|
||||
for (int i = 0; i < mesh->totpoly; i++) {
|
||||
uint32_t flag = 0;
|
||||
if ((mesh->mpoly[i].flag & ME_SMOOTH) != 0) {
|
||||
flag = SUBDIV_COARSE_FACE_FLAG_SMOOTH;
|
||||
}
|
||||
flags_data[i] = (uint)(mesh->mpoly[i].loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_subdiv_cache_extra_coarse_face_data_mapped(Mesh *mesh,
|
||||
BMesh *bm,
|
||||
MeshRenderData *mr,
|
||||
uint32_t *flags_data)
|
||||
{
|
||||
if (bm == nullptr) {
|
||||
draw_subdiv_cache_extra_coarse_face_data_mesh(mesh, flags_data);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < mesh->totpoly; i++) {
|
||||
BMFace *f = bm_original_face_get(mr, i);
|
||||
flags_data[i] = compute_coarse_face_flag(f, mr->efa_act);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_subdiv_cache_update_extra_coarse_face_data(DRWSubdivCache *cache,
|
||||
Mesh *mesh,
|
||||
MeshRenderData *mr)
|
||||
|
@ -611,56 +672,13 @@ static void draw_subdiv_cache_update_extra_coarse_face_data(DRWSubdivCache *cach
|
|||
uint32_t *flags_data = (uint32_t *)(GPU_vertbuf_get_data(cache->extra_coarse_face_data));
|
||||
|
||||
if (mr->extract_type == MR_EXTRACT_BMESH) {
|
||||
BMesh *bm = cache->bm;
|
||||
BMFace *f;
|
||||
BMIter iter;
|
||||
|
||||
/* Ensure all current elements follow new customdata layout. */
|
||||
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
|
||||
const int index = BM_elem_index_get(f);
|
||||
uint32_t flag = 0;
|
||||
if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) {
|
||||
flag |= SUBDIV_COARSE_FACE_FLAG_SMOOTH;
|
||||
}
|
||||
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
|
||||
flag |= SUBDIV_COARSE_FACE_FLAG_SELECT;
|
||||
}
|
||||
if (f == mr->efa_act) {
|
||||
flag |= SUBDIV_COARSE_FACE_FLAG_ACTIVE;
|
||||
}
|
||||
const int loopstart = BM_elem_index_get(f->l_first);
|
||||
flags_data[index] = (uint)(loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET);
|
||||
}
|
||||
draw_subdiv_cache_extra_coarse_face_data_bm(cache->bm, mr->efa_act, flags_data);
|
||||
}
|
||||
else if (mr->extract_type == MR_EXTRACT_MAPPED) {
|
||||
for (int i = 0; i < mesh->totpoly; i++) {
|
||||
BMFace *f = bm_original_face_get(mr, i);
|
||||
uint32_t flag = 0;
|
||||
|
||||
if (f) {
|
||||
if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) {
|
||||
flag |= SUBDIV_COARSE_FACE_FLAG_SMOOTH;
|
||||
}
|
||||
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
|
||||
flag |= SUBDIV_COARSE_FACE_FLAG_SELECT;
|
||||
}
|
||||
if (f == mr->efa_act) {
|
||||
flag |= SUBDIV_COARSE_FACE_FLAG_ACTIVE;
|
||||
}
|
||||
const int loopstart = BM_elem_index_get(f->l_first);
|
||||
flag = (uint)(loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET);
|
||||
}
|
||||
flags_data[i] = flag;
|
||||
}
|
||||
draw_subdiv_cache_extra_coarse_face_data_mapped(mesh, cache->bm, mr, flags_data);
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < mesh->totpoly; i++) {
|
||||
uint32_t flag = 0;
|
||||
if ((mesh->mpoly[i].flag & ME_SMOOTH) != 0) {
|
||||
flag = SUBDIV_COARSE_FACE_FLAG_SMOOTH;
|
||||
}
|
||||
flags_data[i] = (uint)(mesh->mpoly[i].loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET);
|
||||
}
|
||||
draw_subdiv_cache_extra_coarse_face_data_mesh(mesh, flags_data);
|
||||
}
|
||||
|
||||
/* Make sure updated data is re-uploaded. */
|
||||
|
|
|
@ -153,10 +153,10 @@ static void extract_weights_iter_poly_mesh(const MeshRenderData *mr,
|
|||
}
|
||||
|
||||
static void extract_weights_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *UNUSED(mr),
|
||||
const MeshRenderData *mr,
|
||||
struct MeshBatchCache *cache,
|
||||
void *buffer,
|
||||
void *UNUSED(data))
|
||||
void *_data)
|
||||
{
|
||||
Mesh *coarse_mesh = subdiv_cache->mesh;
|
||||
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
|
||||
|
@ -168,28 +168,20 @@ static void extract_weights_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
|||
GPU_vertbuf_init_build_on_device(vbo, &format, subdiv_cache->num_subdiv_loops);
|
||||
|
||||
GPUVertBuf *coarse_weights = GPU_vertbuf_calloc();
|
||||
GPU_vertbuf_init_with_format(coarse_weights, &format);
|
||||
GPU_vertbuf_data_alloc(coarse_weights, coarse_mesh->totloop);
|
||||
float *coarse_weights_data = static_cast<float *>(GPU_vertbuf_get_data(coarse_weights));
|
||||
extract_weights_init(mr, cache, coarse_weights, _data);
|
||||
|
||||
const DRW_MeshWeightState *wstate = &cache->weight_state;
|
||||
const MDeformVert *dverts = static_cast<const MDeformVert *>(
|
||||
CustomData_get_layer(&coarse_mesh->vdata, CD_MDEFORMVERT));
|
||||
|
||||
for (int i = 0; i < coarse_mesh->totpoly; i++) {
|
||||
const MPoly *mpoly = &coarse_mesh->mpoly[i];
|
||||
|
||||
for (int loop_index = mpoly->loopstart; loop_index < mpoly->loopstart + mpoly->totloop;
|
||||
loop_index++) {
|
||||
const MLoop *ml = &coarse_mesh->mloop[loop_index];
|
||||
|
||||
if (dverts != nullptr) {
|
||||
const MDeformVert *dvert = &dverts[ml->v];
|
||||
coarse_weights_data[loop_index] = evaluate_vertex_weight(dvert, wstate);
|
||||
}
|
||||
else {
|
||||
coarse_weights_data[loop_index] = evaluate_vertex_weight(nullptr, wstate);
|
||||
}
|
||||
if (mr->extract_type != MR_EXTRACT_BMESH) {
|
||||
for (int i = 0; i < coarse_mesh->totpoly; i++) {
|
||||
const MPoly *mpoly = &coarse_mesh->mpoly[i];
|
||||
extract_weights_iter_poly_mesh(mr, mpoly, i, _data);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BMIter f_iter;
|
||||
BMFace *efa;
|
||||
int face_index = 0;
|
||||
BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, face_index) {
|
||||
extract_weights_iter_poly_bm(mr, efa, face_index, _data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -163,6 +163,18 @@ static void reset_bezts(tGraphSliderOp *gso)
|
|||
ANIM_animdata_freelist(&anim_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get factor value and store it in RNA property.
|
||||
* Custom data of #wmOperator needs to contain #tGraphSliderOp.
|
||||
*/
|
||||
static float slider_factor_get_and_remember(wmOperator *op)
|
||||
{
|
||||
tGraphSliderOp *gso = op->customdata;
|
||||
const float factor = ED_slider_factor_get(gso->slider);
|
||||
RNA_property_float_set(op->ptr, gso->factor_prop, factor);
|
||||
return factor;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -378,8 +390,7 @@ static void decimate_modal_update(bContext *C, wmOperator *op)
|
|||
reset_bezts(gso);
|
||||
|
||||
/* Apply... */
|
||||
float factor = ED_slider_factor_get(gso->slider);
|
||||
RNA_property_float_set(op->ptr, gso->factor_prop, factor);
|
||||
const float factor = slider_factor_get_and_remember(op);
|
||||
/* We don't want to limit the decimation to a certain error margin. */
|
||||
const float error_sq_max = FLT_MAX;
|
||||
decimate_graph_keys(&gso->ac, factor, error_sq_max);
|
||||
|
@ -598,8 +609,7 @@ static void blend_to_neighbor_modal_update(bContext *C, wmOperator *op)
|
|||
/* Reset keyframe data to the state at invoke. */
|
||||
reset_bezts(gso);
|
||||
|
||||
const float factor = ED_slider_factor_get(gso->slider);
|
||||
RNA_property_float_set(op->ptr, gso->factor_prop, factor);
|
||||
const float factor = slider_factor_get_and_remember(op);
|
||||
blend_to_neighbor_graph_keys(&gso->ac, factor);
|
||||
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
|
||||
|
@ -725,7 +735,8 @@ static void breakdown_modal_update(bContext *C, wmOperator *op)
|
|||
|
||||
/* Reset keyframe data to the state at invoke. */
|
||||
reset_bezts(gso);
|
||||
breakdown_graph_keys(&gso->ac, ED_slider_factor_get(gso->slider));
|
||||
const float factor = slider_factor_get_and_remember(op);
|
||||
breakdown_graph_keys(&gso->ac, factor);
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
|
||||
}
|
||||
|
||||
|
@ -739,6 +750,7 @@ static int breakdown_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
|
||||
tGraphSliderOp *gso = op->customdata;
|
||||
gso->modal_update = breakdown_modal_update;
|
||||
gso->factor_prop = RNA_struct_find_property(op->ptr, "factor");
|
||||
breakdown_draw_status_header(C, gso);
|
||||
|
||||
return invoke_result;
|
||||
|
|
|
@ -1926,7 +1926,6 @@ static void sequencer_draw_display_buffer(const bContext *C,
|
|||
if (!glsl_used) {
|
||||
immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
|
||||
immUniformColor3f(1.0f, 1.0f, 1.0f);
|
||||
immUniform1i("image", 0);
|
||||
}
|
||||
|
||||
immBegin(GPU_PRIM_TRI_FAN, 4);
|
||||
|
|
|
@ -226,7 +226,7 @@ static int lib_id_fake_user_toggle_exec(bContext *C, wmOperator *op)
|
|||
|
||||
ID *id = (ID *)idptr.data;
|
||||
|
||||
if ((id->lib != nullptr) || (ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) {
|
||||
if (ID_IS_LINKED(id) || (ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Data-block type does not support fake user");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
|
|
@ -452,12 +452,21 @@ if(WITH_IMAGE_DDS)
|
|||
add_definitions(-DWITH_DDS)
|
||||
endif()
|
||||
|
||||
if(WITH_OPENCOLORIO)
|
||||
add_definitions(-DWITH_OCIO)
|
||||
endif()
|
||||
|
||||
blender_add_lib(bf_gpu "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
target_link_libraries(bf_gpu PUBLIC
|
||||
bf_draw_shaders
|
||||
bf_gpu_shaders
|
||||
)
|
||||
|
||||
if(WITH_OPENCOLORIO)
|
||||
target_link_libraries(bf_gpu PUBLIC bf_ocio_shaders)
|
||||
endif()
|
||||
|
||||
|
||||
if(CXX_WARN_NO_SUGGEST_OVERRIDE)
|
||||
target_compile_options(bf_gpu PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Wsuggest-override>)
|
||||
endif()
|
||||
|
|
|
@ -21,6 +21,9 @@ extern "C" {
|
|||
#define SHADER_SOURCE(datatoc, filename, filepath) extern char datatoc[];
|
||||
#include "glsl_draw_source_list.h"
|
||||
#include "glsl_gpu_source_list.h"
|
||||
#ifdef WITH_OCIO
|
||||
# include "glsl_ocio_source_list.h"
|
||||
#endif
|
||||
#undef SHADER_SOURCE
|
||||
}
|
||||
|
||||
|
@ -348,6 +351,9 @@ void gpu_shader_dependency_init()
|
|||
g_sources->add_new(filename, new GPUSource(filepath, filename, datatoc));
|
||||
#include "glsl_draw_source_list.h"
|
||||
#include "glsl_gpu_source_list.h"
|
||||
#ifdef WITH_OCIO
|
||||
# include "glsl_ocio_source_list.h"
|
||||
#endif
|
||||
#undef SHADER_SOURCE
|
||||
|
||||
int errors = 0;
|
||||
|
|
|
@ -277,8 +277,6 @@ void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo
|
|||
GPU_matrix_identity_set();
|
||||
GPU_matrix_identity_projection_set();
|
||||
immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_OVERLAYS_STEREO_MERGE);
|
||||
immUniform1i("overlayTexture", 0);
|
||||
immUniform1i("imageTexture", 1);
|
||||
int settings = stereo_format->display_mode;
|
||||
if (settings == S3D_DISPLAY_ANAGLYPH) {
|
||||
switch (stereo_format->anaglyph_type) {
|
||||
|
@ -432,8 +430,6 @@ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport,
|
|||
GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE);
|
||||
GPU_batch_uniform_1i(batch, "overlay", do_overlay_merge);
|
||||
GPU_batch_uniform_1i(batch, "display_transform", display_colorspace);
|
||||
GPU_batch_uniform_1i(batch, "image_texture", 0);
|
||||
GPU_batch_uniform_1i(batch, "overlays_texture", 1);
|
||||
}
|
||||
|
||||
GPU_texture_bind(color, 0);
|
||||
|
|
|
@ -16,6 +16,7 @@ GPU_SHADER_CREATE_INFO(gpu_shader_2D_image_overlays_merge)
|
|||
.push_constant(Type::MAT4, "ModelViewProjectionMatrix")
|
||||
.push_constant(Type::BOOL, "display_transform")
|
||||
.push_constant(Type::BOOL, "overlay")
|
||||
/* Sampler slots should match OCIO's. */
|
||||
.sampler(0, ImageType::FLOAT_2D, "image_texture")
|
||||
.sampler(1, ImageType::FLOAT_2D, "overlays_texture")
|
||||
.vertex_source("gpu_shader_2D_image_vert.glsl")
|
||||
|
|
|
@ -16,30 +16,46 @@
|
|||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include <Iex.h>
|
||||
#include <ImathBox.h>
|
||||
#include <ImfArray.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfCompression.h>
|
||||
#include <ImfCompressionAttribute.h>
|
||||
#include <ImfIO.h>
|
||||
#include <ImfInputFile.h>
|
||||
#include <ImfOutputFile.h>
|
||||
#include <ImfPixelType.h>
|
||||
#include <ImfStandardAttributes.h>
|
||||
#include <ImfStringAttribute.h>
|
||||
#include <ImfVersion.h>
|
||||
#include <half.h>
|
||||
/* The OpenEXR version can reliably be found in this header file from OpenEXR,
|
||||
* for both 2.x and 3.x:
|
||||
*/
|
||||
#include <OpenEXR/OpenEXRConfig.h>
|
||||
#define COMBINED_OPENEXR_VERSION \
|
||||
((10000 * OPENEXR_VERSION_MAJOR) + (100 * OPENEXR_VERSION_MINOR) + OPENEXR_VERSION_PATCH)
|
||||
|
||||
#if COMBINED_OPENEXR_VERSION >= 20599
|
||||
/* >=2.5.99 -> OpenEXR >=3.0 */
|
||||
# include <Imath/half.h>
|
||||
# include <OpenEXR/ImfFrameBuffer.h>
|
||||
# define exr_file_offset_t uint64_t
|
||||
#else
|
||||
/* OpenEXR 2.x, use the old locations. */
|
||||
# include <OpenEXR/half.h>
|
||||
# define exr_file_offset_t Int64
|
||||
#endif
|
||||
|
||||
#include <OpenEXR/Iex.h>
|
||||
#include <OpenEXR/ImfArray.h>
|
||||
#include <OpenEXR/ImfChannelList.h>
|
||||
#include <OpenEXR/ImfCompression.h>
|
||||
#include <OpenEXR/ImfCompressionAttribute.h>
|
||||
#include <OpenEXR/ImfIO.h>
|
||||
#include <OpenEXR/ImfInputFile.h>
|
||||
#include <OpenEXR/ImfOutputFile.h>
|
||||
#include <OpenEXR/ImfPixelType.h>
|
||||
#include <OpenEXR/ImfStandardAttributes.h>
|
||||
#include <OpenEXR/ImfStringAttribute.h>
|
||||
#include <OpenEXR/ImfVersion.h>
|
||||
|
||||
/* multiview/multipart */
|
||||
#include <ImfInputPart.h>
|
||||
#include <ImfMultiPartInputFile.h>
|
||||
#include <ImfMultiPartOutputFile.h>
|
||||
#include <ImfMultiView.h>
|
||||
#include <ImfOutputPart.h>
|
||||
#include <ImfPartHelper.h>
|
||||
#include <ImfPartType.h>
|
||||
#include <ImfTiledOutputPart.h>
|
||||
#include <OpenEXR/ImfInputPart.h>
|
||||
#include <OpenEXR/ImfMultiPartInputFile.h>
|
||||
#include <OpenEXR/ImfMultiPartOutputFile.h>
|
||||
#include <OpenEXR/ImfMultiView.h>
|
||||
#include <OpenEXR/ImfOutputPart.h>
|
||||
#include <OpenEXR/ImfPartHelper.h>
|
||||
#include <OpenEXR/ImfPartType.h>
|
||||
#include <OpenEXR/ImfTiledOutputPart.h>
|
||||
|
||||
#include "DNA_scene_types.h" /* For OpenEXR compression constants */
|
||||
|
||||
|
@ -115,12 +131,12 @@ class IMemStream : public Imf::IStream {
|
|||
return false;
|
||||
}
|
||||
|
||||
Int64 tellg() override
|
||||
exr_file_offset_t tellg() override
|
||||
{
|
||||
return _exrpos;
|
||||
}
|
||||
|
||||
void seekg(Int64 pos) override
|
||||
void seekg(exr_file_offset_t pos) override
|
||||
{
|
||||
_exrpos = pos;
|
||||
}
|
||||
|
@ -130,8 +146,8 @@ class IMemStream : public Imf::IStream {
|
|||
}
|
||||
|
||||
private:
|
||||
Int64 _exrpos;
|
||||
Int64 _exrsize;
|
||||
exr_file_offset_t _exrpos;
|
||||
exr_file_offset_t _exrsize;
|
||||
unsigned char *_exrbuf;
|
||||
};
|
||||
|
||||
|
@ -166,12 +182,12 @@ class IFileStream : public Imf::IStream {
|
|||
return check_error();
|
||||
}
|
||||
|
||||
Int64 tellg() override
|
||||
exr_file_offset_t tellg() override
|
||||
{
|
||||
return std::streamoff(ifs.tellg());
|
||||
}
|
||||
|
||||
void seekg(Int64 pos) override
|
||||
void seekg(exr_file_offset_t pos) override
|
||||
{
|
||||
ifs.seekg(pos);
|
||||
check_error();
|
||||
|
@ -215,19 +231,19 @@ class OMemStream : public OStream {
|
|||
ibuf->encodedsize += n;
|
||||
}
|
||||
|
||||
Int64 tellp() override
|
||||
exr_file_offset_t tellp() override
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
|
||||
void seekp(Int64 pos) override
|
||||
void seekp(exr_file_offset_t pos) override
|
||||
{
|
||||
offset = pos;
|
||||
ensure_size(offset);
|
||||
}
|
||||
|
||||
private:
|
||||
void ensure_size(Int64 size)
|
||||
void ensure_size(exr_file_offset_t size)
|
||||
{
|
||||
/* if buffer is too small increase it. */
|
||||
while (size > ibuf->encodedbuffersize) {
|
||||
|
@ -238,7 +254,7 @@ class OMemStream : public OStream {
|
|||
}
|
||||
|
||||
ImBuf *ibuf;
|
||||
Int64 offset;
|
||||
exr_file_offset_t offset;
|
||||
};
|
||||
|
||||
/* File Output Stream */
|
||||
|
@ -268,12 +284,12 @@ class OFileStream : public OStream {
|
|||
check_error();
|
||||
}
|
||||
|
||||
Int64 tellp() override
|
||||
exr_file_offset_t tellp() override
|
||||
{
|
||||
return std::streamoff(ofs.tellp());
|
||||
}
|
||||
|
||||
void seekp(Int64 pos) override
|
||||
void seekp(exr_file_offset_t pos) override
|
||||
{
|
||||
ofs.seekp(pos);
|
||||
check_error();
|
||||
|
|
|
@ -14,6 +14,10 @@ if(OPENCOLLADA_ANIMATION_CLIP)
|
|||
add_definitions(-DWITH_OPENCOLLADA_ANIMATION_CLIP)
|
||||
endif()
|
||||
|
||||
# In cmake version 3.21 and up, we can instead use the NO_CACHE option for
|
||||
# find_file so we don't need to clear it from the cache here.
|
||||
unset(OPENCOLLADA_ANIMATION_CLIP CACHE)
|
||||
|
||||
set(INC
|
||||
.
|
||||
../../blenkernel
|
||||
|
|
|
@ -330,7 +330,7 @@ enum {
|
|||
/* 2 characters for ID code and 64 for actual name */
|
||||
#define MAX_ID_NAME 66
|
||||
|
||||
/* ID_Runtime.remapping_status */
|
||||
/* ID_Runtime_Remap.status */
|
||||
enum {
|
||||
/** new_id is directly linked in current .blend. */
|
||||
ID_REMAP_IS_LINKED_DIRECT = 1 << 0,
|
||||
|
|
|
@ -13,6 +13,33 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace blender::bke {
|
||||
class CurvesGeometryRuntime;
|
||||
} // namespace blender::bke
|
||||
using CurvesGeometryRuntimeHandle = blender::bke::CurvesGeometryRuntime;
|
||||
#else
|
||||
typedef struct CurvesGeometryRuntimeHandle CurvesGeometryRuntimeHandle;
|
||||
#endif
|
||||
|
||||
typedef enum CurveType {
|
||||
CURVE_TYPE_CATMULL_ROM = 0,
|
||||
CURVE_TYPE_POLY = 1,
|
||||
CURVE_TYPE_BEZIER = 2,
|
||||
CURVE_TYPE_NURBS = 3,
|
||||
} CurveType;
|
||||
|
||||
typedef enum HandleType {
|
||||
/** The handle can be moved anywhere, and doesn't influence the point's other handle. */
|
||||
BEZIER_HANDLE_FREE = 0,
|
||||
/** The location is automatically calculated to be smooth. */
|
||||
BEZIER_HANDLE_AUTO = 1,
|
||||
/** The location is calculated to point to the next/previous control point. */
|
||||
BEZIER_HANDLE_VECTOR = 2,
|
||||
/** The location is constrained to point in the opposite direction as the other handle. */
|
||||
BEZIER_HANDLE_ALIGN = 3,
|
||||
} HandleType;
|
||||
|
||||
/**
|
||||
* A reusable data structure for geometry consisting of many curves. All control point data is
|
||||
* stored contiguously for better efficiency. Data for each curve is stored as a slice of the
|
||||
|
@ -33,6 +60,12 @@ typedef struct CurvesGeometry {
|
|||
*/
|
||||
float *radius;
|
||||
|
||||
/**
|
||||
* The type of each curve. #CurveType.
|
||||
* \note This data is owned by #curve_data.
|
||||
*/
|
||||
int8_t *curve_type;
|
||||
|
||||
/**
|
||||
* The start index of each curve in the point data. The size of each curve can be calculated by
|
||||
* subtracting the offset from the next offset. That is valid even for the last curve because
|
||||
|
@ -40,7 +73,7 @@ typedef struct CurvesGeometry {
|
|||
*
|
||||
* \note This is *not* stored in #CustomData because its size is one larger than #curve_data.
|
||||
*/
|
||||
int *offsets;
|
||||
int *curve_offsets;
|
||||
|
||||
/**
|
||||
* All attributes stored on control points (#ATTR_DOMAIN_POINT).
|
||||
|
@ -60,6 +93,11 @@ typedef struct CurvesGeometry {
|
|||
* The number of curves in the data-block.
|
||||
*/
|
||||
int curve_size;
|
||||
|
||||
/**
|
||||
* Runtime data for curves, stored as a pointer to allow defining this as a C++ class.
|
||||
*/
|
||||
CurvesGeometryRuntimeHandle *runtime;
|
||||
} CurvesGeometry;
|
||||
|
||||
typedef struct Curves {
|
||||
|
|
|
@ -1988,7 +1988,7 @@ extern const char *RE_engine_id_CYCLES;
|
|||
((v3d == NULL) || (((1 << (base)->object->type) & (v3d)->object_type_exclude_select) == 0)) && \
|
||||
(((base)->flag & BASE_SELECTABLE) != 0))
|
||||
#define BASE_SELECTED(v3d, base) (BASE_VISIBLE(v3d, base) && (((base)->flag & BASE_SELECTED) != 0))
|
||||
#define BASE_EDITABLE(v3d, base) (BASE_VISIBLE(v3d, base) && ((base)->object->id.lib == NULL))
|
||||
#define BASE_EDITABLE(v3d, base) (BASE_VISIBLE(v3d, base) && !ID_IS_LINKED((base)->object))
|
||||
#define BASE_SELECTED_EDITABLE(v3d, base) \
|
||||
(BASE_EDITABLE(v3d, base) && (((base)->flag & BASE_SELECTED) != 0))
|
||||
|
||||
|
|
|
@ -106,8 +106,23 @@ typedef enum eXrPoseFlag {
|
|||
XR_POSE_AIM = (1 << 1),
|
||||
} eXrPoseFlag;
|
||||
|
||||
/**
|
||||
* The following user and component path lengths are dependent on OpenXR's XR_MAX_PATH_LENGTH
|
||||
* (256). A user path will be combined with a component path to identify an action binding, and
|
||||
* that combined path should also have a max of XR_MAX_PATH_LENGTH (e.g. user_path =
|
||||
* /user/hand/left, component_path = /input/trigger/value, full_path =
|
||||
* /user/hand/left/input/trigger/value).
|
||||
*/
|
||||
#define XR_MAX_USER_PATH_LENGTH 64
|
||||
#define XR_MAX_COMPONENT_PATH_LENGTH 192
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
typedef struct XrComponentPath {
|
||||
struct XrComponentPath *next, *prev;
|
||||
char path[192]; /* XR_MAX_COMPONENT_PATH_LENGTH */
|
||||
} XrComponentPath;
|
||||
|
||||
typedef struct XrActionMapBinding {
|
||||
struct XrActionMapBinding *next, *prev;
|
||||
|
||||
|
@ -117,8 +132,7 @@ typedef struct XrActionMapBinding {
|
|||
/** OpenXR interaction profile path. */
|
||||
char profile[256];
|
||||
/** OpenXR component paths. */
|
||||
char component_path0[192];
|
||||
char component_path1[192];
|
||||
ListBase component_paths; /* XrComponentPath */
|
||||
|
||||
/** Input threshold/region. */
|
||||
float float_threshold;
|
||||
|
@ -132,6 +146,11 @@ typedef struct XrActionMapBinding {
|
|||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
typedef struct XrUserPath {
|
||||
struct XrUserPath *next, *prev;
|
||||
char path[64]; /* XR_MAX_USER_PATH_LENGTH */
|
||||
} XrUserPath;
|
||||
|
||||
typedef struct XrActionMapItem {
|
||||
struct XrActionMapItem *next, *prev;
|
||||
|
||||
|
@ -142,8 +161,7 @@ typedef struct XrActionMapItem {
|
|||
char _pad[7];
|
||||
|
||||
/** OpenXR user paths. */
|
||||
char user_path0[64];
|
||||
char user_path1[64];
|
||||
ListBase user_paths; /* XrUserPath */
|
||||
|
||||
/** Operator to be called on XR events. */
|
||||
char op[64]; /* OP_MAX_TYPENAME */
|
||||
|
|
|
@ -43,7 +43,7 @@ static void rna_Curves_curve_offset_data_begin(CollectionPropertyIterator *iter,
|
|||
{
|
||||
const Curves *curves = rna_curves(ptr);
|
||||
rna_iterator_array_begin(iter,
|
||||
(void *)curves->geometry.offsets,
|
||||
(void *)curves->geometry.curve_offsets,
|
||||
sizeof(int),
|
||||
curves->geometry.curve_size + 1,
|
||||
false,
|
||||
|
@ -95,7 +95,7 @@ static char *rna_CurvePoint_path(PointerRNA *ptr)
|
|||
static int rna_CurveSlice_index_get(PointerRNA *ptr)
|
||||
{
|
||||
Curves *curves = rna_curves(ptr);
|
||||
return (int)((int *)ptr->data - curves->geometry.offsets);
|
||||
return (int)((int *)ptr->data - curves->geometry.curve_offsets);
|
||||
}
|
||||
|
||||
static char *rna_CurveSlice_path(PointerRNA *ptr)
|
||||
|
@ -220,7 +220,7 @@ static void rna_def_curves(BlenderRNA *brna)
|
|||
/* Point and Curve RNA API helpers. */
|
||||
|
||||
prop = RNA_def_property(srna, "curves", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "geometry.offsets", "geometry.curve_size");
|
||||
RNA_def_property_collection_sdna(prop, NULL, "geometry.curve_offsets", "geometry.curve_size");
|
||||
RNA_def_property_struct_type(prop, "CurveSlice");
|
||||
RNA_def_property_ui_text(prop, "Curves", "All curves in the data-block");
|
||||
|
||||
|
@ -243,7 +243,7 @@ static void rna_def_curves(BlenderRNA *brna)
|
|||
RNA_define_verify_sdna(1);
|
||||
|
||||
prop = RNA_def_property(srna, "curve_offset_data", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "geometry.offsets", NULL);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "geometry.curve_offsets", NULL);
|
||||
RNA_def_property_struct_type(prop, "IntAttributeValue");
|
||||
RNA_def_property_collection_funcs(prop,
|
||||
"rna_Curves_curve_offset_data_begin",
|
||||
|
|
|
@ -26,7 +26,6 @@ const EnumPropertyItem rna_enum_volume_grid_data_type_items[] = {
|
|||
{VOLUME_GRID_INT, "INT", 0, "Integer", "32-bit integer"},
|
||||
{VOLUME_GRID_INT64, "INT64", 0, "Integer 64-bit", "64-bit integer"},
|
||||
{VOLUME_GRID_MASK, "MASK", 0, "Mask", "No data, boolean mask of active voxels"},
|
||||
{VOLUME_GRID_STRING, "STRING", 0, "String", "Text string"},
|
||||
{VOLUME_GRID_VECTOR_FLOAT, "VECTOR_FLOAT", 0, "Float Vector", "3D float vector"},
|
||||
{VOLUME_GRID_VECTOR_DOUBLE, "VECTOR_DOUBLE", 0, "Double Vector", "3D double vector"},
|
||||
{VOLUME_GRID_VECTOR_INT, "VECTOR_INT", 0, "Integer Vector", "3D integer vector"},
|
||||
|
|
|
@ -46,6 +46,43 @@ static wmXrData *rna_XrSession_wm_xr_data_get(PointerRNA *ptr)
|
|||
/** \name XR Action Map
|
||||
* \{ */
|
||||
|
||||
static XrComponentPath *rna_XrComponentPath_new(XrActionMapBinding *amb, const char *path_str)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
XrComponentPath *component_path = MEM_callocN(sizeof(XrComponentPath), __func__);
|
||||
BLI_strncpy(component_path->path, path_str, sizeof(component_path->path));
|
||||
BLI_addtail(&amb->component_paths, component_path);
|
||||
return component_path;
|
||||
# else
|
||||
UNUSED_VARS(amb, path_str);
|
||||
return NULL;
|
||||
# endif
|
||||
}
|
||||
|
||||
static void rna_XrComponentPath_remove(XrActionMapBinding *amb, PointerRNA *component_path_ptr)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
XrComponentPath *component_path = component_path_ptr->data;
|
||||
int idx = BLI_findindex(&amb->component_paths, component_path);
|
||||
if (idx != -1) {
|
||||
BLI_freelinkN(&amb->component_paths, component_path);
|
||||
}
|
||||
RNA_POINTER_INVALIDATE(component_path_ptr);
|
||||
# else
|
||||
UNUSED_VARS(amb, component_path_ptr);
|
||||
# endif
|
||||
}
|
||||
|
||||
static XrComponentPath *rna_XrComponentPath_find(XrActionMapBinding *amb, const char *path_str)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
return BLI_findstring(&amb->component_paths, path_str, offsetof(XrComponentPath, path));
|
||||
# else
|
||||
UNUSED_VARS(amb, path_str);
|
||||
return NULL;
|
||||
# endif
|
||||
}
|
||||
|
||||
static XrActionMapBinding *rna_XrActionMapBinding_new(XrActionMapItem *ami,
|
||||
const char *name,
|
||||
bool replace_existing)
|
||||
|
@ -99,6 +136,28 @@ static XrActionMapBinding *rna_XrActionMapBinding_find(XrActionMapItem *ami, con
|
|||
# endif
|
||||
}
|
||||
|
||||
static void rna_XrActionMapBinding_component_paths_begin(CollectionPropertyIterator *iter,
|
||||
PointerRNA *ptr)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
XrActionMapBinding *amb = (XrActionMapBinding *)ptr->data;
|
||||
rna_iterator_listbase_begin(iter, &amb->component_paths, NULL);
|
||||
# else
|
||||
UNUSED_VARS(iter, ptr);
|
||||
# endif
|
||||
}
|
||||
|
||||
static int rna_XrActionMapBinding_component_paths_length(PointerRNA *ptr)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
XrActionMapBinding *amb = (XrActionMapBinding *)ptr->data;
|
||||
return BLI_listbase_count(&amb->component_paths);
|
||||
# else
|
||||
UNUSED_VARS(ptr);
|
||||
return 0;
|
||||
# endif
|
||||
}
|
||||
|
||||
static int rna_XrActionMapBinding_axis0_region_get(PointerRNA *ptr)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
|
@ -174,6 +233,43 @@ static void rna_XrActionMapBinding_name_update(Main *bmain, Scene *UNUSED(scene)
|
|||
# endif
|
||||
}
|
||||
|
||||
static XrUserPath *rna_XrUserPath_new(XrActionMapItem *ami, const char *path_str)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
XrUserPath *user_path = MEM_callocN(sizeof(XrUserPath), __func__);
|
||||
BLI_strncpy(user_path->path, path_str, sizeof(user_path->path));
|
||||
BLI_addtail(&ami->user_paths, user_path);
|
||||
return user_path;
|
||||
# else
|
||||
UNUSED_VARS(ami, path_str);
|
||||
return NULL;
|
||||
# endif
|
||||
}
|
||||
|
||||
static void rna_XrUserPath_remove(XrActionMapItem *ami, PointerRNA *user_path_ptr)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
XrUserPath *user_path = user_path_ptr->data;
|
||||
int idx = BLI_findindex(&ami->user_paths, user_path);
|
||||
if (idx != -1) {
|
||||
BLI_freelinkN(&ami->user_paths, user_path);
|
||||
}
|
||||
RNA_POINTER_INVALIDATE(user_path_ptr);
|
||||
# else
|
||||
UNUSED_VARS(ami, user_path_ptr);
|
||||
# endif
|
||||
}
|
||||
|
||||
static XrUserPath *rna_XrUserPath_find(XrActionMapItem *ami, const char *path_str)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
return BLI_findstring(&ami->user_paths, path_str, offsetof(XrUserPath, path));
|
||||
# else
|
||||
UNUSED_VARS(ami, path_str);
|
||||
return NULL;
|
||||
# endif
|
||||
}
|
||||
|
||||
static XrActionMapItem *rna_XrActionMapItem_new(XrActionMap *am,
|
||||
const char *name,
|
||||
bool replace_existing)
|
||||
|
@ -222,6 +318,27 @@ static XrActionMapItem *rna_XrActionMapItem_find(XrActionMap *am, const char *na
|
|||
# endif
|
||||
}
|
||||
|
||||
static void rna_XrActionMapItem_user_paths_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
XrActionMapItem *ami = (XrActionMapItem *)ptr->data;
|
||||
rna_iterator_listbase_begin(iter, &ami->user_paths, NULL);
|
||||
# else
|
||||
UNUSED_VARS(iter, ptr);
|
||||
# endif
|
||||
}
|
||||
|
||||
static int rna_XrActionMapItem_user_paths_length(PointerRNA *ptr)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
XrActionMapItem *ami = (XrActionMapItem *)ptr->data;
|
||||
return BLI_listbase_count(&ami->user_paths);
|
||||
# else
|
||||
UNUSED_VARS(ptr);
|
||||
return 0;
|
||||
# endif
|
||||
}
|
||||
|
||||
static void rna_XrActionMapItem_op_name_get(PointerRNA *ptr, char *value)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
|
@ -395,6 +512,27 @@ static void rna_XrActionMapItem_pose_is_controller_aim_set(PointerRNA *ptr, bool
|
|||
# endif
|
||||
}
|
||||
|
||||
static void rna_XrActionMapItem_bindings_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
XrActionMapItem *ami = (XrActionMapItem *)ptr->data;
|
||||
rna_iterator_listbase_begin(iter, &ami->bindings, NULL);
|
||||
# else
|
||||
UNUSED_VARS(iter, ptr);
|
||||
# endif
|
||||
}
|
||||
|
||||
static int rna_XrActionMapItem_bindings_length(PointerRNA *ptr)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
XrActionMapItem *ami = (XrActionMapItem *)ptr->data;
|
||||
return BLI_listbase_count(&ami->bindings);
|
||||
# else
|
||||
UNUSED_VARS(ptr);
|
||||
return 0;
|
||||
# endif
|
||||
}
|
||||
|
||||
static void rna_XrActionMapItem_name_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
|
@ -471,6 +609,27 @@ static XrActionMap *rna_XrActionMap_find(PointerRNA *ptr, const char *name)
|
|||
# endif
|
||||
}
|
||||
|
||||
static void rna_XrActionMap_items_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
XrActionMap *actionmap = (XrActionMap *)ptr->data;
|
||||
rna_iterator_listbase_begin(iter, &actionmap->items, NULL);
|
||||
# else
|
||||
UNUSED_VARS(iter, ptr);
|
||||
# endif
|
||||
}
|
||||
|
||||
static int rna_XrActionMap_items_length(PointerRNA *ptr)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
XrActionMap *actionmap = (XrActionMap *)ptr->data;
|
||||
return BLI_listbase_count(&actionmap->items);
|
||||
# else
|
||||
UNUSED_VARS(ptr);
|
||||
return 0;
|
||||
# endif
|
||||
}
|
||||
|
||||
static void rna_XrActionMap_name_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
|
@ -576,26 +735,8 @@ static bool rna_XrSessionState_action_create(bContext *C,
|
|||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
unsigned int count_subaction_paths = 0;
|
||||
const char *subaction_paths[2];
|
||||
|
||||
if (ami->user_path0[0]) {
|
||||
subaction_paths[0] = ami->user_path0;
|
||||
++count_subaction_paths;
|
||||
|
||||
if (ami->user_path1[0]) {
|
||||
subaction_paths[1] = ami->user_path1;
|
||||
++count_subaction_paths;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ami->user_path1[0]) {
|
||||
subaction_paths[0] = ami->user_path1;
|
||||
++count_subaction_paths;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
if (BLI_listbase_is_empty(&ami->user_paths)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool is_float_action = (ami->type == XR_FLOAT_INPUT || ami->type == XR_VECTOR2F_INPUT);
|
||||
|
@ -621,8 +762,7 @@ static bool rna_XrSessionState_action_create(bContext *C,
|
|||
actionmap->name,
|
||||
ami->name,
|
||||
ami->type,
|
||||
count_subaction_paths,
|
||||
subaction_paths,
|
||||
&ami->user_paths,
|
||||
ot,
|
||||
op_properties,
|
||||
is_button_action ? ami->haptic_name : NULL,
|
||||
|
@ -645,30 +785,10 @@ static bool rna_XrSessionState_action_binding_create(bContext *C,
|
|||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
unsigned int count_subaction_paths = 0;
|
||||
const char *subaction_paths[2];
|
||||
const char *component_paths[2];
|
||||
|
||||
if (ami->user_path0[0]) {
|
||||
subaction_paths[0] = ami->user_path0;
|
||||
component_paths[0] = amb->component_path0;
|
||||
++count_subaction_paths;
|
||||
|
||||
if (ami->user_path1[0]) {
|
||||
subaction_paths[1] = ami->user_path1;
|
||||
component_paths[1] = amb->component_path1;
|
||||
++count_subaction_paths;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ami->user_path1[0]) {
|
||||
subaction_paths[0] = ami->user_path1;
|
||||
component_paths[0] = amb->component_path1;
|
||||
++count_subaction_paths;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
const int count_user_paths = BLI_listbase_count(&ami->user_paths);
|
||||
const int count_component_paths = BLI_listbase_count(&amb->component_paths);
|
||||
if (count_user_paths < 1 || (count_user_paths != count_component_paths)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool is_float_action = (ami->type == XR_FLOAT_INPUT || ami->type == XR_VECTOR2F_INPUT);
|
||||
|
@ -695,9 +815,8 @@ static bool rna_XrSessionState_action_binding_create(bContext *C,
|
|||
actionmap->name,
|
||||
ami->name,
|
||||
amb->profile,
|
||||
count_subaction_paths,
|
||||
subaction_paths,
|
||||
component_paths,
|
||||
&ami->user_paths,
|
||||
&amb->component_paths,
|
||||
is_float_action ? float_thresholds : NULL,
|
||||
is_button_action ? axis_flags : NULL,
|
||||
is_pose_action ? poses : NULL);
|
||||
|
@ -954,6 +1073,18 @@ static void rna_XrSessionState_actionmaps_begin(CollectionPropertyIterator *iter
|
|||
# endif
|
||||
}
|
||||
|
||||
static int rna_XrSessionState_actionmaps_length(PointerRNA *ptr)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr);
|
||||
ListBase *lb = WM_xr_actionmaps_get(xr->runtime);
|
||||
return BLI_listbase_count(lb);
|
||||
# else
|
||||
UNUSED_VARS(ptr);
|
||||
return 0;
|
||||
# endif
|
||||
}
|
||||
|
||||
static int rna_XrSessionState_active_actionmap_get(PointerRNA *ptr)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
|
@ -1240,6 +1371,42 @@ static const EnumPropertyItem rna_enum_xr_axis1_flags[] = {
|
|||
/** \name XR Action Map
|
||||
* \{ */
|
||||
|
||||
static void rna_def_xr_component_paths(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
{
|
||||
StructRNA *srna;
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *parm;
|
||||
|
||||
RNA_def_property_srna(cprop, "XrComponentPaths");
|
||||
srna = RNA_def_struct(brna, "XrComponentPaths", NULL);
|
||||
RNA_def_struct_sdna(srna, "XrActionMapBinding");
|
||||
RNA_def_struct_ui_text(srna, "XR Component Paths", "Collection of OpenXR component paths");
|
||||
|
||||
func = RNA_def_function(srna, "new", "rna_XrComponentPath_new");
|
||||
parm = RNA_def_string(
|
||||
func, "path", NULL, XR_MAX_COMPONENT_PATH_LENGTH, "Path", "OpenXR component path");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
parm = RNA_def_pointer(
|
||||
func, "component_path", "XrComponentPath", "Component Path", "Added component path");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func = RNA_def_function(srna, "remove", "rna_XrComponentPath_remove");
|
||||
parm = RNA_def_pointer(func, "component_path", "XrComponentPath", "Component Path", "");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
|
||||
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
|
||||
|
||||
func = RNA_def_function(srna, "find", "rna_XrComponentPath_find");
|
||||
parm = RNA_def_string(
|
||||
func, "path", NULL, XR_MAX_COMPONENT_PATH_LENGTH, "Path", "OpenXR component path");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
parm = RNA_def_pointer(func,
|
||||
"component_path",
|
||||
"XrComponentPath",
|
||||
"Component Path",
|
||||
"The component path with the given path");
|
||||
RNA_def_function_return(func, parm);
|
||||
}
|
||||
|
||||
static void rna_def_xr_actionmap_bindings(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
@ -1289,6 +1456,36 @@ static void rna_def_xr_actionmap_bindings(BlenderRNA *brna, PropertyRNA *cprop)
|
|||
RNA_def_function_return(func, parm);
|
||||
}
|
||||
|
||||
static void rna_def_xr_user_paths(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
{
|
||||
StructRNA *srna;
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *parm;
|
||||
|
||||
RNA_def_property_srna(cprop, "XrUserPaths");
|
||||
srna = RNA_def_struct(brna, "XrUserPaths", NULL);
|
||||
RNA_def_struct_sdna(srna, "XrActionMapItem");
|
||||
RNA_def_struct_ui_text(srna, "XR User Paths", "Collection of OpenXR user paths");
|
||||
|
||||
func = RNA_def_function(srna, "new", "rna_XrUserPath_new");
|
||||
parm = RNA_def_string(func, "path", NULL, XR_MAX_USER_PATH_LENGTH, "Path", "OpenXR user path");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
parm = RNA_def_pointer(func, "user_path", "XrUserPath", "User Path", "Added user path");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func = RNA_def_function(srna, "remove", "rna_XrUserPath_remove");
|
||||
parm = RNA_def_pointer(func, "user_path", "XrUserPath", "User Path", "");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
|
||||
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
|
||||
|
||||
func = RNA_def_function(srna, "find", "rna_XrUserPath_find");
|
||||
parm = RNA_def_string(func, "path", NULL, XR_MAX_USER_PATH_LENGTH, "Path", "OpenXR user path");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
parm = RNA_def_pointer(
|
||||
func, "user_path", "XrUserPath", "User Path", "The user path with the given path");
|
||||
RNA_def_function_return(func, parm);
|
||||
}
|
||||
|
||||
static void rna_def_xr_actionmap_items(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
@ -1404,6 +1601,15 @@ static void rna_def_xr_actionmap(BlenderRNA *brna)
|
|||
prop = RNA_def_property(srna, "actionmap_items", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "items", NULL);
|
||||
RNA_def_property_struct_type(prop, "XrActionMapItem");
|
||||
RNA_def_property_collection_funcs(prop,
|
||||
"rna_XrActionMap_items_begin",
|
||||
"rna_iterator_listbase_next",
|
||||
"rna_iterator_listbase_end",
|
||||
"rna_iterator_listbase_get",
|
||||
"rna_XrActionMap_items_length",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Items",
|
||||
|
@ -1414,6 +1620,15 @@ static void rna_def_xr_actionmap(BlenderRNA *brna)
|
|||
RNA_def_property_int_sdna(prop, NULL, "selitem");
|
||||
RNA_def_property_ui_text(prop, "Selected Item", "");
|
||||
|
||||
/* XrUserPath */
|
||||
srna = RNA_def_struct(brna, "XrUserPath", NULL);
|
||||
RNA_def_struct_sdna(srna, "XrUserPath");
|
||||
RNA_def_struct_ui_text(srna, "XR User Path", "");
|
||||
|
||||
prop = RNA_def_property(srna, "path", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_maxlength(prop, XR_MAX_USER_PATH_LENGTH);
|
||||
RNA_def_property_ui_text(prop, "Path", "OpenXR user path");
|
||||
|
||||
/* XrActionMapItem */
|
||||
srna = RNA_def_struct(brna, "XrActionMapItem", NULL);
|
||||
RNA_def_struct_sdna(srna, "XrActionMapItem");
|
||||
|
@ -1429,13 +1644,19 @@ static void rna_def_xr_actionmap(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Type", "Action type");
|
||||
RNA_def_property_update(prop, 0, "rna_XrActionMapItem_update");
|
||||
|
||||
prop = RNA_def_property(srna, "user_path0", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_maxlength(prop, 64);
|
||||
RNA_def_property_ui_text(prop, "User Path 0", "OpenXR user path");
|
||||
|
||||
prop = RNA_def_property(srna, "user_path1", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_maxlength(prop, 64);
|
||||
RNA_def_property_ui_text(prop, "User Path 1", "OpenXR user path");
|
||||
prop = RNA_def_property(srna, "user_paths", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "XrUserPath");
|
||||
RNA_def_property_collection_funcs(prop,
|
||||
"rna_XrActionMapItem_user_paths_begin",
|
||||
"rna_iterator_listbase_next",
|
||||
"rna_iterator_listbase_end",
|
||||
"rna_iterator_listbase_get",
|
||||
"rna_XrActionMapItem_user_paths_length",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
RNA_def_property_ui_text(prop, "User Paths", "OpenXR user paths");
|
||||
rna_def_xr_user_paths(brna, prop);
|
||||
|
||||
prop = RNA_def_property(srna, "op", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_maxlength(prop, OP_MAX_TYPENAME);
|
||||
|
@ -1520,6 +1741,15 @@ static void rna_def_xr_actionmap(BlenderRNA *brna)
|
|||
|
||||
prop = RNA_def_property(srna, "bindings", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "XrActionMapBinding");
|
||||
RNA_def_property_collection_funcs(prop,
|
||||
"rna_XrActionMapItem_bindings_begin",
|
||||
"rna_iterator_listbase_next",
|
||||
"rna_iterator_listbase_end",
|
||||
"rna_iterator_listbase_get",
|
||||
"rna_XrActionMapItem_bindings_length",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Bindings", "Bindings for the action map item, mapping the action to an XR input");
|
||||
rna_def_xr_actionmap_bindings(brna, prop);
|
||||
|
@ -1528,6 +1758,15 @@ static void rna_def_xr_actionmap(BlenderRNA *brna)
|
|||
RNA_def_property_int_sdna(prop, NULL, "selbinding");
|
||||
RNA_def_property_ui_text(prop, "Selected Binding", "Currently selected binding");
|
||||
|
||||
/* XrComponentPath */
|
||||
srna = RNA_def_struct(brna, "XrComponentPath", NULL);
|
||||
RNA_def_struct_sdna(srna, "XrComponentPath");
|
||||
RNA_def_struct_ui_text(srna, "XR Component Path", "");
|
||||
|
||||
prop = RNA_def_property(srna, "path", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_maxlength(prop, XR_MAX_COMPONENT_PATH_LENGTH);
|
||||
RNA_def_property_ui_text(prop, "Path", "OpenXR component path");
|
||||
|
||||
/* XrActionMapBinding */
|
||||
srna = RNA_def_struct(brna, "XrActionMapBinding", NULL);
|
||||
RNA_def_struct_sdna(srna, "XrActionMapBinding");
|
||||
|
@ -1542,13 +1781,19 @@ static void rna_def_xr_actionmap(BlenderRNA *brna)
|
|||
RNA_def_property_string_maxlength(prop, 256);
|
||||
RNA_def_property_ui_text(prop, "Profile", "OpenXR interaction profile path");
|
||||
|
||||
prop = RNA_def_property(srna, "component_path0", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_maxlength(prop, 192);
|
||||
RNA_def_property_ui_text(prop, "Component Path 0", "OpenXR component path");
|
||||
|
||||
prop = RNA_def_property(srna, "component_path1", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_maxlength(prop, 192);
|
||||
RNA_def_property_ui_text(prop, "Component Path 1", "OpenXR component path");
|
||||
prop = RNA_def_property(srna, "component_paths", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "XrComponentPath");
|
||||
RNA_def_property_collection_funcs(prop,
|
||||
"rna_XrActionMapBinding_component_paths_begin",
|
||||
"rna_iterator_listbase_next",
|
||||
"rna_iterator_listbase_end",
|
||||
"rna_iterator_listbase_get",
|
||||
"rna_XrActionMapBinding_component_paths_length",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
RNA_def_property_ui_text(prop, "Component Paths", "OpenXR component paths");
|
||||
rna_def_xr_component_paths(brna, prop);
|
||||
|
||||
prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "float_threshold");
|
||||
|
@ -1812,7 +2057,7 @@ static void rna_def_xr_session_state(BlenderRNA *brna)
|
|||
RNA_def_function_flag(func, FUNC_NO_SELF);
|
||||
parm = RNA_def_pointer(func, "context", "Context", "", "");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_string(func, "action_set", NULL, 64, "Action Set", "Action set name");
|
||||
parm = RNA_def_string(func, "action_set", NULL, MAX_NAME, "Action Set", "Action set name");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_boolean(func, "result", 0, "Result", "");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
@ -1823,19 +2068,19 @@ static void rna_def_xr_session_state(BlenderRNA *brna)
|
|||
RNA_def_function_flag(func, FUNC_NO_SELF);
|
||||
parm = RNA_def_pointer(func, "context", "Context", "", "");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_string(func, "action_set", NULL, 64, "Action Set", "Action set name");
|
||||
parm = RNA_def_string(func, "action_set", NULL, MAX_NAME, "Action Set", "Action set name");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_string(func,
|
||||
"grip_action",
|
||||
NULL,
|
||||
64,
|
||||
MAX_NAME,
|
||||
"Grip Action",
|
||||
"Name of the action representing the controller grips");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_string(func,
|
||||
"aim_action",
|
||||
NULL,
|
||||
64,
|
||||
MAX_NAME,
|
||||
"Aim Action",
|
||||
"Name of the action representing the controller aims");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
|
@ -1847,11 +2092,12 @@ static void rna_def_xr_session_state(BlenderRNA *brna)
|
|||
RNA_def_function_flag(func, FUNC_NO_SELF);
|
||||
parm = RNA_def_pointer(func, "context", "Context", "", "");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_string(func, "action_set_name", NULL, 64, "Action Set", "Action set name");
|
||||
parm = RNA_def_string(func, "action_set_name", NULL, MAX_NAME, "Action Set", "Action set name");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_string(func, "action_name", NULL, 64, "Action", "Action name");
|
||||
parm = RNA_def_string(func, "action_name", NULL, MAX_NAME, "Action", "Action name");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_string(func, "user_path", NULL, 64, "User Path", "OpenXR user path");
|
||||
parm = RNA_def_string(
|
||||
func, "user_path", NULL, XR_MAX_USER_PATH_LENGTH, "User Path", "OpenXR user path");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_float_array(
|
||||
func,
|
||||
|
@ -1871,15 +2117,15 @@ static void rna_def_xr_session_state(BlenderRNA *brna)
|
|||
RNA_def_function_flag(func, FUNC_NO_SELF);
|
||||
parm = RNA_def_pointer(func, "context", "Context", "", "");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_string(func, "action_set_name", NULL, 64, "Action Set", "Action set name");
|
||||
parm = RNA_def_string(func, "action_set_name", NULL, MAX_NAME, "Action Set", "Action set name");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_string(func, "action_name", NULL, 64, "Action", "Action name");
|
||||
parm = RNA_def_string(func, "action_name", NULL, MAX_NAME, "Action", "Action name");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_string(
|
||||
func,
|
||||
"user_path",
|
||||
NULL,
|
||||
64,
|
||||
XR_MAX_USER_PATH_LENGTH,
|
||||
"User Path",
|
||||
"Optional OpenXR user path. If not set, the action will be applied to all paths");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
|
@ -1922,15 +2168,15 @@ static void rna_def_xr_session_state(BlenderRNA *brna)
|
|||
RNA_def_function_flag(func, FUNC_NO_SELF);
|
||||
parm = RNA_def_pointer(func, "context", "Context", "", "");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_string(func, "action_set_name", NULL, 64, "Action Set", "Action set name");
|
||||
parm = RNA_def_string(func, "action_set_name", NULL, MAX_NAME, "Action Set", "Action set name");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_string(func, "action_name", NULL, 64, "Action", "Action name");
|
||||
parm = RNA_def_string(func, "action_name", NULL, MAX_NAME, "Action", "Action name");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_string(
|
||||
func,
|
||||
"user_path",
|
||||
NULL,
|
||||
64,
|
||||
XR_MAX_USER_PATH_LENGTH,
|
||||
"User Path",
|
||||
"Optional OpenXR user path. If not set, the action will be stopped for all paths");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
|
@ -2068,16 +2314,16 @@ static void rna_def_xr_session_state(BlenderRNA *brna)
|
|||
"Additional scale multiplier to apply to base scale when determining viewer scale");
|
||||
|
||||
prop = RNA_def_property(srna, "actionmaps", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "XrActionMap");
|
||||
RNA_def_property_collection_funcs(prop,
|
||||
"rna_XrSessionState_actionmaps_begin",
|
||||
"rna_iterator_listbase_next",
|
||||
"rna_iterator_listbase_end",
|
||||
"rna_iterator_listbase_get",
|
||||
NULL,
|
||||
"rna_XrSessionState_actionmaps_length",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
RNA_def_property_struct_type(prop, "XrActionMap");
|
||||
RNA_def_property_ui_text(prop, "XR Action Maps", "");
|
||||
rna_def_xr_actionmaps(brna, prop);
|
||||
|
||||
|
|
|
@ -189,10 +189,8 @@ struct DisplaceGridOp {
|
|||
|
||||
template<typename GridType> void operator()()
|
||||
{
|
||||
if constexpr (blender::is_same_any_v<GridType,
|
||||
openvdb::points::PointDataGrid,
|
||||
openvdb::StringGrid,
|
||||
openvdb::MaskGrid>) {
|
||||
if constexpr (blender::
|
||||
is_same_any_v<GridType, openvdb::points::PointDataGrid, openvdb::MaskGrid>) {
|
||||
/* We don't support displacing these grid types yet. */
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "BLI_assert.h"
|
||||
#include "BLI_dynstr.h"
|
||||
#include "BLI_hash_mm3.h"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <cmath>
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
#include "BLI_math_vector.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
|
|
|
@ -1585,8 +1585,7 @@ bool WM_xr_action_create(wmXrData *xr,
|
|||
const char *action_set_name,
|
||||
const char *action_name,
|
||||
eXrActionType type,
|
||||
unsigned int count_subaction_paths,
|
||||
const char **subaction_paths,
|
||||
const ListBase *user_paths,
|
||||
struct wmOperatorType *ot,
|
||||
struct IDProperty *op_properties,
|
||||
const char *haptic_name,
|
||||
|
@ -1601,9 +1600,8 @@ bool WM_xr_action_binding_create(wmXrData *xr,
|
|||
const char *action_set_name,
|
||||
const char *action_name,
|
||||
const char *profile_path,
|
||||
unsigned int count_subaction_paths,
|
||||
const char **subaction_paths,
|
||||
const char **component_paths,
|
||||
const ListBase *user_paths,
|
||||
const ListBase *component_paths,
|
||||
const float *float_thresholds,
|
||||
const eXrAxisFlag *axis_flags,
|
||||
const struct wmXrPose *poses);
|
||||
|
|
|
@ -483,7 +483,6 @@ static void draw_display_buffer(PlayState *ps, ImBuf *ibuf)
|
|||
if (!glsl_used) {
|
||||
immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
|
||||
immUniformColor3f(1.0f, 1.0f, 1.0f);
|
||||
immUniform1i("image", 0);
|
||||
}
|
||||
|
||||
immBegin(GPU_PRIM_TRI_FAN, 4);
|
||||
|
|
|
@ -67,7 +67,7 @@ void wm_stereo3d_draw_sidebyside(wmWindow *win, int view)
|
|||
const float halfx = GLA_PIXEL_OFS / sizex;
|
||||
const float halfy = GLA_PIXEL_OFS / sizex;
|
||||
|
||||
immUniform1i("image", 0); /* texture is already bound to GL_TEXTURE0 unit */
|
||||
/* Texture is already bound to GL_TEXTURE0 unit. */
|
||||
|
||||
immBegin(GPU_PRIM_TRI_FAN, 4);
|
||||
|
||||
|
@ -111,7 +111,7 @@ void wm_stereo3d_draw_topbottom(wmWindow *win, int view)
|
|||
const float halfx = GLA_PIXEL_OFS / sizex;
|
||||
const float halfy = GLA_PIXEL_OFS / sizex;
|
||||
|
||||
immUniform1i("image", 0); /* texture is already bound to GL_TEXTURE0 unit */
|
||||
/* Texture is already bound to GL_TEXTURE0 unit. */
|
||||
|
||||
immBegin(GPU_PRIM_TRI_FAN, 4);
|
||||
|
||||
|
|
|
@ -56,8 +56,7 @@ static wmXrActionSet *action_set_find(wmXrData *xr, const char *action_set_name)
|
|||
|
||||
static wmXrAction *action_create(const char *action_name,
|
||||
eXrActionType type,
|
||||
unsigned int count_subaction_paths,
|
||||
const char **subaction_paths,
|
||||
const ListBase *user_paths,
|
||||
wmOperatorType *ot,
|
||||
IDProperty *op_properties,
|
||||
const char *haptic_name,
|
||||
|
@ -73,15 +72,16 @@ static wmXrAction *action_create(const char *action_name,
|
|||
strcpy(action->name, action_name);
|
||||
action->type = type;
|
||||
|
||||
const unsigned int count = count_subaction_paths;
|
||||
const unsigned int count = (unsigned int)BLI_listbase_count(user_paths);
|
||||
unsigned int subaction_idx = 0;
|
||||
action->count_subaction_paths = count;
|
||||
|
||||
action->subaction_paths = MEM_mallocN(sizeof(*action->subaction_paths) * count,
|
||||
"XrAction_SubactionPaths");
|
||||
for (unsigned int i = 0; i < count; ++i) {
|
||||
action->subaction_paths[i] = MEM_mallocN(strlen(subaction_paths[i]) + 1,
|
||||
"XrAction_SubactionPath");
|
||||
strcpy(action->subaction_paths[i], subaction_paths[i]);
|
||||
LISTBASE_FOREACH_INDEX (XrUserPath *, user_path, user_paths, subaction_idx) {
|
||||
action->subaction_paths[subaction_idx] = MEM_mallocN(strlen(user_path->path) + 1,
|
||||
"XrAction_SubactionPath");
|
||||
strcpy(action->subaction_paths[subaction_idx], user_path->path);
|
||||
}
|
||||
|
||||
size_t size;
|
||||
|
@ -140,10 +140,9 @@ static void action_destroy(void *val)
|
|||
|
||||
MEM_SAFE_FREE(action->name);
|
||||
|
||||
const unsigned int count = action->count_subaction_paths;
|
||||
char **subaction_paths = action->subaction_paths;
|
||||
if (subaction_paths) {
|
||||
for (unsigned int i = 0; i < count; ++i) {
|
||||
for (unsigned int i = 0; i < action->count_subaction_paths; ++i) {
|
||||
MEM_SAFE_FREE(subaction_paths[i]);
|
||||
}
|
||||
MEM_freeN(subaction_paths);
|
||||
|
@ -214,8 +213,7 @@ bool WM_xr_action_create(wmXrData *xr,
|
|||
const char *action_set_name,
|
||||
const char *action_name,
|
||||
eXrActionType type,
|
||||
unsigned int count_subaction_paths,
|
||||
const char **subaction_paths,
|
||||
const ListBase *user_paths,
|
||||
wmOperatorType *ot,
|
||||
IDProperty *op_properties,
|
||||
const char *haptic_name,
|
||||
|
@ -232,8 +230,7 @@ bool WM_xr_action_create(wmXrData *xr,
|
|||
|
||||
wmXrAction *action = action_create(action_name,
|
||||
type,
|
||||
count_subaction_paths,
|
||||
subaction_paths,
|
||||
user_paths,
|
||||
ot,
|
||||
op_properties,
|
||||
haptic_name,
|
||||
|
@ -244,9 +241,19 @@ bool WM_xr_action_create(wmXrData *xr,
|
|||
action_flag,
|
||||
haptic_flag);
|
||||
|
||||
const unsigned int count = (unsigned int)BLI_listbase_count(user_paths);
|
||||
unsigned int subaction_idx = 0;
|
||||
|
||||
char **subaction_paths = MEM_calloc_arrayN(
|
||||
count, sizeof(*subaction_paths), "XrAction_SubactionPathPointers");
|
||||
|
||||
LISTBASE_FOREACH_INDEX (XrUserPath *, user_path, user_paths, subaction_idx) {
|
||||
subaction_paths[subaction_idx] = (char *)user_path->path;
|
||||
}
|
||||
|
||||
GHOST_XrActionInfo info = {
|
||||
.name = action_name,
|
||||
.count_subaction_paths = count_subaction_paths,
|
||||
.count_subaction_paths = count,
|
||||
.subaction_paths = subaction_paths,
|
||||
.states = action->states,
|
||||
.float_thresholds = action->float_thresholds,
|
||||
|
@ -273,11 +280,11 @@ bool WM_xr_action_create(wmXrData *xr,
|
|||
break;
|
||||
}
|
||||
|
||||
if (!GHOST_XrCreateActions(xr->runtime->context, action_set_name, 1, &info)) {
|
||||
return false;
|
||||
}
|
||||
const bool success = GHOST_XrCreateActions(xr->runtime->context, action_set_name, 1, &info);
|
||||
|
||||
return true;
|
||||
MEM_freeN(subaction_paths);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void WM_xr_action_destroy(wmXrData *xr, const char *action_set_name, const char *action_name)
|
||||
|
@ -323,19 +330,29 @@ bool WM_xr_action_binding_create(wmXrData *xr,
|
|||
const char *action_set_name,
|
||||
const char *action_name,
|
||||
const char *profile_path,
|
||||
unsigned int count_subaction_paths,
|
||||
const char **subaction_paths,
|
||||
const char **component_paths,
|
||||
const ListBase *user_paths,
|
||||
const ListBase *component_paths,
|
||||
const float *float_thresholds,
|
||||
const eXrAxisFlag *axis_flags,
|
||||
const struct wmXrPose *poses)
|
||||
{
|
||||
GHOST_XrActionBindingInfo *binding_infos = MEM_calloc_arrayN(
|
||||
count_subaction_paths, sizeof(*binding_infos), __func__);
|
||||
const unsigned int count = (unsigned int)BLI_listbase_count(user_paths);
|
||||
BLI_assert(count == (unsigned int)BLI_listbase_count(component_paths));
|
||||
|
||||
for (unsigned int i = 0; i < count_subaction_paths; ++i) {
|
||||
GHOST_XrActionBindingInfo *binding_infos = MEM_calloc_arrayN(
|
||||
count, sizeof(*binding_infos), "XrActionBinding_Infos");
|
||||
|
||||
char **subaction_paths = MEM_calloc_arrayN(
|
||||
count, sizeof(*subaction_paths), "XrActionBinding_SubactionPathPointers");
|
||||
|
||||
for (unsigned int i = 0; i < count; ++i) {
|
||||
GHOST_XrActionBindingInfo *binding_info = &binding_infos[i];
|
||||
binding_info->component_path = component_paths[i];
|
||||
const XrUserPath *user_path = BLI_findlink(user_paths, i);
|
||||
const XrComponentPath *component_path = BLI_findlink(component_paths, i);
|
||||
|
||||
subaction_paths[i] = (char *)user_path->path;
|
||||
|
||||
binding_info->component_path = component_path->path;
|
||||
if (float_thresholds) {
|
||||
binding_info->float_threshold = float_thresholds[i];
|
||||
}
|
||||
|
@ -351,15 +368,18 @@ bool WM_xr_action_binding_create(wmXrData *xr,
|
|||
GHOST_XrActionProfileInfo profile_info = {
|
||||
.action_name = action_name,
|
||||
.profile_path = profile_path,
|
||||
.count_subaction_paths = count_subaction_paths,
|
||||
.count_subaction_paths = count,
|
||||
.subaction_paths = subaction_paths,
|
||||
.bindings = binding_infos,
|
||||
};
|
||||
|
||||
bool ret = GHOST_XrCreateActionBindings(xr->runtime->context, action_set_name, 1, &profile_info);
|
||||
const bool success = GHOST_XrCreateActionBindings(
|
||||
xr->runtime->context, action_set_name, 1, &profile_info);
|
||||
|
||||
MEM_freeN(subaction_paths);
|
||||
MEM_freeN(binding_infos);
|
||||
return ret;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void WM_xr_action_binding_destroy(wmXrData *xr,
|
||||
|
|
|
@ -118,11 +118,17 @@ XrActionMapBinding *WM_xr_actionmap_binding_add_copy(XrActionMapItem *ami,
|
|||
return amb_dst;
|
||||
}
|
||||
|
||||
static void wm_xr_actionmap_binding_clear(XrActionMapBinding *amb)
|
||||
{
|
||||
BLI_freelistN(&amb->component_paths);
|
||||
}
|
||||
|
||||
bool WM_xr_actionmap_binding_remove(XrActionMapItem *ami, XrActionMapBinding *amb)
|
||||
{
|
||||
int idx = BLI_findindex(&ami->bindings, amb);
|
||||
|
||||
if (idx != -1) {
|
||||
wm_xr_actionmap_binding_clear(amb);
|
||||
BLI_freelinkN(&ami->bindings, amb);
|
||||
|
||||
if (idx <= ami->selbinding) {
|
||||
|
@ -155,12 +161,6 @@ XrActionMapBinding *WM_xr_actionmap_binding_find(XrActionMapItem *ami, const cha
|
|||
* Item in an XR action map, that maps an XR event to an operator, pose, or haptic output.
|
||||
* \{ */
|
||||
|
||||
static void wm_xr_actionmap_item_bindings_clear(XrActionMapItem *ami)
|
||||
{
|
||||
BLI_freelistN(&ami->bindings);
|
||||
ami->selbinding = 0;
|
||||
}
|
||||
|
||||
static void wm_xr_actionmap_item_properties_set(XrActionMapItem *ami)
|
||||
{
|
||||
WM_operator_properties_alloc(&(ami->op_properties_ptr), &(ami->op_properties), ami->op);
|
||||
|
@ -180,6 +180,19 @@ static void wm_xr_actionmap_item_properties_free(XrActionMapItem *ami)
|
|||
}
|
||||
}
|
||||
|
||||
static void wm_xr_actionmap_item_clear(XrActionMapItem *ami)
|
||||
{
|
||||
LISTBASE_FOREACH (XrActionMapBinding *, amb, &ami->bindings) {
|
||||
wm_xr_actionmap_binding_clear(amb);
|
||||
}
|
||||
BLI_freelistN(&ami->bindings);
|
||||
ami->selbinding = 0;
|
||||
|
||||
wm_xr_actionmap_item_properties_free(ami);
|
||||
|
||||
BLI_freelistN(&ami->user_paths);
|
||||
}
|
||||
|
||||
void WM_xr_actionmap_item_properties_update_ot(XrActionMapItem *ami)
|
||||
{
|
||||
switch (ami->type) {
|
||||
|
@ -324,8 +337,7 @@ bool WM_xr_actionmap_item_remove(XrActionMap *actionmap, XrActionMapItem *ami)
|
|||
int idx = BLI_findindex(&actionmap->items, ami);
|
||||
|
||||
if (idx != -1) {
|
||||
wm_xr_actionmap_item_bindings_clear(ami);
|
||||
wm_xr_actionmap_item_properties_free(ami);
|
||||
wm_xr_actionmap_item_clear(ami);
|
||||
BLI_freelinkN(&actionmap->items, ami);
|
||||
|
||||
if (idx <= actionmap->selitem) {
|
||||
|
@ -480,12 +492,9 @@ XrActionMap *WM_xr_actionmap_find(wmXrRuntimeData *runtime, const char *name)
|
|||
void WM_xr_actionmap_clear(XrActionMap *actionmap)
|
||||
{
|
||||
LISTBASE_FOREACH (XrActionMapItem *, ami, &actionmap->items) {
|
||||
wm_xr_actionmap_item_bindings_clear(ami);
|
||||
wm_xr_actionmap_item_properties_free(ami);
|
||||
wm_xr_actionmap_item_clear(ami);
|
||||
}
|
||||
|
||||
BLI_freelistN(&actionmap->items);
|
||||
|
||||
actionmap->selitem = 0;
|
||||
}
|
||||
|
||||
|
@ -494,9 +503,7 @@ void WM_xr_actionmaps_clear(wmXrRuntimeData *runtime)
|
|||
LISTBASE_FOREACH (XrActionMap *, am, &runtime->actionmaps) {
|
||||
WM_xr_actionmap_clear(am);
|
||||
}
|
||||
|
||||
BLI_freelistN(&runtime->actionmaps);
|
||||
|
||||
runtime->actactionmap = runtime->selactionmap = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -114,12 +114,8 @@ typedef struct wmXrDrawData {
|
|||
|
||||
typedef struct wmXrController {
|
||||
struct wmXrController *next, *prev;
|
||||
/** OpenXR path identifier. Length is dependent on OpenXR's XR_MAX_PATH_LENGTH (256).
|
||||
This subaction path will later be combined with a component path, and that combined path should
|
||||
also have a max of XR_MAX_PATH_LENGTH (e.g. subaction_path = /user/hand/left, component_path =
|
||||
/input/trigger/value, interaction_path = /user/hand/left/input/trigger/value).
|
||||
*/
|
||||
char subaction_path[64];
|
||||
/** OpenXR user path identifier. */
|
||||
char subaction_path[64]; /* XR_MAX_USER_PATH_LENGTH */
|
||||
|
||||
/** Pose (in world space) that represents the user's hand when holding the controller. */
|
||||
GHOST_XrPose grip_pose;
|
||||
|
|
|
@ -1188,8 +1188,9 @@ void wm_xr_session_actions_update(wmWindowManager *wm)
|
|||
&state->viewer_pose, settings->base_scale * state->nav_scale, state->viewer_viewmat);
|
||||
}
|
||||
|
||||
int ret = GHOST_XrSyncActions(xr_context, active_action_set ? active_action_set->name : NULL);
|
||||
if (!ret) {
|
||||
const bool synced = GHOST_XrSyncActions(xr_context,
|
||||
active_action_set ? active_action_set->name : NULL);
|
||||
if (!synced) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -319,16 +319,23 @@ elseif(WIN32)
|
|||
elseif(APPLE)
|
||||
if(WITH_PYTHON_MODULE)
|
||||
if(WITH_INSTALL_PORTABLE)
|
||||
set(BPY_INSTALL_DIR)
|
||||
set(TARGETDIR_VER $<TARGET_FILE_DIR:blender>/../Resources/${BLENDER_VERSION})
|
||||
# Keep the `BLENDER_VERSION` folder and bpy.so in the build folder.
|
||||
set(INSTALL_BPY_TO_SITE_PACKAGES OFF)
|
||||
else()
|
||||
set(TARGETDIR_VER "${PYTHON_LIBPATH}/Resources/${BLENDER_VERSION}")
|
||||
# Parent directory of bpy.so for installation.
|
||||
set(BPY_INSTALL_DIR ${PYTHON_LIBPATH}/site-packages)
|
||||
# Defined in terms of site-packages since the site-packages
|
||||
# directory can be a symlink (brew for example).
|
||||
set(TARGETDIR_VER "${BPY_INSTALL_DIR}/../Resources/${BLENDER_VERSION}")
|
||||
set(INSTALL_BPY_TO_SITE_PACKAGES ON)
|
||||
endif()
|
||||
else()
|
||||
set(TARGETDIR_VER Blender.app/Contents/Resources/${BLENDER_VERSION})
|
||||
endif()
|
||||
# License, copyright, readme files.
|
||||
set(BLENDER_TEXT_FILES_DESTINATION "${TARGETDIR_VER}/../text")
|
||||
set(MAC_BLENDER_TARGET_DYLIBS_DIR "${TARGETDIR_VER}/lib")
|
||||
# Skip relinking on cpack / install
|
||||
set_target_properties(blender PROPERTIES BUILD_WITH_INSTALL_RPATH true)
|
||||
|
@ -1052,9 +1059,6 @@ elseif(APPLE)
|
|||
DESTINATION "."
|
||||
)
|
||||
|
||||
# install release and app files
|
||||
set(BLENDER_TEXT_FILES_DESTINATION Blender.app/Contents/Resources/text)
|
||||
|
||||
install(
|
||||
FILES ${OSX_APP_SOURCEDIR}/Contents/PkgInfo
|
||||
DESTINATION Blender.app/Contents
|
||||
|
@ -1108,11 +1112,12 @@ elseif(APPLE)
|
|||
)
|
||||
unset(_py_inc_suffix)
|
||||
endif()
|
||||
|
||||
if(WITH_PYTHON_MODULE)
|
||||
if(INSTALL_BPY_TO_SITE_PACKAGES)
|
||||
install(
|
||||
TARGETS blender
|
||||
LIBRARY DESTINATION ${PYTHON_LIBPATH}/site-packages
|
||||
LIBRARY DESTINATION ${BPY_INSTALL_DIR}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
|
Loading…
Reference in New Issue