Merge branch 'master' into blender2.8
This commit is contained in:
commit
d96b8e168f
|
@ -155,6 +155,7 @@ option_defaults_init(
|
|||
_init_BUILDINFO
|
||||
_init_CODEC_FFMPEG
|
||||
_init_CYCLES_OSL
|
||||
_init_CYCLES_OPENSUBDIV
|
||||
_init_IMAGE_OPENEXR
|
||||
_init_INPUT_NDOF
|
||||
_init_JACK
|
||||
|
@ -172,6 +173,7 @@ if(UNIX AND NOT APPLE)
|
|||
# disable less important dependencies by default
|
||||
set(_init_CODEC_FFMPEG OFF)
|
||||
set(_init_CYCLES_OSL OFF)
|
||||
set(_init_CYCLES_OPENSUBDIV OFF)
|
||||
set(_init_IMAGE_OPENEXR OFF)
|
||||
set(_init_JACK OFF)
|
||||
set(_init_OPENCOLLADA OFF)
|
||||
|
@ -220,6 +222,8 @@ if(${CMAKE_VERSION} VERSION_LESS 2.8.8)
|
|||
endif()
|
||||
set(BUILDINFO_OVERRIDE_DATE "" CACHE STRING "Use instead of the current date for reproducable builds (empty string disables this option)")
|
||||
set(BUILDINFO_OVERRIDE_TIME "" CACHE STRING "Use instead of the current time for reproducable builds (empty string disables this option)")
|
||||
set(CPACK_OVERRIDE_PACKAGENAME "" CACHE STRING "Use instead of the standard packagename (empty string disables this option)")
|
||||
mark_as_advanced(CPACK_OVERRIDE_PACKAGENAME)
|
||||
mark_as_advanced(BUILDINFO_OVERRIDE_DATE)
|
||||
mark_as_advanced(BUILDINFO_OVERRIDE_TIME)
|
||||
|
||||
|
@ -398,7 +402,7 @@ option(WITH_CYCLES "Enable Cycles Render Engine" ON)
|
|||
option(WITH_CYCLES_STANDALONE "Build Cycles standalone application" OFF)
|
||||
option(WITH_CYCLES_STANDALONE_GUI "Build Cycles standalone with GUI" OFF)
|
||||
option(WITH_CYCLES_OSL "Build Cycles with OSL support" ${_init_CYCLES_OSL})
|
||||
option(WITH_CYCLES_OPENSUBDIV "Build Cycles with OpenSubdiv support" ON)
|
||||
option(WITH_CYCLES_OPENSUBDIV "Build Cycles with OpenSubdiv support" ${_init_CYCLES_OPENSUBDIV})
|
||||
option(WITH_CYCLES_CUDA_BINARIES "Build Cycles CUDA binaries" OFF)
|
||||
set(CYCLES_CUDA_BINARIES_ARCH sm_20 sm_21 sm_30 sm_35 sm_37 sm_50 sm_52 CACHE STRING "CUDA architectures to build binaries for")
|
||||
mark_as_advanced(CYCLES_CUDA_BINARIES_ARCH)
|
||||
|
@ -950,11 +954,6 @@ if(WITH_CYCLES)
|
|||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_OPENSUBDIV AND NOT WITH_OPENSUBDIV)
|
||||
message(STATUS "WITH_CYCLES_OPENSUBDIV requires WITH_OPENSUBDIV to be ON, turning OFF")
|
||||
set(WITH_CYCLES_OPENSUBDIV OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_INTERNATIONAL)
|
||||
|
|
|
@ -12,6 +12,7 @@ set(WITH_CODEC_FFMPEG ON CACHE BOOL "" FORCE)
|
|||
set(WITH_CODEC_SNDFILE ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_OSL ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_OPENSUBDIV ON CACHE BOOL "" FORCE)
|
||||
set(WITH_FFTW3 ON CACHE BOOL "" FORCE)
|
||||
set(WITH_LIBMV ON CACHE BOOL "" FORCE)
|
||||
set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE)
|
||||
|
|
|
@ -16,6 +16,7 @@ set(WITH_CODEC_FFMPEG OFF CACHE BOOL "" FORCE)
|
|||
set(WITH_CODEC_SNDFILE OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_OSL OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_OPENSUBDIV OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_FFTW3 OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_LIBMV OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_LLVM OFF CACHE BOOL "" FORCE)
|
||||
|
@ -48,6 +49,7 @@ set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
|
|||
set(WITH_OPENCOLORIO OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_OPENIMAGEIO OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_OPENMP OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_OPENVDB OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_RAYOPTIMIZATION OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_SDL OFF CACHE BOOL "" FORCE)
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
# Turn everything ON thats expected for an official release builds.
|
||||
#
|
||||
# Example usage:
|
||||
# cmake -C../blender/build_files/cmake/config/blender_full.cmake ../blender
|
||||
#
|
||||
|
||||
set(WITH_ALEMBIC ON CACHE BOOL "" FORCE)
|
||||
set(WITH_BUILDINFO ON CACHE BOOL "" FORCE)
|
||||
set(WITH_BULLET ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CODEC_AVI ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CODEC_FFMPEG ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CODEC_SNDFILE ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_OSL ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_OPENSUBDIV ON CACHE BOOL "" FORCE)
|
||||
set(WITH_FFTW3 ON CACHE BOOL "" FORCE)
|
||||
set(WITH_LIBMV ON CACHE BOOL "" FORCE)
|
||||
set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE)
|
||||
set(WITH_GAMEENGINE ON CACHE BOOL "" FORCE)
|
||||
set(WITH_COMPOSITOR ON CACHE BOOL "" FORCE)
|
||||
set(WITH_FREESTYLE ON CACHE BOOL "" FORCE)
|
||||
set(WITH_GHOST_XDND ON CACHE BOOL "" FORCE)
|
||||
set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE)
|
||||
set(WITH_IK_ITASC ON CACHE BOOL "" FORCE)
|
||||
set(WITH_IMAGE_CINEON ON CACHE BOOL "" FORCE)
|
||||
set(WITH_IMAGE_DDS ON CACHE BOOL "" FORCE)
|
||||
set(WITH_IMAGE_FRAMESERVER ON CACHE BOOL "" FORCE)
|
||||
set(WITH_IMAGE_HDR ON CACHE BOOL "" FORCE)
|
||||
set(WITH_IMAGE_OPENEXR ON CACHE BOOL "" FORCE)
|
||||
set(WITH_IMAGE_OPENJPEG ON CACHE BOOL "" FORCE)
|
||||
set(WITH_IMAGE_TIFF ON CACHE BOOL "" FORCE)
|
||||
set(WITH_INPUT_NDOF ON CACHE BOOL "" FORCE)
|
||||
set(WITH_INTERNATIONAL ON CACHE BOOL "" FORCE)
|
||||
set(WITH_JACK ON CACHE BOOL "" FORCE)
|
||||
set(WITH_LZMA ON CACHE BOOL "" FORCE)
|
||||
set(WITH_LZO ON CACHE BOOL "" FORCE)
|
||||
set(WITH_MOD_BOOLEAN ON CACHE BOOL "" FORCE)
|
||||
set(WITH_MOD_FLUID ON CACHE BOOL "" FORCE)
|
||||
set(WITH_MOD_REMESH ON CACHE BOOL "" FORCE)
|
||||
set(WITH_MOD_SMOKE ON CACHE BOOL "" FORCE)
|
||||
set(WITH_MOD_OCEANSIM ON CACHE BOOL "" FORCE)
|
||||
set(WITH_AUDASPACE ON CACHE BOOL "" FORCE)
|
||||
set(WITH_OPENAL ON CACHE BOOL "" FORCE)
|
||||
set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE)
|
||||
set(WITH_OPENCOLORIO ON CACHE BOOL "" FORCE)
|
||||
set(WITH_OPENMP ON CACHE BOOL "" FORCE)
|
||||
set(WITH_OPENVDB ON CACHE BOOL "" FORCE)
|
||||
set(WITH_OPENVDB_BLOSC ON CACHE BOOL "" FORCE)
|
||||
set(WITH_PYTHON_INSTALL ON CACHE BOOL "" FORCE)
|
||||
set(WITH_RAYOPTIMIZATION ON CACHE BOOL "" FORCE)
|
||||
set(WITH_SDL ON CACHE BOOL "" FORCE)
|
||||
set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE)
|
||||
set(WITH_X11_XF86VMODE ON CACHE BOOL "" FORCE)
|
||||
|
||||
set(WITH_PLAYER ON CACHE BOOL "" FORCE)
|
||||
set(WITH_MEM_JEMALLOC ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_CUDA_BINARIES ON CACHE BOOL "" FORCE)
|
||||
set(CYCLES_CUDA_BINARIES_ARCH sm_20;sm_21;sm_30;sm_35;sm_37;sm_50;sm_52;sm_60;sm_61 CACHE STRING "" FORCE)
|
||||
|
||||
# platform dependent options
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(WITH_JACK ON CACHE BOOL "" FORCE)
|
||||
set(WITH_DOC_MANPAGE ON CACHE BOOL "" FORCE)
|
||||
set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
|
||||
elseif(WIN32)
|
||||
set(WITH_JACK OFF CACHE BOOL "" FORCE)
|
||||
if(NOT CMAKE_COMPILER_IS_GNUCC)
|
||||
set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
|
||||
else()
|
||||
# MinGW exceptions
|
||||
set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CODEC_SNDFILE OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_OSL OFF CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
elseif(APPLE)
|
||||
set(WITH_JACK ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CODEC_QUICKTIME ON CACHE BOOL "" FORCE)
|
||||
set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
|
||||
endif()
|
|
@ -415,7 +415,7 @@ function(setup_liblinks
|
|||
if(WITH_OPENCOLORIO)
|
||||
target_link_libraries(${target} ${OPENCOLORIO_LIBRARIES})
|
||||
endif()
|
||||
if(WITH_OPENSUBDIV)
|
||||
if(WITH_OPENSUBDIV OR WITH_CYCLES_OPENSUBDIV)
|
||||
if(WIN32 AND NOT UNIX)
|
||||
file_list_suffix(OPENSUBDIV_LIBRARIES_DEBUG "${OPENSUBDIV_LIBRARIES}" "_d")
|
||||
target_link_libraries_debug(${target} "${OPENSUBDIV_LIBRARIES_DEBUG}")
|
||||
|
@ -745,7 +745,7 @@ function(SETUP_BLENDER_SORTED_LIBS)
|
|||
list(APPEND BLENDER_SORTED_LIBS bf_intern_gpudirect)
|
||||
endif()
|
||||
|
||||
if(WITH_OPENSUBDIV)
|
||||
if(WITH_OPENSUBDIV OR WITH_CYCLES_OPENSUBDIV)
|
||||
list(APPEND BLENDER_SORTED_LIBS bf_intern_opensubdiv)
|
||||
endif()
|
||||
|
||||
|
@ -1600,4 +1600,4 @@ MACRO(WINDOWS_SIGN_TARGET target)
|
|||
)
|
||||
endif()
|
||||
endif()
|
||||
ENDMACRO()
|
||||
ENDMACRO()
|
||||
|
|
|
@ -48,7 +48,11 @@ else(MSVC)
|
|||
set(PACKAGE_ARCH ${CMAKE_SYSTEM_PROCESSOR})
|
||||
endif()
|
||||
|
||||
set(CPACK_PACKAGE_FILE_NAME ${PROJECT_NAME_LOWER}-${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}-git${CPACK_DATE}.${BUILD_REV}-${PACKAGE_ARCH})
|
||||
if (CPACK_OVERRIDE_PACKAGENAME)
|
||||
set(CPACK_PACKAGE_FILE_NAME ${CPACK_OVERRIDE_PACKAGENAME}-${PACKAGE_ARCH})
|
||||
else()
|
||||
set(CPACK_PACKAGE_FILE_NAME ${PROJECT_NAME_LOWER}-${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}-git${CPACK_DATE}.${BUILD_REV}-${PACKAGE_ARCH})
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
# RPM packages
|
||||
|
|
|
@ -50,15 +50,14 @@ if(WITH_ALEMBIC)
|
|||
set(ALEMBIC_LIBRARIES Alembic)
|
||||
endif()
|
||||
|
||||
if(WITH_OPENSUBDIV)
|
||||
if(WITH_OPENSUBDIV OR WITH_CYCLES_OPENSUBDIV)
|
||||
set(OPENSUBDIV ${LIBDIR}/opensubdiv)
|
||||
set(OPENSUBDIV_LIBPATH ${OPENSUBDIV}/lib)
|
||||
find_library(OSL_LIB_UTIL NAMES osdutil PATHS ${OPENSUBDIV_LIBPATH})
|
||||
find_library(OSL_LIB_CPU NAMES osdCPU PATHS ${OPENSUBDIV_LIBPATH})
|
||||
find_library(OSL_LIB_GPU NAMES osdGPU PATHS ${OPENSUBDIV_LIBPATH})
|
||||
find_library(OSD_LIB_CPU NAMES osdCPU PATHS ${OPENSUBDIV_LIBPATH})
|
||||
find_library(OSD_LIB_GPU NAMES osdGPU PATHS ${OPENSUBDIV_LIBPATH})
|
||||
set(OPENSUBDIV_INCLUDE_DIR ${OPENSUBDIV}/include)
|
||||
set(OPENSUBDIV_INCLUDE_DIRS ${OPENSUBDIV_INCLUDE_DIR})
|
||||
list(APPEND OPENSUBDIV_LIBRARIES ${OSL_LIB_UTIL} ${OSL_LIB_CPU} ${OSL_LIB_GPU})
|
||||
list(APPEND OPENSUBDIV_LIBRARIES ${OSD_LIB_CPU} ${OSD_LIB_GPU})
|
||||
endif()
|
||||
|
||||
if(WITH_JACK)
|
||||
|
|
|
@ -245,7 +245,7 @@ if(WITH_BOOST)
|
|||
set(Boost_USE_STATIC_LIBS ON)
|
||||
endif()
|
||||
set(Boost_USE_MULTITHREADED ON)
|
||||
set(__boost_packages filesystem regex system thread date_time)
|
||||
set(__boost_packages filesystem regex thread date_time)
|
||||
if(WITH_CYCLES_OSL)
|
||||
if(NOT (${OSL_LIBRARY_VERSION_MAJOR} EQUAL "1" AND ${OSL_LIBRARY_VERSION_MINOR} LESS "6"))
|
||||
list(APPEND __boost_packages wave)
|
||||
|
@ -261,6 +261,7 @@ if(WITH_BOOST)
|
|||
if(WITH_OPENVDB)
|
||||
list(APPEND __boost_packages iostreams)
|
||||
endif()
|
||||
list(APPEND __boost_packages system)
|
||||
find_package(Boost 1.48 COMPONENTS ${__boost_packages})
|
||||
if(NOT Boost_FOUND)
|
||||
# try to find non-multithreaded if -mt not found, this flag
|
||||
|
@ -343,7 +344,7 @@ if(WITH_LLVM OR WITH_SDL_DYNLOAD)
|
|||
)
|
||||
endif()
|
||||
|
||||
if(WITH_OPENSUBDIV)
|
||||
if(WITH_OPENSUBDIV OR WITH_CYCLES_OPENSUBDIV)
|
||||
find_package_wrapper(OpenSubdiv)
|
||||
|
||||
set(OPENSUBDIV_LIBRARIES ${OPENSUBDIV_LIBRARIES})
|
||||
|
@ -351,6 +352,7 @@ if(WITH_OPENSUBDIV)
|
|||
|
||||
if(NOT OPENSUBDIV_FOUND)
|
||||
set(WITH_OPENSUBDIV OFF)
|
||||
set(WITH_CYCLES_OPENSUBDIV OFF)
|
||||
message(STATUS "OpenSubdiv not found")
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
@ -39,20 +39,22 @@ endmacro()
|
|||
|
||||
add_definitions(-DWIN32)
|
||||
# Minimum MSVC Version
|
||||
if(MSVC_VERSION EQUAL 1800)
|
||||
set(_min_ver "18.0.31101")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${_min_ver})
|
||||
message(FATAL_ERROR
|
||||
"Visual Studio 2013 (Update 4, ${_min_ver}) required, "
|
||||
"found (${CMAKE_CXX_COMPILER_VERSION})")
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
if(MSVC_VERSION EQUAL 1800)
|
||||
set(_min_ver "18.0.31101")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${_min_ver})
|
||||
message(FATAL_ERROR
|
||||
"Visual Studio 2013 (Update 4, ${_min_ver}) required, "
|
||||
"found (${CMAKE_CXX_COMPILER_VERSION})")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
if(MSVC_VERSION EQUAL 1900)
|
||||
set(_min_ver "19.0.24210")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${_min_ver})
|
||||
message(FATAL_ERROR
|
||||
"Visual Studio 2015 (Update 3, ${_min_ver}) required, "
|
||||
"found (${CMAKE_CXX_COMPILER_VERSION})")
|
||||
if(MSVC_VERSION EQUAL 1900)
|
||||
set(_min_ver "19.0.24210")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${_min_ver})
|
||||
message(FATAL_ERROR
|
||||
"Visual Studio 2015 (Update 3, ${_min_ver}) required, "
|
||||
"found (${CMAKE_CXX_COMPILER_VERSION})")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
unset(_min_ver)
|
||||
|
@ -440,7 +442,7 @@ if(WITH_MOD_CLOTH_ELTOPO)
|
|||
)
|
||||
endif()
|
||||
|
||||
if(WITH_OPENSUBDIV)
|
||||
if(WITH_OPENSUBDIV OR WITH_CYCLES_OPENSUBDIV)
|
||||
set(OPENSUBDIV_INCLUDE_DIR ${LIBDIR}/opensubdiv/include)
|
||||
set(OPENSUBDIV_LIBPATH ${LIBDIR}/opensubdiv/lib)
|
||||
set(OPENSUBDIV_LIBRARIES ${OPENSUBDIV_LIBPATH}/osdCPU.lib ${OPENSUBDIV_LIBPATH}/osdGPU.lib)
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Contributor(s): Bastien Montagne
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
"""
|
||||
This is a helper script to generate Blender Python API documentation (using Sphinx), and update server data using rsync.
|
||||
|
||||
You'll need to specify your user login and password, obviously.
|
||||
|
||||
Example usage:
|
||||
|
||||
./sphinx_doc_update.py --mirror ../../../docs/remote_api_backup/ --source ../.. --blender ../../../build_cmake/bin/blender --user foobar --password barfoo
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import zipfile
|
||||
|
||||
|
||||
DEFAULT_RSYNC_SERVER = "www.blender.org"
|
||||
DEFAULT_RSYNC_ROOT = "/api/"
|
||||
DEFAULT_SYMLINK_ROOT = "/data/www/vhosts/www.blender.org/api"
|
||||
|
||||
|
||||
def argparse_create():
|
||||
import argparse
|
||||
global __doc__
|
||||
|
||||
# When --help or no args are given, print this help
|
||||
usage_text = __doc__
|
||||
|
||||
parser = argparse.ArgumentParser(description=usage_text,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
|
||||
parser.add_argument(
|
||||
"--mirror", dest="mirror_dir",
|
||||
metavar='PATH', required=True,
|
||||
help="Path to local rsync mirror of api doc server")
|
||||
parser.add_argument(
|
||||
"--source", dest="source_dir",
|
||||
metavar='PATH', required=True,
|
||||
help="Path to Blender git repository")
|
||||
parser.add_argument(
|
||||
"--blender", dest="blender",
|
||||
metavar='PATH', required=True,
|
||||
help="Path to Blender executable")
|
||||
parser.add_argument(
|
||||
"--rsync-server", dest="rsync_server", default=DEFAULT_RSYNC_SERVER,
|
||||
metavar='RSYNCSERVER', type=str, required=False,
|
||||
help=("rsync server address"))
|
||||
parser.add_argument(
|
||||
"--rsync-root", dest="rsync_root", default=DEFAULT_RSYNC_ROOT,
|
||||
metavar='RSYNCROOT', type=str, required=False,
|
||||
help=("Root path of API doc on rsync server"))
|
||||
parser.add_argument(
|
||||
"--user", dest="user",
|
||||
metavar='USER', type=str, required=True,
|
||||
help=("User to login on rsync server"))
|
||||
parser.add_argument(
|
||||
"--password", dest="password",
|
||||
metavar='PASSWORD', type=str, required=True,
|
||||
help=("Password to login on rsync server"))
|
||||
|
||||
return parser
|
||||
|
||||
|
||||
def main():
|
||||
# ----------
|
||||
# Parse Args
|
||||
|
||||
args = argparse_create().parse_args()
|
||||
|
||||
rsync_base = "rsync://%s@%s:%s" % (args.user, args.rsync_server, args.rsync_root)
|
||||
|
||||
# I) Update local mirror using rsync.
|
||||
rsync_mirror_cmd = ("rsync", "--delete-after", "-avzz", rsync_base, args.mirror_dir)
|
||||
subprocess.run(rsync_mirror_cmd, env=dict(os.environ, RSYNC_PASSWORD=args.password))
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
# II) Generate doc source in temp dir.
|
||||
doc_gen_cmd = (args.blender, "--background", "-noaudio", "--factory-startup", "--python-exit-code", "1",
|
||||
"--python", "%s/doc/python_api/sphinx_doc_gen.py" % args.source_dir, "--",
|
||||
"--output", tmp_dir)
|
||||
subprocess.run(doc_gen_cmd)
|
||||
|
||||
# III) Get Blender version info.
|
||||
blenver = blenver_zip = ""
|
||||
getver_file = os.path.join(tmp_dir, "blendver.txt")
|
||||
getver_script = (""
|
||||
"import sys, bpy\n"
|
||||
"with open(sys.argv[-1], 'w') as f:\n"
|
||||
" f.write('%d_%d%s_release\\n' % (bpy.app.version[0], bpy.app.version[1], bpy.app.version_char)\n"
|
||||
" if bpy.app.version_cycle in {'rc', 'release'} else '%d_%d_%d\\n' % bpy.app.version)\n"
|
||||
" f.write('%d_%d_%d' % bpy.app.version)\n")
|
||||
get_ver_cmd = (args.blender, "--background", "-noaudio", "--factory-startup", "--python-exit-code", "1",
|
||||
"--python-expr", getver_script, "--", getver_file)
|
||||
subprocess.run(get_ver_cmd)
|
||||
with open(getver_file) as f:
|
||||
blenver, blenver_zip = f.read().split("\n")
|
||||
os.remove(getver_file)
|
||||
|
||||
# IV) Build doc.
|
||||
curr_dir = os.getcwd()
|
||||
os.chdir(tmp_dir)
|
||||
sphinx_cmd = ("sphinx-build", "-b", "html", "sphinx-in", "sphinx-out")
|
||||
subprocess.run(sphinx_cmd)
|
||||
shutil.rmtree(os.path.join("sphinx-out", ".doctrees"))
|
||||
os.chdir(curr_dir)
|
||||
|
||||
# V) Cleanup existing matching dir in server mirror (if any), and copy new doc.
|
||||
api_name = "blender_python_api_%s" % blenver
|
||||
api_dir = os.path.join(args.mirror_dir, api_name)
|
||||
if os.path.exists(api_dir):
|
||||
shutil.rmtree(api_dir)
|
||||
os.rename(os.path.join(tmp_dir, "sphinx-out"), api_dir)
|
||||
|
||||
# VI) Create zip archive.
|
||||
zip_name = "blender_python_reference_%s" % blenver_zip # We can't use 'release' postfix here...
|
||||
zip_path = os.path.join(args.mirror_dir, zip_name)
|
||||
with zipfile.ZipFile(zip_path, 'w') as zf:
|
||||
for de in os.scandir(api_dir):
|
||||
zf.write(de.path, arcname=os.path.join(zip_name, de.name))
|
||||
os.rename(zip_path, os.path.join(api_dir, "%s.zip" % zip_name))
|
||||
|
||||
# VII) Create symlinks and html redirects.
|
||||
#~ os.symlink(os.path.join(DEFAULT_SYMLINK_ROOT, api_name, "contents.html"), os.path.join(api_dir, "index.html"))
|
||||
os.symlink("./contents.html", os.path.join(api_dir, "index.html"))
|
||||
if blenver.endswith("release"):
|
||||
symlink = os.path.join(args.mirror_dir, "blender_python_api_current")
|
||||
os.remove(symlink)
|
||||
os.symlink("./%s" % api_name, symlink)
|
||||
with open(os.path.join(args.mirror_dir, "250PythonDoc/index.html"), 'w') as f:
|
||||
f.write("<html><head><title>Redirecting...</title><meta http-equiv=\"REFRESH\""
|
||||
"content=\"0;url=../%s/\"></head><body>Redirecting...</body></html>" % api_name)
|
||||
else:
|
||||
symlink = os.path.join(args.mirror_dir, "blender_python_api_master")
|
||||
os.remove(symlink)
|
||||
os.symlink("./%s" % api_name, symlink)
|
||||
with open(os.path.join(args.mirror_dir, "blender_python_api/index.html"), 'w') as f:
|
||||
f.write("<html><head><title>Redirecting...</title><meta http-equiv=\"REFRESH\""
|
||||
"content=\"0;url=../%s/\"></head><body>Redirecting...</body></html>" % api_name)
|
||||
|
||||
# VIII) Upload (first do a dry-run so user can ensure everything is OK).
|
||||
print("Doc generated in local mirror %s, please check it before uploading "
|
||||
"(hit [Enter] to continue, [Ctrl-C] to exit):" % api_dir)
|
||||
sys.stdin.read(1)
|
||||
|
||||
rsync_mirror_cmd = ("rsync", "--dry-run", "--delete-after", "-avzz", args.mirror_dir, rsync_base)
|
||||
subprocess.run(rsync_mirror_cmd, env=dict(os.environ, RSYNC_PASSWORD=args.password))
|
||||
|
||||
print("Rsync upload simulated, please check every thing is OK (hit [Enter] to continue, [Ctrl-C] to exit):")
|
||||
sys.stdin.read(1)
|
||||
|
||||
rsync_mirror_cmd = ("rsync", "--delete-after", "-avzz", args.mirror_dir, rsync_base)
|
||||
subprocess.run(rsync_mirror_cmd, env=dict(os.environ, RSYNC_PASSWORD=args.password))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -660,6 +660,7 @@ void BlenderSync::sync_motion(BL::RenderSettings& b_render,
|
|||
Camera prevcam = *(scene->camera);
|
||||
|
||||
int frame_center = b_scene.frame_current();
|
||||
float subframe_center = b_scene.frame_subframe();
|
||||
float frame_center_delta = 0.0f;
|
||||
|
||||
if(scene->need_motion() != Scene::MOTION_PASS &&
|
||||
|
@ -673,7 +674,7 @@ void BlenderSync::sync_motion(BL::RenderSettings& b_render,
|
|||
assert(scene->camera->motion_position == Camera::MOTION_POSITION_START);
|
||||
frame_center_delta = shuttertime * 0.5f;
|
||||
}
|
||||
float time = frame_center + frame_center_delta;
|
||||
float time = frame_center + subframe_center + frame_center_delta;
|
||||
int frame = (int)floorf(time);
|
||||
float subframe = time - frame;
|
||||
python_thread_state_restore(python_thread_state);
|
||||
|
@ -696,7 +697,7 @@ void BlenderSync::sync_motion(BL::RenderSettings& b_render,
|
|||
float shuttertime = scene->motion_shutter_time();
|
||||
|
||||
/* compute frame and subframe time */
|
||||
float time = frame_center + frame_center_delta + relative_time * shuttertime * 0.5f;
|
||||
float time = frame_center + subframe_center + frame_center_delta + relative_time * shuttertime * 0.5f;
|
||||
int frame = (int)floorf(time);
|
||||
float subframe = time - frame;
|
||||
|
||||
|
@ -721,7 +722,7 @@ void BlenderSync::sync_motion(BL::RenderSettings& b_render,
|
|||
* function assumes it is being executed from python and will
|
||||
* try to save the thread state */
|
||||
python_thread_state_restore(python_thread_state);
|
||||
b_engine.frame_set(frame_center, 0.0f);
|
||||
b_engine.frame_set(frame_center, subframe_center);
|
||||
python_thread_state_save(python_thread_state);
|
||||
|
||||
/* tag camera for motion update */
|
||||
|
|
|
@ -681,8 +681,7 @@ void BlenderSession::bake(BL::Object& b_object,
|
|||
}
|
||||
}
|
||||
|
||||
/* when used, non-instanced convention: object = ~object */
|
||||
int object = ~object_index;
|
||||
int object = object_index;
|
||||
|
||||
BakeData *bake_data = scene->bake_manager->init(object, tri_offset, num_pixels);
|
||||
|
||||
|
|
|
@ -425,6 +425,7 @@ RegularBVH::RegularBVH(const BVHParams& params_, const vector<Object*>& objects_
|
|||
void RegularBVH::pack_leaf(const BVHStackEntry& e,
|
||||
const LeafNode *leaf)
|
||||
{
|
||||
assert(e.idx + BVH_NODE_LEAF_SIZE <= pack.leaf_nodes.size());
|
||||
float4 data[BVH_NODE_LEAF_SIZE];
|
||||
memset(data, 0, sizeof(data));
|
||||
if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1) {
|
||||
|
@ -472,13 +473,26 @@ void RegularBVH::pack_aligned_node(int idx,
|
|||
int c0, int c1,
|
||||
uint visibility0, uint visibility1)
|
||||
{
|
||||
int4 data[BVH_NODE_SIZE] =
|
||||
{
|
||||
assert(idx + BVH_NODE_SIZE <= pack.nodes.size());
|
||||
assert(c0 < 0 || c0 < pack.nodes.size());
|
||||
assert(c1 < 0 || c1 < pack.nodes.size());
|
||||
|
||||
int4 data[BVH_NODE_SIZE] = {
|
||||
make_int4(visibility0 & ~PATH_RAY_NODE_UNALIGNED,
|
||||
visibility1 & ~PATH_RAY_NODE_UNALIGNED, c0, c1),
|
||||
make_int4(__float_as_int(b0.min.x), __float_as_int(b1.min.x), __float_as_int(b0.max.x), __float_as_int(b1.max.x)),
|
||||
make_int4(__float_as_int(b0.min.y), __float_as_int(b1.min.y), __float_as_int(b0.max.y), __float_as_int(b1.max.y)),
|
||||
make_int4(__float_as_int(b0.min.z), __float_as_int(b1.min.z), __float_as_int(b0.max.z), __float_as_int(b1.max.z)),
|
||||
visibility1 & ~PATH_RAY_NODE_UNALIGNED,
|
||||
c0, c1),
|
||||
make_int4(__float_as_int(b0.min.x),
|
||||
__float_as_int(b1.min.x),
|
||||
__float_as_int(b0.max.x),
|
||||
__float_as_int(b1.max.x)),
|
||||
make_int4(__float_as_int(b0.min.y),
|
||||
__float_as_int(b1.min.y),
|
||||
__float_as_int(b0.max.y),
|
||||
__float_as_int(b1.max.y)),
|
||||
make_int4(__float_as_int(b0.min.z),
|
||||
__float_as_int(b1.min.z),
|
||||
__float_as_int(b0.max.z),
|
||||
__float_as_int(b1.max.z)),
|
||||
};
|
||||
|
||||
memcpy(&pack.nodes[idx], data, sizeof(int4)*BVH_NODE_SIZE);
|
||||
|
@ -505,6 +519,10 @@ void RegularBVH::pack_unaligned_node(int idx,
|
|||
int c0, int c1,
|
||||
uint visibility0, uint visibility1)
|
||||
{
|
||||
assert(idx + BVH_UNALIGNED_NODE_SIZE <= pack.nodes.size());
|
||||
assert(c0 < 0 || c0 < pack.nodes.size());
|
||||
assert(c1 < 0 || c1 < pack.nodes.size());
|
||||
|
||||
float4 data[BVH_UNALIGNED_NODE_SIZE];
|
||||
Transform space0 = BVHUnaligned::compute_node_transform(bounds0,
|
||||
aligned_space0);
|
||||
|
@ -614,9 +632,10 @@ void RegularBVH::refit_nodes()
|
|||
void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
|
||||
{
|
||||
if(leaf) {
|
||||
int4 *data = &pack.leaf_nodes[idx];
|
||||
int c0 = data[0].x;
|
||||
int c1 = data[0].y;
|
||||
assert(idx + BVH_NODE_LEAF_SIZE <= pack.leaf_nodes.size());
|
||||
const int4 *data = &pack.leaf_nodes[idx];
|
||||
const int c0 = data[0].x;
|
||||
const int c1 = data[0].y;
|
||||
/* refit leaf node */
|
||||
for(int prim = c0; prim < c1; prim++) {
|
||||
int pidx = pack.prim_index[prim];
|
||||
|
@ -691,9 +710,12 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
|
|||
memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4)*BVH_NODE_LEAF_SIZE);
|
||||
}
|
||||
else {
|
||||
int4 *data = &pack.nodes[idx];
|
||||
int c0 = data[0].z;
|
||||
int c1 = data[0].w;
|
||||
assert(idx + BVH_NODE_SIZE <= pack.nodes.size());
|
||||
|
||||
const int4 *data = &pack.nodes[idx];
|
||||
const bool is_unaligned = (data[0].x & PATH_RAY_NODE_UNALIGNED) != 0;
|
||||
const int c0 = data[0].z;
|
||||
const int c1 = data[0].w;
|
||||
/* refit inner node, set bbox from children */
|
||||
BoundBox bbox0 = BoundBox::empty, bbox1 = BoundBox::empty;
|
||||
uint visibility0 = 0, visibility1 = 0;
|
||||
|
@ -701,7 +723,22 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
|
|||
refit_node((c0 < 0)? -c0-1: c0, (c0 < 0), bbox0, visibility0);
|
||||
refit_node((c1 < 0)? -c1-1: c1, (c1 < 0), bbox1, visibility1);
|
||||
|
||||
pack_aligned_node(idx, bbox0, bbox1, c0, c1, visibility0, visibility1);
|
||||
if(is_unaligned) {
|
||||
Transform aligned_space = transform_identity();
|
||||
pack_unaligned_node(idx,
|
||||
aligned_space, aligned_space,
|
||||
bbox0, bbox1,
|
||||
c0, c1,
|
||||
visibility0,
|
||||
visibility1);
|
||||
}
|
||||
else {
|
||||
pack_aligned_node(idx,
|
||||
bbox0, bbox1,
|
||||
c0, c1,
|
||||
visibility0,
|
||||
visibility1);
|
||||
}
|
||||
|
||||
bbox.grow(bbox0);
|
||||
bbox.grow(bbox1);
|
||||
|
@ -797,14 +834,33 @@ void QBVH::pack_inner(const BVHStackEntry& e,
|
|||
void QBVH::pack_aligned_inner(const BVHStackEntry& e,
|
||||
const BVHStackEntry *en,
|
||||
int num)
|
||||
{
|
||||
BoundBox bounds[4];
|
||||
int child[4];
|
||||
for(int i = 0; i < num; ++i) {
|
||||
bounds[i] = en[i].node->m_bounds;
|
||||
child[i] = en[i].encodeIdx();
|
||||
}
|
||||
pack_aligned_node(e.idx,
|
||||
bounds,
|
||||
child,
|
||||
e.node->m_visibility,
|
||||
num);
|
||||
}
|
||||
|
||||
void QBVH::pack_aligned_node(int idx,
|
||||
const BoundBox *bounds,
|
||||
const int *child,
|
||||
const uint visibility,
|
||||
const int num)
|
||||
{
|
||||
float4 data[BVH_QNODE_SIZE];
|
||||
memset(data, 0, sizeof(data));
|
||||
|
||||
data[0].x = __uint_as_float(e.node->m_visibility & ~PATH_RAY_NODE_UNALIGNED);
|
||||
data[0].x = __uint_as_float(visibility & ~PATH_RAY_NODE_UNALIGNED);
|
||||
for(int i = 0; i < num; i++) {
|
||||
float3 bb_min = en[i].node->m_bounds.min;
|
||||
float3 bb_max = en[i].node->m_bounds.max;
|
||||
float3 bb_min = bounds[i].min;
|
||||
float3 bb_max = bounds[i].max;
|
||||
|
||||
data[1][i] = bb_min.x;
|
||||
data[2][i] = bb_max.x;
|
||||
|
@ -813,7 +869,7 @@ void QBVH::pack_aligned_inner(const BVHStackEntry& e,
|
|||
data[5][i] = bb_min.z;
|
||||
data[6][i] = bb_max.z;
|
||||
|
||||
data[7][i] = __int_as_float(en[i].encodeIdx());
|
||||
data[7][i] = __int_as_float(child[i]);
|
||||
}
|
||||
|
||||
for(int i = num; i < 4; i++) {
|
||||
|
@ -832,22 +888,45 @@ void QBVH::pack_aligned_inner(const BVHStackEntry& e,
|
|||
data[7][i] = __int_as_float(0);
|
||||
}
|
||||
|
||||
memcpy(&pack.nodes[e.idx], data, sizeof(float4)*BVH_QNODE_SIZE);
|
||||
memcpy(&pack.nodes[idx], data, sizeof(float4)*BVH_QNODE_SIZE);
|
||||
}
|
||||
|
||||
void QBVH::pack_unaligned_inner(const BVHStackEntry& e,
|
||||
const BVHStackEntry *en,
|
||||
int num)
|
||||
{
|
||||
Transform aligned_space[4];
|
||||
BoundBox bounds[4];
|
||||
int child[4];
|
||||
for(int i = 0; i < num; ++i) {
|
||||
aligned_space[i] = en[i].node->get_aligned_space();
|
||||
bounds[i] = en[i].node->m_bounds;
|
||||
child[i] = en[i].encodeIdx();
|
||||
}
|
||||
pack_unaligned_node(e.idx,
|
||||
aligned_space,
|
||||
bounds,
|
||||
child,
|
||||
e.node->m_visibility,
|
||||
num);
|
||||
}
|
||||
|
||||
void QBVH::pack_unaligned_node(int idx,
|
||||
const Transform *aligned_space,
|
||||
const BoundBox *bounds,
|
||||
const int *child,
|
||||
const uint visibility,
|
||||
const int num)
|
||||
{
|
||||
float4 data[BVH_UNALIGNED_QNODE_SIZE];
|
||||
memset(data, 0, sizeof(data));
|
||||
|
||||
data[0].x = __uint_as_float(e.node->m_visibility | PATH_RAY_NODE_UNALIGNED);
|
||||
data[0].x = __uint_as_float(visibility | PATH_RAY_NODE_UNALIGNED);
|
||||
|
||||
for(int i = 0; i < num; i++) {
|
||||
Transform space = BVHUnaligned::compute_node_transform(
|
||||
en[i].node->m_bounds,
|
||||
en[i].node->get_aligned_space());
|
||||
bounds[i],
|
||||
aligned_space[i]);
|
||||
|
||||
data[1][i] = space.x.x;
|
||||
data[2][i] = space.x.y;
|
||||
|
@ -865,20 +944,34 @@ void QBVH::pack_unaligned_inner(const BVHStackEntry& e,
|
|||
data[11][i] = space.y.w;
|
||||
data[12][i] = space.z.w;
|
||||
|
||||
data[13][i] = __int_as_float(en[i].encodeIdx());
|
||||
data[13][i] = __int_as_float(child[i]);
|
||||
}
|
||||
|
||||
for(int i = num; i < 4; i++) {
|
||||
/* We store BB which would never be recorded as intersection
|
||||
* so kernel might safely assume there are always 4 child nodes.
|
||||
*/
|
||||
for(int j = 1; j < 13; ++j) {
|
||||
data[j][i] = 0.0f;
|
||||
}
|
||||
|
||||
data[1][i] = 1.0f;
|
||||
data[2][i] = 0.0f;
|
||||
data[3][i] = 0.0f;
|
||||
|
||||
data[4][i] = 0.0f;
|
||||
data[5][i] = 0.0f;
|
||||
data[6][i] = 0.0f;
|
||||
|
||||
data[7][i] = 0.0f;
|
||||
data[8][i] = 0.0f;
|
||||
data[9][i] = 0.0f;
|
||||
|
||||
data[10][i] = -FLT_MAX;
|
||||
data[11][i] = -FLT_MAX;
|
||||
data[12][i] = -FLT_MAX;
|
||||
|
||||
data[13][i] = __int_as_float(0);
|
||||
}
|
||||
|
||||
memcpy(&pack.nodes[e.idx], data, sizeof(float4)*BVH_UNALIGNED_QNODE_SIZE);
|
||||
memcpy(&pack.nodes[idx], data, sizeof(float4)*BVH_UNALIGNED_QNODE_SIZE);
|
||||
}
|
||||
|
||||
/* Quad SIMD Nodes */
|
||||
|
@ -1104,61 +1197,24 @@ void QBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
|
|||
}
|
||||
}
|
||||
|
||||
/* TODO(sergey): To be de-duplicated with pack_inner(),
|
||||
* but for that need some sort of pack_node(). which operates with
|
||||
* direct data, not stack element.
|
||||
*/
|
||||
if(is_unaligned) {
|
||||
Transform aligned_space = transform_identity();
|
||||
float4 inner_data[BVH_UNALIGNED_QNODE_SIZE];
|
||||
inner_data[0] = make_float4(
|
||||
__int_as_float(visibility | PATH_RAY_NODE_UNALIGNED),
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f);
|
||||
for(int i = 0; i < 4; ++i) {
|
||||
Transform space = BVHUnaligned::compute_node_transform(
|
||||
child_bbox[i],
|
||||
aligned_space);
|
||||
inner_data[1][i] = space.x.x;
|
||||
inner_data[2][i] = space.x.y;
|
||||
inner_data[3][i] = space.x.z;
|
||||
|
||||
inner_data[4][i] = space.y.x;
|
||||
inner_data[5][i] = space.y.y;
|
||||
inner_data[6][i] = space.y.z;
|
||||
|
||||
inner_data[7][i] = space.z.x;
|
||||
inner_data[8][i] = space.z.y;
|
||||
inner_data[9][i] = space.z.z;
|
||||
|
||||
inner_data[10][i] = space.x.w;
|
||||
inner_data[11][i] = space.y.w;
|
||||
inner_data[12][i] = space.z.w;
|
||||
|
||||
inner_data[13][i] = __int_as_float(c[i]);
|
||||
}
|
||||
memcpy(&pack.nodes[idx], inner_data, sizeof(float4)*BVH_UNALIGNED_QNODE_SIZE);
|
||||
Transform aligned_space[4] = {transform_identity(),
|
||||
transform_identity(),
|
||||
transform_identity(),
|
||||
transform_identity()};
|
||||
pack_unaligned_node(idx,
|
||||
aligned_space,
|
||||
child_bbox,
|
||||
&c[0],
|
||||
visibility,
|
||||
4);
|
||||
}
|
||||
else {
|
||||
float4 inner_data[BVH_QNODE_SIZE];
|
||||
inner_data[0] = make_float4(
|
||||
__int_as_float(visibility & ~PATH_RAY_NODE_UNALIGNED),
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f);
|
||||
for(int i = 0; i < 4; ++i) {
|
||||
float3 bb_min = child_bbox[i].min;
|
||||
float3 bb_max = child_bbox[i].max;
|
||||
inner_data[1][i] = bb_min.x;
|
||||
inner_data[2][i] = bb_max.x;
|
||||
inner_data[3][i] = bb_min.y;
|
||||
inner_data[4][i] = bb_max.y;
|
||||
inner_data[5][i] = bb_min.z;
|
||||
inner_data[6][i] = bb_max.z;
|
||||
inner_data[7][i] = __int_as_float(c[i]);
|
||||
}
|
||||
memcpy(&pack.nodes[idx], inner_data, sizeof(float4)*BVH_QNODE_SIZE);
|
||||
pack_aligned_node(idx,
|
||||
child_bbox,
|
||||
&c[0],
|
||||
visibility,
|
||||
4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -171,9 +171,21 @@ protected:
|
|||
void pack_aligned_inner(const BVHStackEntry& e,
|
||||
const BVHStackEntry *en,
|
||||
int num);
|
||||
void pack_aligned_node(int idx,
|
||||
const BoundBox *bounds,
|
||||
const int *child,
|
||||
const uint visibility,
|
||||
const int num);
|
||||
|
||||
void pack_unaligned_inner(const BVHStackEntry& e,
|
||||
const BVHStackEntry *en,
|
||||
int num);
|
||||
void pack_unaligned_node(int idx,
|
||||
const Transform *aligned_space,
|
||||
const BoundBox *bounds,
|
||||
const int *child,
|
||||
const uint visibility,
|
||||
const int num);
|
||||
|
||||
/* refit */
|
||||
void refit_nodes();
|
||||
|
|
|
@ -343,7 +343,7 @@ public:
|
|||
const string cubin_file = string_printf("cycles_kernel_sm%d%d_%s.cubin",
|
||||
major, minor,
|
||||
cubin_md5.c_str());
|
||||
const string cubin = path_user_get(path_join("cache", cubin_file));
|
||||
const string cubin = path_cache_get(path_join("kernels", cubin_file));
|
||||
VLOG(1) << "Testing for locally compiled kernel " << cubin << ".";
|
||||
if(path_exists(cubin)) {
|
||||
VLOG(1) << "Using locally compiled kernel.";
|
||||
|
|
|
@ -987,7 +987,7 @@ public:
|
|||
string clbin = string_printf("cycles_kernel_%s_%s.clbin",
|
||||
device_md5.c_str(),
|
||||
kernel_md5.c_str());
|
||||
clbin = path_user_get(path_join("cache", clbin));
|
||||
clbin = path_cache_get(path_join("kernels", clbin));
|
||||
|
||||
/* path to preprocessed source for debugging */
|
||||
string clsrc, *debug_src = NULL;
|
||||
|
@ -996,7 +996,7 @@ public:
|
|||
clsrc = string_printf("cycles_kernel_%s_%s.cl",
|
||||
device_md5.c_str(),
|
||||
kernel_md5.c_str());
|
||||
clsrc = path_user_get(path_join("cache", clsrc));
|
||||
clsrc = path_cache_get(path_join("kernels", clsrc));
|
||||
debug_src = &clsrc;
|
||||
}
|
||||
|
||||
|
@ -1680,7 +1680,7 @@ public:
|
|||
string clbin = string_printf("cycles_kernel_%s_%s.clbin",
|
||||
device_md5.c_str(),
|
||||
kernel_md5.c_str());
|
||||
clbin = path_user_get(path_join("cache", clbin));
|
||||
clbin = path_cache_get(path_join("kernels", clbin));
|
||||
|
||||
/* Path to preprocessed source for debugging. */
|
||||
string clsrc, *debug_src = NULL;
|
||||
|
@ -1688,7 +1688,7 @@ public:
|
|||
clsrc = string_printf("cycles_kernel_%s_%s.cl",
|
||||
device_md5.c_str(),
|
||||
kernel_md5.c_str());
|
||||
clsrc = path_user_get(path_join("cache", clsrc));
|
||||
clsrc = path_cache_get(path_join("kernels", clsrc));
|
||||
debug_src = &clsrc;
|
||||
}
|
||||
|
||||
|
@ -2102,7 +2102,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
string cache_clbin = path_user_get(path_join("cache", clbin));
|
||||
string cache_clbin = path_cache_get(path_join("kernels", clbin));
|
||||
|
||||
/* If exists already, try use it. */
|
||||
if(path_exists(cache_clbin) && load_binary(kernel_path,
|
||||
|
@ -2220,7 +2220,7 @@ public:
|
|||
if(opencl_kernel_use_debug()) { \
|
||||
clsrc = string_printf("cycles_kernel_%s_%s_" #name ".cl", \
|
||||
device_md5.c_str(), kernel_md5.c_str()); \
|
||||
clsrc = path_user_get(path_join("cache", clsrc)); \
|
||||
clsrc = path_cache_get(path_join("kernels", clsrc)); \
|
||||
debug_src = &clsrc; \
|
||||
} \
|
||||
if(!load_split_kernel(#name, \
|
||||
|
|
|
@ -278,7 +278,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
|
|||
shader = __float_as_int(str.z);
|
||||
}
|
||||
#endif
|
||||
int flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*2);
|
||||
int flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*SHADER_SIZE);
|
||||
|
||||
/* if no transparent shadows, all light is blocked */
|
||||
if(!(flag & SD_HAS_TRANSPARENT_SHADOW)) {
|
||||
|
|
|
@ -356,7 +356,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
|
|||
shader = __float_as_int(str.z);
|
||||
}
|
||||
#endif
|
||||
int flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*2);
|
||||
int flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*SHADER_SIZE);
|
||||
|
||||
/* if no transparent shadows, all light is blocked */
|
||||
if(!(flag & SD_HAS_TRANSPARENT_SHADOW)) {
|
||||
|
|
|
@ -308,7 +308,7 @@ ccl_device_inline uint object_patch_map_offset(KernelGlobals *kg, int object)
|
|||
|
||||
ccl_device int shader_pass_id(KernelGlobals *kg, const ShaderData *sd)
|
||||
{
|
||||
return kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*2 + 1);
|
||||
return kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*SHADER_SIZE + 1);
|
||||
}
|
||||
|
||||
/* Particle data from which object was instanced */
|
||||
|
@ -564,6 +564,15 @@ ccl_device_inline void bvh_instance_motion_pop_factor(KernelGlobals *kg,
|
|||
*/
|
||||
|
||||
#ifdef __KERNEL_OPENCL__
|
||||
ccl_device_inline void object_position_transform_addrspace(KernelGlobals *kg,
|
||||
const ShaderData *sd,
|
||||
ccl_addr_space float3 *P)
|
||||
{
|
||||
float3 private_P = *P;
|
||||
object_position_transform(kg, sd, &private_P);
|
||||
*P = private_P;
|
||||
}
|
||||
|
||||
ccl_device_inline void object_dir_transform_addrspace(KernelGlobals *kg,
|
||||
const ShaderData *sd,
|
||||
ccl_addr_space float3 *D)
|
||||
|
@ -584,9 +593,11 @@ ccl_device_inline void object_normal_transform_addrspace(KernelGlobals *kg,
|
|||
#endif
|
||||
|
||||
#ifndef __KERNEL_OPENCL__
|
||||
# define object_position_transform_auto object_position_transform
|
||||
# define object_dir_transform_auto object_dir_transform
|
||||
# define object_normal_transform_auto object_normal_transform
|
||||
#else
|
||||
# define object_position_transform_auto object_position_transform_addrspace
|
||||
# define object_dir_transform_auto object_dir_transform_addrspace
|
||||
# define object_normal_transform_auto object_normal_transform_addrspace
|
||||
#endif
|
||||
|
|
|
@ -52,8 +52,8 @@ ccl_device_inline void triangle_point_normal(KernelGlobals *kg, int object, int
|
|||
float t = 1.0f - u - v;
|
||||
*P = (u*v0 + v*v1 + t*v2);
|
||||
|
||||
/* get object flags, instance-aware */
|
||||
int object_flag = kernel_tex_fetch(__object_flag, object >= 0 ? object : ~object);
|
||||
/* get object flags */
|
||||
int object_flag = kernel_tex_fetch(__object_flag, object);
|
||||
|
||||
/* compute normal */
|
||||
if(object_flag & SD_NEGATIVE_SCALE_APPLIED)
|
||||
|
|
|
@ -48,10 +48,10 @@ ccl_device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 v
|
|||
eval->scatter = value;
|
||||
}
|
||||
else
|
||||
eval->diffuse = value;
|
||||
#else
|
||||
eval->diffuse = value;
|
||||
#endif
|
||||
{
|
||||
eval->diffuse = value;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO(sergey): This is just a workaround for annoying 6.5 compiler bug. */
|
||||
|
@ -78,10 +78,10 @@ void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3 value)
|
|||
/* skipping transparent, this function is used by for eval(), will be zero then */
|
||||
}
|
||||
else
|
||||
eval->diffuse += value;
|
||||
#else
|
||||
eval->diffuse += value;
|
||||
#endif
|
||||
{
|
||||
eval->diffuse += value;
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device_inline bool bsdf_eval_is_zero(BsdfEval *eval)
|
||||
|
@ -96,10 +96,10 @@ ccl_device_inline bool bsdf_eval_is_zero(BsdfEval *eval)
|
|||
&& is_zero(eval->scatter);
|
||||
}
|
||||
else
|
||||
return is_zero(eval->diffuse);
|
||||
#else
|
||||
return is_zero(eval->diffuse);
|
||||
#endif
|
||||
{
|
||||
return is_zero(eval->diffuse);
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float3 value)
|
||||
|
@ -115,10 +115,10 @@ ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float3 value)
|
|||
/* skipping transparent, this function is used by for eval(), will be zero then */
|
||||
}
|
||||
else
|
||||
eval->diffuse *= value;
|
||||
#else
|
||||
eval->diffuse *= value;
|
||||
#endif
|
||||
{
|
||||
eval->diffuse *= value;
|
||||
}
|
||||
}
|
||||
|
||||
/* Path Radiance
|
||||
|
@ -170,10 +170,10 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
|
|||
L->mist = 0.0f;
|
||||
}
|
||||
else
|
||||
L->emission = make_float3(0.0f, 0.0f, 0.0f);
|
||||
#else
|
||||
L->emission = make_float3(0.0f, 0.0f, 0.0f);
|
||||
#endif
|
||||
{
|
||||
L->emission = make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device_inline void path_radiance_bsdf_bounce(PathRadiance *L, ccl_addr_space float3 *throughput,
|
||||
|
@ -205,10 +205,10 @@ ccl_device_inline void path_radiance_bsdf_bounce(PathRadiance *L, ccl_addr_space
|
|||
}
|
||||
}
|
||||
else
|
||||
*throughput *= bsdf_eval->diffuse*inverse_pdf;
|
||||
#else
|
||||
*throughput *= bsdf_eval->diffuse*inverse_pdf;
|
||||
#endif
|
||||
{
|
||||
*throughput *= bsdf_eval->diffuse*inverse_pdf;
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device_inline void path_radiance_accum_emission(PathRadiance *L, float3 throughput, float3 value, int bounce)
|
||||
|
@ -223,10 +223,10 @@ ccl_device_inline void path_radiance_accum_emission(PathRadiance *L, float3 thro
|
|||
L->indirect += throughput*value;
|
||||
}
|
||||
else
|
||||
L->emission += throughput*value;
|
||||
#else
|
||||
L->emission += throughput*value;
|
||||
#endif
|
||||
{
|
||||
L->emission += throughput*value;
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device_inline void path_radiance_accum_ao(PathRadiance *L, float3 throughput, float3 alpha, float3 bsdf, float3 ao, int bounce)
|
||||
|
@ -244,10 +244,10 @@ ccl_device_inline void path_radiance_accum_ao(PathRadiance *L, float3 throughput
|
|||
}
|
||||
}
|
||||
else
|
||||
L->emission += throughput*bsdf*ao;
|
||||
#else
|
||||
L->emission += throughput*bsdf*ao;
|
||||
#endif
|
||||
{
|
||||
L->emission += throughput*bsdf*ao;
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughput, BsdfEval *bsdf_eval, float3 shadow, float shadow_fac, int bounce, bool is_lamp)
|
||||
|
@ -275,10 +275,10 @@ ccl_device_inline void path_radiance_accum_light(PathRadiance *L, float3 through
|
|||
}
|
||||
}
|
||||
else
|
||||
L->emission += throughput*bsdf_eval->diffuse*shadow;
|
||||
#else
|
||||
L->emission += throughput*bsdf_eval->diffuse*shadow;
|
||||
#endif
|
||||
{
|
||||
L->emission += throughput*bsdf_eval->diffuse*shadow;
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device_inline void path_radiance_accum_background(PathRadiance *L, float3 throughput, float3 value, int bounce)
|
||||
|
@ -293,10 +293,10 @@ ccl_device_inline void path_radiance_accum_background(PathRadiance *L, float3 th
|
|||
L->indirect += throughput*value;
|
||||
}
|
||||
else
|
||||
L->emission += throughput*value;
|
||||
#else
|
||||
L->emission += throughput*value;
|
||||
#endif
|
||||
{
|
||||
L->emission += throughput*value;
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device_inline void path_radiance_sum_indirect(PathRadiance *L)
|
||||
|
@ -439,10 +439,10 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadi
|
|||
|
||||
/* No Light Passes */
|
||||
else
|
||||
L_sum = L->emission;
|
||||
#else
|
||||
L_sum = L->emission;
|
||||
#endif
|
||||
{
|
||||
L_sum = L->emission;
|
||||
}
|
||||
|
||||
/* Reject invalid value */
|
||||
float sum = fabsf((L_sum).x) + fabsf((L_sum).y) + fabsf((L_sum).z);
|
||||
|
@ -471,14 +471,12 @@ ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance
|
|||
L->indirect_subsurface += L_sample->indirect_subsurface*fac;
|
||||
L->indirect_scatter += L_sample->indirect_scatter*fac;
|
||||
|
||||
L->emission += L_sample->emission*fac;
|
||||
L->background += L_sample->background*fac;
|
||||
L->ao += L_sample->ao*fac;
|
||||
L->shadow += L_sample->shadow*fac;
|
||||
L->mist += L_sample->mist*fac;
|
||||
#else
|
||||
L->emission += L_sample->emission * fac;
|
||||
#endif
|
||||
L->emission += L_sample->emission * fac;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
@ -41,7 +41,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
|
|||
ray.D = -sd->Ng;
|
||||
ray.t = FLT_MAX;
|
||||
#ifdef __CAMERA_MOTION__
|
||||
ray.time = TIME_INVALID;
|
||||
ray.time = 0.5f;
|
||||
#endif
|
||||
|
||||
/* init radiance */
|
||||
|
@ -313,15 +313,14 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
|
|||
|
||||
triangle_point_normal(kg, object, prim, u, v, &P, &Ng, &shader);
|
||||
|
||||
/* dummy initilizations copied from SHADER_EVAL_DISPLACE */
|
||||
float3 I = Ng;
|
||||
float t = 1.0f;
|
||||
float time = TIME_INVALID;
|
||||
|
||||
/* light passes */
|
||||
PathRadiance L;
|
||||
|
||||
shader_setup_from_sample(kg, &sd, P, Ng, I, shader, object, prim, u, v, t, time);
|
||||
shader_setup_from_sample(kg, &sd,
|
||||
P, Ng, Ng,
|
||||
shader, object, prim,
|
||||
u, v, 1.0f, 0.5f,
|
||||
!(kernel_tex_fetch(__object_flag, object) & SD_TRANSFORM_APPLIED));
|
||||
sd.I = sd.N;
|
||||
|
||||
/* update differentials */
|
||||
|
@ -525,6 +524,8 @@ ccl_device void kernel_shader_evaluate(KernelGlobals *kg,
|
|||
float3 P = sd.P;
|
||||
shader_eval_displacement(kg, &sd, &state, SHADER_CONTEXT_MAIN);
|
||||
out = sd.P - P;
|
||||
|
||||
object_inverse_dir_transform(kg, &sd, &out);
|
||||
}
|
||||
else { // SHADER_EVAL_BACKGROUND
|
||||
/* setup ray */
|
||||
|
|
|
@ -321,7 +321,7 @@ ccl_device_inline void camera_sample(KernelGlobals *kg,
|
|||
#ifdef __CAMERA_MOTION__
|
||||
/* motion blur */
|
||||
if(kernel_data.cam.shuttertime == -1.0f) {
|
||||
ray->time = TIME_INVALID;
|
||||
ray->time = 0.5f;
|
||||
}
|
||||
else {
|
||||
/* TODO(sergey): Such lookup is unneeded when there's rolling shutter
|
||||
|
|
|
@ -29,6 +29,8 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg,
|
|||
/* setup shading at emitter */
|
||||
float3 eval;
|
||||
|
||||
int shader_flag = kernel_tex_fetch(__shader_flag, (ls->shader & SHADER_MASK)*SHADER_SIZE);
|
||||
|
||||
#ifdef __BACKGROUND_MIS__
|
||||
if(ls->type == LIGHT_BACKGROUND) {
|
||||
Ray ray;
|
||||
|
@ -49,8 +51,21 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg,
|
|||
}
|
||||
else
|
||||
#endif
|
||||
if(shader_flag & SD_HAS_CONSTANT_EMISSION)
|
||||
{
|
||||
shader_setup_from_sample(kg, emission_sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, ls->u, ls->v, t, time);
|
||||
eval.x = __int_as_float(kernel_tex_fetch(__shader_flag, (ls->shader & SHADER_MASK)*SHADER_SIZE + 2));
|
||||
eval.y = __int_as_float(kernel_tex_fetch(__shader_flag, (ls->shader & SHADER_MASK)*SHADER_SIZE + 3));
|
||||
eval.z = __int_as_float(kernel_tex_fetch(__shader_flag, (ls->shader & SHADER_MASK)*SHADER_SIZE + 4));
|
||||
if((ls->prim != PRIM_NONE) && dot(ls->Ng, I) < 0.0f) {
|
||||
ls->Ng = -ls->Ng;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
shader_setup_from_sample(kg, emission_sd,
|
||||
ls->P, ls->Ng, I,
|
||||
ls->shader, ls->object, ls->prim,
|
||||
ls->u, ls->v, t, time, false);
|
||||
|
||||
ls->Ng = ccl_fetch(emission_sd, Ng);
|
||||
|
||||
|
|
|
@ -510,7 +510,7 @@ ccl_device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3
|
|||
return t*t/cos_pi;
|
||||
}
|
||||
|
||||
ccl_device_inline void lamp_light_sample(KernelGlobals *kg,
|
||||
ccl_device_inline bool lamp_light_sample(KernelGlobals *kg,
|
||||
int lamp,
|
||||
float randu, float randv,
|
||||
float3 P,
|
||||
|
@ -581,6 +581,9 @@ ccl_device_inline void lamp_light_sample(KernelGlobals *kg,
|
|||
/* spot light attenuation */
|
||||
float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2);
|
||||
ls->eval_fac *= spot_light_attenuation(data1, data2, ls);
|
||||
if(ls->eval_fac == 0.0f) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
|
||||
}
|
||||
|
@ -593,6 +596,10 @@ ccl_device_inline void lamp_light_sample(KernelGlobals *kg,
|
|||
float3 axisv = make_float3(data2.y, data2.z, data2.w);
|
||||
float3 D = make_float3(data3.y, data3.z, data3.w);
|
||||
|
||||
if(dot(ls->P - P, D) > 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ls->pdf = area_light_sample(P, &ls->P,
|
||||
axisu, axisv,
|
||||
randu, randv,
|
||||
|
@ -603,13 +610,12 @@ ccl_device_inline void lamp_light_sample(KernelGlobals *kg,
|
|||
|
||||
float invarea = data2.x;
|
||||
ls->eval_fac = 0.25f*invarea;
|
||||
|
||||
if(dot(ls->D, D) > 0.0f)
|
||||
ls->pdf = 0.0f;
|
||||
}
|
||||
|
||||
ls->eval_fac *= kernel_data.integrator.inv_pdf_lights;
|
||||
}
|
||||
|
||||
return (ls->pdf > 0.0f);
|
||||
}
|
||||
|
||||
ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, float t, LightSample *ls)
|
||||
|
@ -747,7 +753,7 @@ ccl_device void object_transform_light_sample(KernelGlobals *kg, LightSample *ls
|
|||
{
|
||||
#ifdef __INSTANCING__
|
||||
/* instance transform */
|
||||
if(object >= 0) {
|
||||
if(!(kernel_tex_fetch(__object_flag, object) & SD_TRANSFORM_APPLIED)) {
|
||||
# ifdef __OBJECT_MOTION__
|
||||
Transform itfm;
|
||||
Transform tfm = object_fetch_transform_motion_test(kg, object, time, &itfm);
|
||||
|
@ -836,7 +842,7 @@ ccl_device bool light_select_reached_max_bounces(KernelGlobals *kg, int index, i
|
|||
return (bounce > __float_as_int(data4.x));
|
||||
}
|
||||
|
||||
ccl_device_noinline void light_sample(KernelGlobals *kg,
|
||||
ccl_device_noinline bool light_sample(KernelGlobals *kg,
|
||||
float randt,
|
||||
float randu,
|
||||
float randv,
|
||||
|
@ -857,21 +863,20 @@ ccl_device_noinline void light_sample(KernelGlobals *kg,
|
|||
int shader_flag = __float_as_int(l.z);
|
||||
|
||||
triangle_light_sample(kg, prim, object, randu, randv, time, ls);
|
||||
|
||||
/* compute incoming direction, distance and pdf */
|
||||
ls->D = normalize_len(ls->P - P, &ls->t);
|
||||
ls->pdf = triangle_light_pdf(kg, ls->Ng, -ls->D, ls->t);
|
||||
ls->shader |= shader_flag;
|
||||
return (ls->pdf > 0.0f);
|
||||
}
|
||||
else {
|
||||
int lamp = -prim-1;
|
||||
|
||||
if(UNLIKELY(light_select_reached_max_bounces(kg, lamp, bounce))) {
|
||||
ls->pdf = 0.0f;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
lamp_light_sample(kg, lamp, randu, randv, P, ls);
|
||||
return lamp_light_sample(kg, lamp, randu, randv, P, ls);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,15 +54,15 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal
|
|||
path_branched_rng_2D(kg, &lamp_rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
|
||||
|
||||
LightSample ls;
|
||||
lamp_light_sample(kg, i, light_u, light_v, ccl_fetch(sd, P), &ls);
|
||||
if(lamp_light_sample(kg, i, light_u, light_v, ccl_fetch(sd, P), &ls)) {
|
||||
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp);
|
||||
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -86,15 +86,15 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal
|
|||
light_t = 0.5f*light_t;
|
||||
|
||||
LightSample ls;
|
||||
light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls);
|
||||
if(light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls)) {
|
||||
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp);
|
||||
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,16 +107,16 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal
|
|||
path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
|
||||
|
||||
LightSample ls;
|
||||
light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls);
|
||||
if(light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls)) {
|
||||
/* sample random light */
|
||||
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
/* sample random light */
|
||||
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(L, throughput*num_samples_adjust, &L_light, shadow, num_samples_adjust, state->bounce, is_lamp);
|
||||
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(L, throughput*num_samples_adjust, &L_light, shadow, num_samples_adjust, state->bounce, is_lamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -206,15 +206,15 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, ccl_
|
|||
#endif
|
||||
|
||||
LightSample ls;
|
||||
light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls);
|
||||
if(light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls)) {
|
||||
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(L, throughput, &L_light, shadow, 1.0f, state->bounce, is_lamp);
|
||||
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(L, throughput, &L_light, shadow, 1.0f, state->bounce, is_lamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -46,17 +46,16 @@ ccl_device_inline void kernel_path_volume_connect_light(
|
|||
light_ray.time = sd->time;
|
||||
# endif
|
||||
|
||||
light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls);
|
||||
if(ls.pdf == 0.0f)
|
||||
return;
|
||||
|
||||
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls))
|
||||
{
|
||||
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(L, throughput, &L_light, shadow, 1.0f, state->bounce, is_lamp);
|
||||
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(L, throughput, &L_light, shadow, 1.0f, state->bounce, is_lamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -146,7 +145,7 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
|
|||
path_branched_rng_2D(kg, &lamp_rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
|
||||
|
||||
LightSample ls;
|
||||
lamp_light_sample(kg, i, light_u, light_v, ray->P, &ls);
|
||||
lamp_light_sample(kg, i, light_u, light_v, ray->P, &ls);
|
||||
|
||||
float3 tp = throughput;
|
||||
|
||||
|
@ -156,23 +155,20 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
|
|||
|
||||
VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
|
||||
state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
|
||||
|
||||
|
||||
(void)result;
|
||||
kernel_assert(result == VOLUME_PATH_SCATTERED);
|
||||
|
||||
/* todo: split up light_sample so we don't have to call it again with new position */
|
||||
lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls);
|
||||
if(lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls)) {
|
||||
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(ls.pdf == 0.0f)
|
||||
continue;
|
||||
|
||||
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(L, tp*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp);
|
||||
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(L, tp*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -212,18 +208,15 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
|
|||
kernel_assert(result == VOLUME_PATH_SCATTERED);
|
||||
|
||||
/* todo: split up light_sample so we don't have to call it again with new position */
|
||||
light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls);
|
||||
if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
|
||||
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(ls.pdf == 0.0f)
|
||||
continue;
|
||||
|
||||
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(L, tp*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp);
|
||||
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(L, tp*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -251,19 +244,16 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
|
|||
kernel_assert(result == VOLUME_PATH_SCATTERED);
|
||||
|
||||
/* todo: split up light_sample so we don't have to call it again with new position */
|
||||
light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls);
|
||||
if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
|
||||
/* sample random light */
|
||||
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(ls.pdf == 0.0f)
|
||||
return;
|
||||
|
||||
/* sample random light */
|
||||
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(L, tp, &L_light, shadow, 1.0f, state->bounce, is_lamp);
|
||||
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(L, tp, &L_light, shadow, 1.0f, state->bounce, is_lamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ ccl_device_noinline void shader_setup_from_ray(KernelGlobals *kg,
|
|||
|
||||
ccl_fetch(sd, I) = -ray->D;
|
||||
|
||||
ccl_fetch(sd, flag) |= kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*2);
|
||||
ccl_fetch(sd, flag) |= kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*SHADER_SIZE);
|
||||
|
||||
#ifdef __INSTANCING__
|
||||
if(isect->object != OBJECT_NONE) {
|
||||
|
@ -195,7 +195,7 @@ void shader_setup_from_subsurface(
|
|||
motion_triangle_shader_setup(kg, sd, isect, ray, true);
|
||||
}
|
||||
|
||||
sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
|
||||
sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE);
|
||||
|
||||
# ifdef __INSTANCING__
|
||||
if(isect->object != OBJECT_NONE) {
|
||||
|
@ -241,7 +241,8 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
|
|||
const float3 I,
|
||||
int shader, int object, int prim,
|
||||
float u, float v, float t,
|
||||
float time)
|
||||
float time,
|
||||
bool object_space)
|
||||
{
|
||||
/* vectors */
|
||||
ccl_fetch(sd, P) = P;
|
||||
|
@ -263,21 +264,7 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
|
|||
#endif
|
||||
ccl_fetch(sd, ray_length) = t;
|
||||
|
||||
/* detect instancing, for non-instanced the object index is -object-1 */
|
||||
#ifdef __INSTANCING__
|
||||
bool instanced = false;
|
||||
|
||||
if(ccl_fetch(sd, prim) != PRIM_NONE) {
|
||||
if(ccl_fetch(sd, object) >= 0)
|
||||
instanced = true;
|
||||
else
|
||||
#endif
|
||||
ccl_fetch(sd, object) = ~ccl_fetch(sd, object);
|
||||
#ifdef __INSTANCING__
|
||||
}
|
||||
#endif
|
||||
|
||||
ccl_fetch(sd, flag) = kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*2);
|
||||
ccl_fetch(sd, flag) = kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*SHADER_SIZE);
|
||||
if(ccl_fetch(sd, object) != OBJECT_NONE) {
|
||||
ccl_fetch(sd, flag) |= kernel_tex_fetch(__object_flag, ccl_fetch(sd, object));
|
||||
|
||||
|
@ -290,14 +277,23 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
|
|||
}
|
||||
#endif
|
||||
|
||||
/* transform into world space */
|
||||
if(object_space) {
|
||||
object_position_transform_auto(kg, sd, &ccl_fetch(sd, P));
|
||||
object_normal_transform_auto(kg, sd, &ccl_fetch(sd, Ng));
|
||||
ccl_fetch(sd, N) = ccl_fetch(sd, Ng);
|
||||
object_dir_transform_auto(kg, sd, &ccl_fetch(sd, I));
|
||||
}
|
||||
|
||||
if(ccl_fetch(sd, type) & PRIMITIVE_TRIANGLE) {
|
||||
/* smooth normal */
|
||||
if(ccl_fetch(sd, shader) & SHADER_SMOOTH_NORMAL) {
|
||||
ccl_fetch(sd, N) = triangle_smooth_normal(kg, ccl_fetch(sd, prim), ccl_fetch(sd, u), ccl_fetch(sd, v));
|
||||
|
||||
#ifdef __INSTANCING__
|
||||
if(instanced)
|
||||
if(!(ccl_fetch(sd, flag) & SD_TRANSFORM_APPLIED)) {
|
||||
object_normal_transform_auto(kg, sd, &ccl_fetch(sd, N));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -306,7 +302,7 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
|
|||
triangle_dPdudv(kg, ccl_fetch(sd, prim), &ccl_fetch(sd, dPdu), &ccl_fetch(sd, dPdv));
|
||||
|
||||
# ifdef __INSTANCING__
|
||||
if(instanced) {
|
||||
if(!(ccl_fetch(sd, flag) & SD_TRANSFORM_APPLIED)) {
|
||||
object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdu));
|
||||
object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdv));
|
||||
}
|
||||
|
@ -357,9 +353,11 @@ ccl_device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
|
|||
/* force smooth shading for displacement */
|
||||
shader |= SHADER_SMOOTH_NORMAL;
|
||||
|
||||
/* watch out: no instance transform currently */
|
||||
|
||||
shader_setup_from_sample(kg, sd, P, Ng, I, shader, object, prim, u, v, 0.0f, TIME_INVALID);
|
||||
shader_setup_from_sample(kg, sd,
|
||||
P, Ng, I,
|
||||
shader, object, prim,
|
||||
u, v, 0.0f, 0.5f,
|
||||
!(kernel_tex_fetch(__object_flag, object) & SD_TRANSFORM_APPLIED));
|
||||
}
|
||||
|
||||
/* ShaderData setup from ray into background */
|
||||
|
@ -372,7 +370,7 @@ ccl_device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderDat
|
|||
ccl_fetch(sd, Ng) = -ray->D;
|
||||
ccl_fetch(sd, I) = -ray->D;
|
||||
ccl_fetch(sd, shader) = kernel_data.background.surface_shader;
|
||||
ccl_fetch(sd, flag) = kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*2);
|
||||
ccl_fetch(sd, flag) = kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*SHADER_SIZE);
|
||||
#ifdef __OBJECT_MOTION__
|
||||
ccl_fetch(sd, time) = ray->time;
|
||||
#endif
|
||||
|
@ -1029,7 +1027,7 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg,
|
|||
sd->shader = stack[i].shader;
|
||||
|
||||
sd->flag &= ~(SD_SHADER_FLAGS|SD_OBJECT_FLAGS);
|
||||
sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
|
||||
sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE);
|
||||
|
||||
if(sd->object != OBJECT_NONE) {
|
||||
sd->flag |= kernel_tex_fetch(__object_flag, sd->object);
|
||||
|
@ -1102,7 +1100,7 @@ ccl_device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect
|
|||
shader = __float_as_int(str.z);
|
||||
}
|
||||
#endif
|
||||
int flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*2);
|
||||
int flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*SHADER_SIZE);
|
||||
|
||||
return (flag & SD_HAS_TRANSPARENT_SHADOW) != 0;
|
||||
}
|
||||
|
|
|
@ -360,14 +360,15 @@ int subsurface_scatter_multi_intersect(
|
|||
return num_eval_hits;
|
||||
}
|
||||
|
||||
ccl_device void subsurface_scatter_multi_setup(KernelGlobals *kg,
|
||||
SubsurfaceIntersection* ss_isect,
|
||||
int hit,
|
||||
ShaderData *sd,
|
||||
PathState *state,
|
||||
int state_flag,
|
||||
ShaderClosure *sc,
|
||||
bool all)
|
||||
ccl_device_noinline void subsurface_scatter_multi_setup(
|
||||
KernelGlobals *kg,
|
||||
SubsurfaceIntersection* ss_isect,
|
||||
int hit,
|
||||
ShaderData *sd,
|
||||
PathState *state,
|
||||
int state_flag,
|
||||
ShaderClosure *sc,
|
||||
bool all)
|
||||
{
|
||||
/* Setup new shading point. */
|
||||
shader_setup_from_subsurface(kg, sd, &ss_isect->hits[hit], &ss_isect->ray);
|
||||
|
|
|
@ -42,7 +42,7 @@ CCL_NAMESPACE_BEGIN
|
|||
#define RAMP_TABLE_SIZE 256
|
||||
#define SHUTTER_TABLE_SIZE 256
|
||||
#define PARTICLE_SIZE 5
|
||||
#define TIME_INVALID FLT_MAX
|
||||
#define SHADER_SIZE 5
|
||||
|
||||
#define BSSRDF_MIN_RADIUS 1e-8f
|
||||
#define BSSRDF_MAX_HITS 4
|
||||
|
@ -715,20 +715,21 @@ enum ShaderDataFlag {
|
|||
SD_VOLUME_CUBIC = (1 << 20), /* use cubic interpolation for voxels */
|
||||
SD_HAS_BUMP = (1 << 21), /* has data connected to the displacement input */
|
||||
SD_HAS_DISPLACEMENT = (1 << 22), /* has true displacement */
|
||||
SD_HAS_CONSTANT_EMISSION = (1 << 23), /* has constant emission (value stored in __shader_flag) */
|
||||
|
||||
SD_SHADER_FLAGS = (SD_USE_MIS|SD_HAS_TRANSPARENT_SHADOW|SD_HAS_VOLUME|
|
||||
SD_HAS_ONLY_VOLUME|SD_HETEROGENEOUS_VOLUME|
|
||||
SD_HAS_BSSRDF_BUMP|SD_VOLUME_EQUIANGULAR|SD_VOLUME_MIS|
|
||||
SD_VOLUME_CUBIC|SD_HAS_BUMP|SD_HAS_DISPLACEMENT),
|
||||
SD_VOLUME_CUBIC|SD_HAS_BUMP|SD_HAS_DISPLACEMENT|SD_HAS_CONSTANT_EMISSION),
|
||||
|
||||
/* object flags */
|
||||
SD_HOLDOUT_MASK = (1 << 23), /* holdout for camera rays */
|
||||
SD_OBJECT_MOTION = (1 << 24), /* has object motion blur */
|
||||
SD_TRANSFORM_APPLIED = (1 << 25), /* vertices have transform applied */
|
||||
SD_NEGATIVE_SCALE_APPLIED = (1 << 26), /* vertices have negative scale applied */
|
||||
SD_OBJECT_HAS_VOLUME = (1 << 27), /* object has a volume shader */
|
||||
SD_OBJECT_INTERSECTS_VOLUME = (1 << 28), /* object intersects AABB of an object with volume shader */
|
||||
SD_OBJECT_HAS_VERTEX_MOTION = (1 << 29), /* has position for motion vertices */
|
||||
SD_HOLDOUT_MASK = (1 << 24), /* holdout for camera rays */
|
||||
SD_OBJECT_MOTION = (1 << 25), /* has object motion blur */
|
||||
SD_TRANSFORM_APPLIED = (1 << 26), /* vertices have transform applied */
|
||||
SD_NEGATIVE_SCALE_APPLIED = (1 << 27), /* vertices have negative scale applied */
|
||||
SD_OBJECT_HAS_VOLUME = (1 << 28), /* object has a volume shader */
|
||||
SD_OBJECT_INTERSECTS_VOLUME = (1 << 29), /* object intersects AABB of an object with volume shader */
|
||||
SD_OBJECT_HAS_VERTEX_MOTION = (1 << 30), /* has position for motion vertices */
|
||||
|
||||
SD_OBJECT_FLAGS = (SD_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_TRANSFORM_APPLIED|
|
||||
SD_NEGATIVE_SCALE_APPLIED|SD_OBJECT_HAS_VOLUME|
|
||||
|
|
|
@ -115,7 +115,7 @@ ccl_device float kernel_volume_channel_get(float3 value, int channel)
|
|||
ccl_device bool volume_stack_is_heterogeneous(KernelGlobals *kg, VolumeStack *stack)
|
||||
{
|
||||
for(int i = 0; stack[i].shader != SHADER_NONE; i++) {
|
||||
int shader_flag = kernel_tex_fetch(__shader_flag, (stack[i].shader & SHADER_MASK)*2);
|
||||
int shader_flag = kernel_tex_fetch(__shader_flag, (stack[i].shader & SHADER_MASK)*SHADER_SIZE);
|
||||
|
||||
if(shader_flag & SD_HETEROGENEOUS_VOLUME)
|
||||
return true;
|
||||
|
@ -132,7 +132,7 @@ ccl_device int volume_stack_sampling_method(KernelGlobals *kg, VolumeStack *stac
|
|||
int method = -1;
|
||||
|
||||
for(int i = 0; stack[i].shader != SHADER_NONE; i++) {
|
||||
int shader_flag = kernel_tex_fetch(__shader_flag, (stack[i].shader & SHADER_MASK)*2);
|
||||
int shader_flag = kernel_tex_fetch(__shader_flag, (stack[i].shader & SHADER_MASK)*SHADER_SIZE);
|
||||
|
||||
if(shader_flag & SD_VOLUME_MIS) {
|
||||
return SD_VOLUME_MIS;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
surface node_bump(
|
||||
int invert = 0,
|
||||
int use_object_space = 0,
|
||||
normal NormalIn = N,
|
||||
float Strength = 0.1,
|
||||
float Distance = 1.0,
|
||||
|
@ -29,12 +30,20 @@ surface node_bump(
|
|||
float SampleY = 0.0,
|
||||
output normal NormalOut = N)
|
||||
{
|
||||
/* get surface tangents from normal */
|
||||
vector dPdx = Dx(P);
|
||||
vector dPdy = Dy(P);
|
||||
point Ptmp = P;
|
||||
normal Normal = NormalIn;
|
||||
|
||||
vector Rx = cross(dPdy, NormalIn);
|
||||
vector Ry = cross(NormalIn, dPdx);
|
||||
if (use_object_space) {
|
||||
Ptmp = transform("object", Ptmp);
|
||||
Normal = normalize(transform("object", Normal));
|
||||
}
|
||||
|
||||
/* get surface tangents from normal */
|
||||
vector dPdx = Dx(Ptmp);
|
||||
vector dPdy = Dy(Ptmp);
|
||||
|
||||
vector Rx = cross(dPdy, Normal);
|
||||
vector Ry = cross(Normal, dPdx);
|
||||
|
||||
/* compute surface gradient and determinant */
|
||||
float det = dot(dPdx, Rx);
|
||||
|
@ -49,7 +58,11 @@ surface node_bump(
|
|||
dist *= -1.0;
|
||||
|
||||
/* compute and output perturbed normal */
|
||||
NormalOut = normalize(absdet * NormalIn - dist * sign(det) * surfgrad);
|
||||
NormalOut = normalize(strength * NormalOut + (1.0 - strength) * NormalIn);
|
||||
NormalOut = normalize(absdet * Normal - dist * sign(det) * surfgrad);
|
||||
NormalOut = normalize(strength * NormalOut + (1.0 - strength) * Normal);
|
||||
|
||||
if (use_object_space) {
|
||||
NormalOut = normalize(transform("object", "world", NormalOut));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
displacement node_output_displacement(float Displacement = 0.0)
|
||||
{
|
||||
P += N * Displacement * 0.1; /* todo: get rid of this factor */
|
||||
vector dP = normalize(transform("object", N));
|
||||
dP *= Displacement * 0.1; /* todo: get rid of this factor */
|
||||
P += transform("object", "world", dP);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@ shader node_rgb_curves(
|
|||
color c = (ColorIn - color(min_x, min_x, min_x)) / (max_x - min_x);
|
||||
|
||||
color r = rgb_ramp_lookup(ramp, c[0], 1, 1);
|
||||
color g = rgb_ramp_lookup(ramp, c[0], 1, 1);
|
||||
color b = rgb_ramp_lookup(ramp, c[0], 1, 1);
|
||||
color g = rgb_ramp_lookup(ramp, c[1], 1, 1);
|
||||
color b = rgb_ramp_lookup(ramp, c[2], 1, 1);
|
||||
|
||||
ColorOut[0] = r[0];
|
||||
ColorOut[1] = g[1];
|
||||
|
|
|
@ -74,30 +74,31 @@ ccl_device char kernel_direct_lighting(
|
|||
path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
|
||||
|
||||
LightSample ls;
|
||||
light_sample(kg,
|
||||
light_t, light_u, light_v,
|
||||
ccl_fetch(sd, time),
|
||||
ccl_fetch(sd, P),
|
||||
state->bounce,
|
||||
&ls);
|
||||
if(light_sample(kg,
|
||||
light_t, light_u, light_v,
|
||||
ccl_fetch(sd, time),
|
||||
ccl_fetch(sd, P),
|
||||
state->bounce,
|
||||
&ls)) {
|
||||
|
||||
Ray light_ray;
|
||||
Ray light_ray;
|
||||
#ifdef __OBJECT_MOTION__
|
||||
light_ray.time = ccl_fetch(sd, time);
|
||||
light_ray.time = ccl_fetch(sd, time);
|
||||
#endif
|
||||
|
||||
BsdfEval L_light;
|
||||
bool is_lamp;
|
||||
if(direct_emission(kg, sd, kg->sd_input, &ls, state, &light_ray, &L_light, &is_lamp)) {
|
||||
/* Write intermediate data to global memory to access from
|
||||
* the next kernel.
|
||||
*/
|
||||
LightRay_coop[ray_index] = light_ray;
|
||||
BSDFEval_coop[ray_index] = L_light;
|
||||
ISLamp_coop[ray_index] = is_lamp;
|
||||
/* Mark ray state for next shadow kernel. */
|
||||
ADD_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL);
|
||||
enqueue_flag = 1;
|
||||
BsdfEval L_light;
|
||||
bool is_lamp;
|
||||
if(direct_emission(kg, sd, kg->sd_input, &ls, state, &light_ray, &L_light, &is_lamp)) {
|
||||
/* Write intermediate data to global memory to access from
|
||||
* the next kernel.
|
||||
*/
|
||||
LightRay_coop[ray_index] = light_ray;
|
||||
BSDFEval_coop[ray_index] = L_light;
|
||||
ISLamp_coop[ray_index] = is_lamp;
|
||||
/* Mark ray state for next shadow kernel. */
|
||||
ADD_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL);
|
||||
enqueue_flag = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* __EMISSION__ */
|
||||
|
|
|
@ -261,7 +261,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_a
|
|||
svm_node_geometry_bump_dy(kg, sd, stack, node.y, node.z);
|
||||
break;
|
||||
case NODE_SET_DISPLACEMENT:
|
||||
svm_node_set_displacement(sd, stack, node.y);
|
||||
svm_node_set_displacement(kg, sd, stack, node.y);
|
||||
break;
|
||||
# endif /* NODES_FEATURE(NODE_FEATURE_BUMP) */
|
||||
# ifdef __TEXTURES__
|
||||
|
@ -295,12 +295,14 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_a
|
|||
case NODE_CLOSURE_SET_NORMAL:
|
||||
svm_node_set_normal(kg, sd, stack, node.y, node.z);
|
||||
break;
|
||||
# if NODES_FEATURE(NODE_FEATURE_BUMP_STATE)
|
||||
case NODE_ENTER_BUMP_EVAL:
|
||||
svm_node_enter_bump_eval(kg, sd, stack, node.y);
|
||||
break;
|
||||
case NODE_LEAVE_BUMP_EVAL:
|
||||
svm_node_leave_bump_eval(kg, sd, stack, node.y);
|
||||
break;
|
||||
# endif /* NODES_FEATURE(NODE_FEATURE_BUMP_STATE) */
|
||||
# endif /* NODES_FEATURE(NODE_FEATURE_BUMP) */
|
||||
case NODE_HSV:
|
||||
svm_node_hsv(kg, sd, stack, node, &offset);
|
||||
|
|
|
@ -22,14 +22,23 @@ ccl_device void svm_node_set_bump(KernelGlobals *kg, ShaderData *sd, float *stac
|
|||
{
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
/* get normal input */
|
||||
uint normal_offset, distance_offset, invert;
|
||||
decode_node_uchar4(node.y, &normal_offset, &distance_offset, &invert, NULL);
|
||||
uint normal_offset, distance_offset, invert, use_object_space;
|
||||
decode_node_uchar4(node.y, &normal_offset, &distance_offset, &invert, &use_object_space);
|
||||
|
||||
float3 normal_in = stack_valid(normal_offset)? stack_load_float3(stack, normal_offset): ccl_fetch(sd, N);
|
||||
|
||||
float3 dPdx = ccl_fetch(sd, dP).dx;
|
||||
float3 dPdy = ccl_fetch(sd, dP).dy;
|
||||
|
||||
if(use_object_space) {
|
||||
object_inverse_normal_transform(kg, sd, &normal_in);
|
||||
object_inverse_dir_transform(kg, sd, &dPdx);
|
||||
object_inverse_dir_transform(kg, sd, &dPdy);
|
||||
}
|
||||
|
||||
/* get surface tangents from normal */
|
||||
float3 Rx = cross(ccl_fetch(sd, dP).dy, normal_in);
|
||||
float3 Ry = cross(normal_in, ccl_fetch(sd, dP).dx);
|
||||
float3 Rx = cross(dPdy, normal_in);
|
||||
float3 Ry = cross(normal_in, dPdx);
|
||||
|
||||
/* get bump values */
|
||||
uint c_offset, x_offset, y_offset, strength_offset;
|
||||
|
@ -40,7 +49,7 @@ ccl_device void svm_node_set_bump(KernelGlobals *kg, ShaderData *sd, float *stac
|
|||
float h_y = stack_load_float(stack, y_offset);
|
||||
|
||||
/* compute surface gradient and determinant */
|
||||
float det = dot(ccl_fetch(sd, dP).dx, Rx);
|
||||
float det = dot(dPdx, Rx);
|
||||
float3 surfgrad = (h_x - h_c)*Rx + (h_y - h_c)*Ry;
|
||||
|
||||
float absdet = fabsf(det);
|
||||
|
@ -56,16 +65,29 @@ ccl_device void svm_node_set_bump(KernelGlobals *kg, ShaderData *sd, float *stac
|
|||
/* compute and output perturbed normal */
|
||||
float3 normal_out = normalize(absdet*normal_in - distance*signf(det)*surfgrad);
|
||||
normal_out = normalize(strength*normal_out + (1.0f - strength)*normal_in);
|
||||
|
||||
if(use_object_space) {
|
||||
object_normal_transform(kg, sd, &normal_out);
|
||||
}
|
||||
|
||||
stack_store_float3(stack, node.w, normal_out);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Displacement Node */
|
||||
|
||||
ccl_device void svm_node_set_displacement(ShaderData *sd, float *stack, uint fac_offset)
|
||||
ccl_device void svm_node_set_displacement(KernelGlobals *kg, ShaderData *sd, float *stack, uint fac_offset)
|
||||
{
|
||||
float d = stack_load_float(stack, fac_offset);
|
||||
ccl_fetch(sd, P) += ccl_fetch(sd, N)*d*0.1f; /* todo: get rid of this factor */
|
||||
|
||||
float3 dP = ccl_fetch(sd, N);
|
||||
object_inverse_normal_transform(kg, sd, &dP);
|
||||
|
||||
dP *= d*0.1f; /* todo: get rid of this factor */
|
||||
|
||||
object_dir_transform(kg, sd, &dP);
|
||||
|
||||
ccl_fetch(sd, P) += dP;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
@ -47,11 +47,12 @@ CCL_NAMESPACE_BEGIN
|
|||
#define NODE_FEATURE_VOLUME (1 << 0)
|
||||
#define NODE_FEATURE_HAIR (1 << 1)
|
||||
#define NODE_FEATURE_BUMP (1 << 2)
|
||||
#define NODE_FEATURE_BUMP_STATE (1 << 3)
|
||||
/* TODO(sergey): Consider using something like ((uint)(-1)).
|
||||
* Need to check carefully operand types around usage of this
|
||||
* define first.
|
||||
*/
|
||||
#define NODE_FEATURE_ALL (NODE_FEATURE_VOLUME|NODE_FEATURE_HAIR|NODE_FEATURE_BUMP)
|
||||
#define NODE_FEATURE_ALL (NODE_FEATURE_VOLUME|NODE_FEATURE_HAIR|NODE_FEATURE_BUMP|NODE_FEATURE_BUMP_STATE)
|
||||
|
||||
typedef enum ShaderNodeType {
|
||||
NODE_END = 0,
|
||||
|
|
|
@ -312,7 +312,8 @@ void ShaderGraph::relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to)
|
|||
void ShaderGraph::finalize(Scene *scene,
|
||||
bool do_bump,
|
||||
bool do_osl,
|
||||
bool do_simplify)
|
||||
bool do_simplify,
|
||||
bool bump_in_object_space)
|
||||
{
|
||||
/* before compiling, the shader graph may undergo a number of modifications.
|
||||
* currently we set default geometry shader inputs, and create automatic bump
|
||||
|
@ -325,7 +326,7 @@ void ShaderGraph::finalize(Scene *scene,
|
|||
refine_bump_nodes();
|
||||
|
||||
if(do_bump)
|
||||
bump_from_displacement();
|
||||
bump_from_displacement(bump_in_object_space);
|
||||
|
||||
ShaderInput *surface_in = output()->input("Surface");
|
||||
ShaderInput *volume_in = output()->input("Volume");
|
||||
|
@ -482,6 +483,8 @@ void ShaderGraph::constant_fold()
|
|||
ShaderNodeSet done, scheduled;
|
||||
queue<ShaderNode*> traverse_queue;
|
||||
|
||||
bool has_displacement = (output()->input("Displacement")->link != NULL);
|
||||
|
||||
/* Schedule nodes which doesn't have any dependencies. */
|
||||
foreach(ShaderNode *node, nodes) {
|
||||
if(!check_node_inputs_has_links(node)) {
|
||||
|
@ -519,6 +522,17 @@ void ShaderGraph::constant_fold()
|
|||
node->constant_fold(folder);
|
||||
}
|
||||
}
|
||||
|
||||
/* Folding might have removed all nodes connected to the displacement output
|
||||
* even tho there is displacement to be applied, so add in a value node if
|
||||
* that happens to ensure there is still a valid graph for displacement.
|
||||
*/
|
||||
if(has_displacement && !output()->input("Displacement")->link) {
|
||||
ValueNode *value = (ValueNode*)add(new ValueNode());
|
||||
value->value = output()->displacement;
|
||||
|
||||
connect(value->output("Value"), output()->input("Displacement"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 3: Simplification. */
|
||||
|
@ -793,7 +807,7 @@ void ShaderGraph::refine_bump_nodes()
|
|||
}
|
||||
}
|
||||
|
||||
void ShaderGraph::bump_from_displacement()
|
||||
void ShaderGraph::bump_from_displacement(bool use_object_space)
|
||||
{
|
||||
/* generate bump mapping automatically from displacement. bump mapping is
|
||||
* done using a 3-tap filter, computing the displacement at the center,
|
||||
|
@ -842,7 +856,8 @@ void ShaderGraph::bump_from_displacement()
|
|||
ShaderNode *set_normal = add(new SetNormalNode());
|
||||
|
||||
/* add bump node and connect copied graphs to it */
|
||||
ShaderNode *bump = add(new BumpNode());
|
||||
BumpNode *bump = (BumpNode*)add(new BumpNode());
|
||||
bump->use_object_space = use_object_space;
|
||||
|
||||
ShaderOutput *out = displacement_in->link;
|
||||
ShaderOutput *out_center = nodes_center[out->parent]->output(out->name());
|
||||
|
|
|
@ -258,7 +258,8 @@ public:
|
|||
void finalize(Scene *scene,
|
||||
bool do_bump = false,
|
||||
bool do_osl = false,
|
||||
bool do_simplify = false);
|
||||
bool do_simplify = false,
|
||||
bool bump_in_object_space = false);
|
||||
|
||||
int get_num_closures();
|
||||
|
||||
|
@ -272,7 +273,7 @@ protected:
|
|||
void copy_nodes(ShaderNodeSet& nodes, ShaderNodeMap& nnodemap);
|
||||
|
||||
void break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack);
|
||||
void bump_from_displacement();
|
||||
void bump_from_displacement(bool use_object_space);
|
||||
void refine_bump_nodes();
|
||||
void default_inputs(bool do_osl);
|
||||
void transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume);
|
||||
|
|
|
@ -280,6 +280,8 @@ int ImageManager::add_image(const string& filename,
|
|||
|
||||
ImageDataType type = get_image_metadata(filename, builtin_data, is_linear);
|
||||
|
||||
thread_scoped_lock device_lock(device_mutex);
|
||||
|
||||
/* Do we have a float? */
|
||||
if(type == IMAGE_DATA_TYPE_FLOAT || type == IMAGE_DATA_TYPE_FLOAT4)
|
||||
is_float = true;
|
||||
|
|
|
@ -309,9 +309,6 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
|
|||
int object_id = j;
|
||||
int shader_flag = 0;
|
||||
|
||||
if(transform_applied)
|
||||
object_id = ~object_id;
|
||||
|
||||
if(!(object->visibility & PATH_RAY_DIFFUSE)) {
|
||||
shader_flag |= SHADER_EXCLUDE_DIFFUSE;
|
||||
use_light_visibility = true;
|
||||
|
@ -677,7 +674,6 @@ void LightManager::device_update_points(Device *device,
|
|||
light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, 0.0f);
|
||||
light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
|
||||
light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
else if(light->type == LIGHT_DISTANT) {
|
||||
shader_id &= ~SHADER_AREA_LIGHT;
|
||||
|
@ -698,7 +694,6 @@ void LightManager::device_update_points(Device *device,
|
|||
light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, cosangle, invarea);
|
||||
light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
|
||||
light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
else if(light->type == LIGHT_BACKGROUND) {
|
||||
uint visibility = scene->background->visibility;
|
||||
|
@ -727,7 +722,6 @@ void LightManager::device_update_points(Device *device,
|
|||
light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), 0.0f, 0.0f, 0.0f);
|
||||
light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
|
||||
light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
else if(light->type == LIGHT_AREA) {
|
||||
float3 axisu = light->axisu*(light->sizeu*light->size);
|
||||
|
@ -745,7 +739,6 @@ void LightManager::device_update_points(Device *device,
|
|||
light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z);
|
||||
light_data[light_index*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z);
|
||||
light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, dir.x, dir.y, dir.z);
|
||||
light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
else if(light->type == LIGHT_SPOT) {
|
||||
shader_id &= ~SHADER_AREA_LIGHT;
|
||||
|
@ -765,9 +758,10 @@ void LightManager::device_update_points(Device *device,
|
|||
light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, spot_angle);
|
||||
light_data[light_index*LIGHT_SIZE + 2] = make_float4(spot_smooth, dir.x, dir.y, dir.z);
|
||||
light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
|
||||
light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
light_index++;
|
||||
}
|
||||
|
||||
|
|
|
@ -1650,10 +1650,10 @@ void MeshManager::device_update_displacement_images(Device *device,
|
|||
foreach(Mesh *mesh, scene->meshes) {
|
||||
if(mesh->need_update) {
|
||||
foreach(Shader *shader, mesh->used_shaders) {
|
||||
if(shader->graph_bump == NULL) {
|
||||
if(!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
|
||||
continue;
|
||||
}
|
||||
foreach(ShaderNode* node, shader->graph_bump->nodes) {
|
||||
foreach(ShaderNode* node, shader->graph->nodes) {
|
||||
if(node->special_type != SHADER_SPECIAL_TYPE_IMAGE_SLOT) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -86,8 +86,7 @@ bool MeshManager::displace(Device *device, DeviceScene *dscene, Scene *scene, Me
|
|||
done[t.v[j]] = true;
|
||||
|
||||
/* set up object, primitive and barycentric coordinates */
|
||||
/* when used, non-instanced convention: object = ~object */
|
||||
int object = ~object_index;
|
||||
int object = object_index;
|
||||
int prim = mesh->tri_offset + i;
|
||||
float u, v;
|
||||
|
||||
|
|
|
@ -284,7 +284,12 @@ struct OsdPatch : Patch {
|
|||
|
||||
if(dPdu) *dPdu = du;
|
||||
if(dPdv) *dPdv = dv;
|
||||
if(N) *N = normalize(cross(du, dv));
|
||||
if(N) {
|
||||
*N = cross(du, dv);
|
||||
|
||||
float t = len(*N);
|
||||
*N = (t != 0.0f) ? *N/t : make_float3(0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
BoundBox bound() { return BoundBox::empty; }
|
||||
|
|
|
@ -4762,6 +4762,7 @@ NODE_DEFINE(BumpNode)
|
|||
NodeType* type = NodeType::add("bump", create, NodeType::SHADER);
|
||||
|
||||
SOCKET_BOOLEAN(invert, "Invert", false);
|
||||
SOCKET_BOOLEAN(use_object_space, "UseObjectSpace", false);
|
||||
|
||||
/* this input is used by the user, but after graph transform it is no longer
|
||||
* used and moved to sampler center/x/y instead */
|
||||
|
@ -4800,7 +4801,8 @@ void BumpNode::compile(SVMCompiler& compiler)
|
|||
compiler.encode_uchar4(
|
||||
compiler.stack_assign_if_linked(normal_in),
|
||||
compiler.stack_assign(distance_in),
|
||||
invert),
|
||||
invert,
|
||||
use_object_space),
|
||||
compiler.encode_uchar4(
|
||||
compiler.stack_assign(center_in),
|
||||
compiler.stack_assign(dx_in),
|
||||
|
@ -4812,6 +4814,7 @@ void BumpNode::compile(SVMCompiler& compiler)
|
|||
void BumpNode::compile(OSLCompiler& compiler)
|
||||
{
|
||||
compiler.parameter(this, "invert");
|
||||
compiler.parameter(this, "use_object_space");
|
||||
compiler.add(this, "node_bump");
|
||||
}
|
||||
|
||||
|
|
|
@ -770,6 +770,7 @@ class CameraNode : public ShaderNode {
|
|||
public:
|
||||
SHADER_NODE_CLASS(CameraNode)
|
||||
bool has_spatial_varying() { return true; }
|
||||
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
|
||||
};
|
||||
|
||||
class FresnelNode : public ShaderNode {
|
||||
|
@ -873,6 +874,7 @@ public:
|
|||
}
|
||||
|
||||
bool invert;
|
||||
bool use_object_space;
|
||||
float height;
|
||||
float sample_center;
|
||||
float sample_x;
|
||||
|
|
|
@ -1103,7 +1103,8 @@ void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader)
|
|||
shader->graph_bump->finalize(scene,
|
||||
true,
|
||||
true,
|
||||
shader->has_integrator_dependency);
|
||||
shader->has_integrator_dependency,
|
||||
shader->displacement_method == DISPLACE_BOTH);
|
||||
}
|
||||
|
||||
current_shader = shader;
|
||||
|
|
|
@ -194,6 +194,28 @@ Shader::~Shader()
|
|||
delete graph_bump;
|
||||
}
|
||||
|
||||
bool Shader::is_constant_emission(float3 *emission)
|
||||
{
|
||||
ShaderInput *surf = graph->output()->input("Surface");
|
||||
|
||||
if(!surf->link || surf->link->parent->type != EmissionNode::node_type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EmissionNode *node = (EmissionNode*) surf->link->parent;
|
||||
|
||||
assert(node->input("Color"));
|
||||
assert(node->input("Strength"));
|
||||
|
||||
if(node->input("Color")->link || node->input("Strength")->link) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*emission = node->color*node->strength;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Shader::set_graph(ShaderGraph *graph_)
|
||||
{
|
||||
/* do this here already so that we can detect if mesh or object attributes
|
||||
|
@ -379,7 +401,7 @@ void ShaderManager::device_update_common(Device *device,
|
|||
if(scene->shaders.size() == 0)
|
||||
return;
|
||||
|
||||
uint shader_flag_size = scene->shaders.size()*2;
|
||||
uint shader_flag_size = scene->shaders.size()*SHADER_SIZE;
|
||||
uint *shader_flag = dscene->shader_flag.resize(shader_flag_size);
|
||||
uint i = 0;
|
||||
bool has_volumes = false;
|
||||
|
@ -424,9 +446,17 @@ void ShaderManager::device_update_common(Device *device,
|
|||
if(shader->displacement_method != DISPLACE_TRUE && shader->graph_bump)
|
||||
flag |= SD_HAS_BSSRDF_BUMP;
|
||||
|
||||
/* constant emission check */
|
||||
float3 constant_emission = make_float3(0.0f, 0.0f, 0.0f);
|
||||
if(shader->is_constant_emission(&constant_emission))
|
||||
flag |= SD_HAS_CONSTANT_EMISSION;
|
||||
|
||||
/* regular shader */
|
||||
shader_flag[i++] = flag;
|
||||
shader_flag[i++] = shader->pass_id;
|
||||
shader_flag[i++] = __float_as_int(constant_emission.x);
|
||||
shader_flag[i++] = __float_as_int(constant_emission.y);
|
||||
shader_flag[i++] = __float_as_int(constant_emission.z);
|
||||
|
||||
has_transparent_shadow |= (flag & SD_HAS_TRANSPARENT_SHADOW) != 0;
|
||||
}
|
||||
|
@ -561,6 +591,9 @@ void ShaderManager::get_requested_features(Scene *scene,
|
|||
ShaderNode *output_node = shader->graph->output();
|
||||
if(output_node->input("Displacement")->link != NULL) {
|
||||
requested_features->nodes_features |= NODE_FEATURE_BUMP;
|
||||
if(shader->displacement_method == DISPLACE_BOTH && requested_features->experimental) {
|
||||
requested_features->nodes_features |= NODE_FEATURE_BUMP_STATE;
|
||||
}
|
||||
}
|
||||
/* On top of volume nodes, also check if we need volume sampling because
|
||||
* e.g. an Emission node would slip through the NODE_FEATURE_VOLUME check */
|
||||
|
|
|
@ -139,6 +139,10 @@ public:
|
|||
Shader();
|
||||
~Shader();
|
||||
|
||||
/* Checks whether the shader consists of just a emission node with fixed inputs that's connected directly to the output.
|
||||
* If yes, it sets the content of emission to the constant value (color * strength), which is then used for speeding up light evaluation. */
|
||||
bool is_constant_emission(float3* emission);
|
||||
|
||||
void set_graph(ShaderGraph *graph);
|
||||
void tag_update(Scene *scene);
|
||||
void tag_used(Scene *scene);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "util_logging.h"
|
||||
#include "util_foreach.h"
|
||||
#include "util_progress.h"
|
||||
#include "util_task.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -44,6 +45,51 @@ void SVMShaderManager::reset(Scene * /*scene*/)
|
|||
{
|
||||
}
|
||||
|
||||
void SVMShaderManager::device_update_shader(Scene *scene,
|
||||
Shader *shader,
|
||||
Progress *progress,
|
||||
vector<int4> *global_svm_nodes)
|
||||
{
|
||||
if(progress->get_cancel()) {
|
||||
return;
|
||||
}
|
||||
assert(shader->graph);
|
||||
|
||||
vector<int4> svm_nodes;
|
||||
svm_nodes.push_back(make_int4(NODE_SHADER_JUMP, 0, 0, 0));
|
||||
|
||||
SVMCompiler::Summary summary;
|
||||
SVMCompiler compiler(scene->shader_manager, scene->image_manager);
|
||||
compiler.background = (shader == scene->default_background);
|
||||
compiler.compile(scene, shader, svm_nodes, 0, &summary);
|
||||
|
||||
VLOG(2) << "Compilation summary:\n"
|
||||
<< "Shader name: " << shader->name << "\n"
|
||||
<< summary.full_report();
|
||||
|
||||
if(shader->use_mis && shader->has_surface_emission) {
|
||||
scene->light_manager->need_update = true;
|
||||
}
|
||||
|
||||
/* We only calculate offset and do re-allocation from the locked block,
|
||||
* actual copy we do after the lock is releases to hopefully gain some
|
||||
* percent of performance.
|
||||
*/
|
||||
nodes_lock_.lock();
|
||||
size_t global_nodes_size = global_svm_nodes->size();
|
||||
global_svm_nodes->resize(global_nodes_size + svm_nodes.size());
|
||||
nodes_lock_.unlock();
|
||||
/* Offset local SVM nodes to a global address space. */
|
||||
int4& jump_node = global_svm_nodes->at(shader->id);
|
||||
jump_node.y = svm_nodes[0].y + global_nodes_size - 1;
|
||||
jump_node.z = svm_nodes[0].z + global_nodes_size - 1;
|
||||
jump_node.w = svm_nodes[0].w + global_nodes_size - 1;
|
||||
/* Copy new nodes to global storage. */
|
||||
memcpy(&global_svm_nodes->at(global_nodes_size),
|
||||
&svm_nodes[1],
|
||||
sizeof(int4) * (svm_nodes.size() - 1));
|
||||
}
|
||||
|
||||
void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
|
||||
{
|
||||
if(!need_update)
|
||||
|
@ -51,6 +97,8 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
|
|||
|
||||
VLOG(1) << "Total " << scene->shaders.size() << " shaders.";
|
||||
|
||||
double start_time = time_dt();
|
||||
|
||||
/* test if we need to update */
|
||||
device_free(device, dscene, scene);
|
||||
|
||||
|
@ -65,23 +113,20 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
|
|||
svm_nodes.push_back(make_int4(NODE_SHADER_JUMP, 0, 0, 0));
|
||||
}
|
||||
|
||||
TaskPool task_pool;
|
||||
foreach(Shader *shader, scene->shaders) {
|
||||
if(progress.get_cancel()) return;
|
||||
task_pool.push(function_bind(&SVMShaderManager::device_update_shader,
|
||||
this,
|
||||
scene,
|
||||
shader,
|
||||
&progress,
|
||||
&svm_nodes),
|
||||
false);
|
||||
}
|
||||
task_pool.wait_work();
|
||||
|
||||
assert(shader->graph);
|
||||
|
||||
SVMCompiler::Summary summary;
|
||||
SVMCompiler compiler(scene->shader_manager, scene->image_manager);
|
||||
compiler.background = (shader == scene->default_background);
|
||||
compiler.compile(scene, shader, svm_nodes, shader->id, &summary);
|
||||
|
||||
if(shader->use_mis && shader->has_surface_emission) {
|
||||
scene->light_manager->need_update = true;
|
||||
}
|
||||
|
||||
VLOG(2) << "Compilation summary:\n"
|
||||
<< "Shader name: " << shader->name << "\n"
|
||||
<< summary.full_report();
|
||||
if(progress.get_cancel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
dscene->svm_nodes.copy((uint4*)&svm_nodes[0], svm_nodes.size());
|
||||
|
@ -95,6 +140,10 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
|
|||
device_update_common(device, dscene, scene, progress);
|
||||
|
||||
need_update = false;
|
||||
|
||||
VLOG(1) << "Shader manager updated "
|
||||
<< scene->shaders.size() << " shaders in "
|
||||
<< time_dt() - start_time << " seconds.";
|
||||
}
|
||||
|
||||
void SVMShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *scene)
|
||||
|
@ -317,17 +366,17 @@ uint SVMCompiler::encode_uchar4(uint x, uint y, uint z, uint w)
|
|||
|
||||
void SVMCompiler::add_node(int a, int b, int c, int d)
|
||||
{
|
||||
svm_nodes.push_back(make_int4(a, b, c, d));
|
||||
current_svm_nodes.push_back(make_int4(a, b, c, d));
|
||||
}
|
||||
|
||||
void SVMCompiler::add_node(ShaderNodeType type, int a, int b, int c)
|
||||
{
|
||||
svm_nodes.push_back(make_int4(type, a, b, c));
|
||||
current_svm_nodes.push_back(make_int4(type, a, b, c));
|
||||
}
|
||||
|
||||
void SVMCompiler::add_node(ShaderNodeType type, const float3& f)
|
||||
{
|
||||
svm_nodes.push_back(make_int4(type,
|
||||
current_svm_nodes.push_back(make_int4(type,
|
||||
__float_as_int(f.x),
|
||||
__float_as_int(f.y),
|
||||
__float_as_int(f.z)));
|
||||
|
@ -335,7 +384,7 @@ void SVMCompiler::add_node(ShaderNodeType type, const float3& f)
|
|||
|
||||
void SVMCompiler::add_node(const float4& f)
|
||||
{
|
||||
svm_nodes.push_back(make_int4(
|
||||
current_svm_nodes.push_back(make_int4(
|
||||
__float_as_int(f.x),
|
||||
__float_as_int(f.y),
|
||||
__float_as_int(f.z),
|
||||
|
@ -572,26 +621,38 @@ void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
|
|||
|
||||
/* generate instructions for input closure 1 */
|
||||
if(cl1in->link) {
|
||||
/* add instruction to skip closure and its dependencies if mix weight is zero */
|
||||
svm_nodes.push_back(make_int4(NODE_JUMP_IF_ONE, 0, stack_assign(facin), 0));
|
||||
int node_jump_skip_index = svm_nodes.size() - 1;
|
||||
/* Add instruction to skip closure and its dependencies if mix
|
||||
* weight is zero.
|
||||
*/
|
||||
current_svm_nodes.push_back(make_int4(NODE_JUMP_IF_ONE,
|
||||
0,
|
||||
stack_assign(facin),
|
||||
0));
|
||||
int node_jump_skip_index = current_svm_nodes.size() - 1;
|
||||
|
||||
generate_multi_closure(root_node, cl1in->link->parent, state);
|
||||
|
||||
/* fill in jump instruction location to be after closure */
|
||||
svm_nodes[node_jump_skip_index].y = svm_nodes.size() - node_jump_skip_index - 1;
|
||||
/* Fill in jump instruction location to be after closure. */
|
||||
current_svm_nodes[node_jump_skip_index].y =
|
||||
current_svm_nodes.size() - node_jump_skip_index - 1;
|
||||
}
|
||||
|
||||
/* generate instructions for input closure 2 */
|
||||
if(cl2in->link) {
|
||||
/* add instruction to skip closure and its dependencies if mix weight is zero */
|
||||
svm_nodes.push_back(make_int4(NODE_JUMP_IF_ZERO, 0, stack_assign(facin), 0));
|
||||
int node_jump_skip_index = svm_nodes.size() - 1;
|
||||
/* Add instruction to skip closure and its dependencies if mix
|
||||
* weight is zero.
|
||||
*/
|
||||
current_svm_nodes.push_back(make_int4(NODE_JUMP_IF_ZERO,
|
||||
0,
|
||||
stack_assign(facin),
|
||||
0));
|
||||
int node_jump_skip_index = current_svm_nodes.size() - 1;
|
||||
|
||||
generate_multi_closure(root_node, cl2in->link->parent, state);
|
||||
|
||||
/* fill in jump instruction location to be after closure */
|
||||
svm_nodes[node_jump_skip_index].y = svm_nodes.size() - node_jump_skip_index - 1;
|
||||
/* Fill in jump instruction location to be after closure. */
|
||||
current_svm_nodes[node_jump_skip_index].y =
|
||||
current_svm_nodes.size() - node_jump_skip_index - 1;
|
||||
}
|
||||
|
||||
/* unassign */
|
||||
|
@ -661,7 +722,7 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
|
|||
|
||||
/* clear all compiler state */
|
||||
memset(&active_stack, 0, sizeof(active_stack));
|
||||
svm_nodes.clear();
|
||||
current_svm_nodes.clear();
|
||||
|
||||
foreach(ShaderNode *node_iter, graph->nodes) {
|
||||
foreach(ShaderInput *input, node_iter->inputs)
|
||||
|
@ -671,8 +732,9 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
|
|||
}
|
||||
|
||||
/* for the bump shader we need add a node to store the shader state */
|
||||
bool need_bump_state = (type == SHADER_TYPE_BUMP) && (shader->displacement_method == DISPLACE_BOTH);
|
||||
int bump_state_offset = SVM_STACK_INVALID;
|
||||
if(type == SHADER_TYPE_BUMP) {
|
||||
if(need_bump_state) {
|
||||
bump_state_offset = stack_find_offset(SVM_BUMP_EVAL_STATE_SIZE);
|
||||
add_node(NODE_ENTER_BUMP_EVAL, bump_state_offset);
|
||||
}
|
||||
|
@ -714,13 +776,13 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
|
|||
}
|
||||
|
||||
/* add node to restore state after bump shader has finished */
|
||||
if(type == SHADER_TYPE_BUMP) {
|
||||
if(need_bump_state) {
|
||||
add_node(NODE_LEAVE_BUMP_EVAL, bump_state_offset);
|
||||
}
|
||||
|
||||
/* if compile failed, generate empty shader */
|
||||
if(compile_failed) {
|
||||
svm_nodes.clear();
|
||||
current_svm_nodes.clear();
|
||||
compile_failed = false;
|
||||
}
|
||||
|
||||
|
@ -732,13 +794,13 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
|
|||
|
||||
void SVMCompiler::compile(Scene *scene,
|
||||
Shader *shader,
|
||||
vector<int4>& global_svm_nodes,
|
||||
vector<int4>& svm_nodes,
|
||||
int index,
|
||||
Summary *summary)
|
||||
{
|
||||
/* copy graph for shader with bump mapping */
|
||||
ShaderNode *node = shader->graph->output();
|
||||
int start_num_svm_nodes = global_svm_nodes.size();
|
||||
int start_num_svm_nodes = svm_nodes.size();
|
||||
|
||||
const double time_start = time_dt();
|
||||
|
||||
|
@ -760,7 +822,8 @@ void SVMCompiler::compile(Scene *scene,
|
|||
shader->graph_bump->finalize(scene,
|
||||
true,
|
||||
false,
|
||||
shader->has_integrator_dependency);
|
||||
shader->has_integrator_dependency,
|
||||
shader->displacement_method == DISPLACE_BOTH);
|
||||
}
|
||||
|
||||
current_shader = shader;
|
||||
|
@ -781,8 +844,10 @@ void SVMCompiler::compile(Scene *scene,
|
|||
if(shader->displacement_method != DISPLACE_TRUE && shader->graph_bump) {
|
||||
scoped_timer timer((summary != NULL)? &summary->time_generate_bump: NULL);
|
||||
compile_type(shader, shader->graph_bump, SHADER_TYPE_BUMP);
|
||||
global_svm_nodes[index].y = global_svm_nodes.size();
|
||||
global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
|
||||
svm_nodes[index].y = svm_nodes.size();
|
||||
svm_nodes.insert(svm_nodes.end(),
|
||||
current_svm_nodes.begin(),
|
||||
current_svm_nodes.end());
|
||||
}
|
||||
|
||||
/* generate surface shader */
|
||||
|
@ -791,32 +856,38 @@ void SVMCompiler::compile(Scene *scene,
|
|||
compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
|
||||
/* only set jump offset if there's no bump shader, as the bump shader will fall thru to this one if it exists */
|
||||
if(shader->displacement_method == DISPLACE_TRUE || !shader->graph_bump) {
|
||||
global_svm_nodes[index].y = global_svm_nodes.size();
|
||||
svm_nodes[index].y = svm_nodes.size();
|
||||
}
|
||||
global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
|
||||
svm_nodes.insert(svm_nodes.end(),
|
||||
current_svm_nodes.begin(),
|
||||
current_svm_nodes.end());
|
||||
}
|
||||
|
||||
/* generate volume shader */
|
||||
{
|
||||
scoped_timer timer((summary != NULL)? &summary->time_generate_volume: NULL);
|
||||
compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
|
||||
global_svm_nodes[index].z = global_svm_nodes.size();
|
||||
global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
|
||||
svm_nodes[index].z = svm_nodes.size();
|
||||
svm_nodes.insert(svm_nodes.end(),
|
||||
current_svm_nodes.begin(),
|
||||
current_svm_nodes.end());
|
||||
}
|
||||
|
||||
/* generate displacement shader */
|
||||
{
|
||||
scoped_timer timer((summary != NULL)? &summary->time_generate_displacement: NULL);
|
||||
compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
|
||||
global_svm_nodes[index].w = global_svm_nodes.size();
|
||||
global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
|
||||
svm_nodes[index].w = svm_nodes.size();
|
||||
svm_nodes.insert(svm_nodes.end(),
|
||||
current_svm_nodes.begin(),
|
||||
current_svm_nodes.end());
|
||||
}
|
||||
|
||||
/* Fill in summary information. */
|
||||
if(summary != NULL) {
|
||||
summary->time_total = time_dt() - time_start;
|
||||
summary->peak_stack_usage = max_stack_use;
|
||||
summary->num_svm_nodes = global_svm_nodes.size() - start_num_svm_nodes;
|
||||
summary->num_svm_nodes = svm_nodes.size() - start_num_svm_nodes;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "util_set.h"
|
||||
#include "util_string.h"
|
||||
#include "util_thread.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -46,6 +47,15 @@ public:
|
|||
|
||||
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
|
||||
void device_free(Device *device, DeviceScene *dscene, Scene *scene);
|
||||
|
||||
protected:
|
||||
/* Lock used to synchronize threaded nodes compilation. */
|
||||
thread_spin_lock nodes_lock_;
|
||||
|
||||
void device_update_shader(Scene *scene,
|
||||
Shader *shader,
|
||||
Progress *progress,
|
||||
vector<int4> *global_svm_nodes);
|
||||
};
|
||||
|
||||
/* Graph Compiler */
|
||||
|
@ -200,7 +210,7 @@ protected:
|
|||
/* compile */
|
||||
void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
|
||||
|
||||
vector<int4> svm_nodes;
|
||||
vector<int4> current_svm_nodes;
|
||||
ShaderType current_type;
|
||||
Shader *current_shader;
|
||||
ShaderGraph *current_graph;
|
||||
|
|
|
@ -36,6 +36,9 @@ OIIO_NAMESPACE_USING
|
|||
#else
|
||||
# define DIR_SEP '/'
|
||||
# include <dirent.h>
|
||||
# include <pwd.h>
|
||||
# include <unistd.h>
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SHLWAPI_H
|
||||
|
@ -63,6 +66,7 @@ typedef struct stat path_stat_t;
|
|||
|
||||
static string cached_path = "";
|
||||
static string cached_user_path = "";
|
||||
static string cached_xdg_cache_path = "";
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -331,6 +335,23 @@ static char *path_specials(const string& sub)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
static string path_xdg_cache_get()
|
||||
{
|
||||
const char *home = getenv("XDG_CACHE_HOME");
|
||||
if(home) {
|
||||
return string(home);
|
||||
}
|
||||
else {
|
||||
home = getenv("HOME");
|
||||
if(home == NULL) {
|
||||
home = getpwuid(getuid())->pw_dir;
|
||||
}
|
||||
return path_join(string(home), ".cache");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void path_init(const string& path, const string& user_path)
|
||||
{
|
||||
cached_path = path;
|
||||
|
@ -364,6 +385,24 @@ string path_user_get(const string& sub)
|
|||
return path_join(cached_user_path, sub);
|
||||
}
|
||||
|
||||
string path_cache_get(const string& sub)
|
||||
{
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
if(cached_xdg_cache_path == "") {
|
||||
cached_xdg_cache_path = path_xdg_cache_get();
|
||||
}
|
||||
string result = path_join(cached_xdg_cache_path, "cycles");
|
||||
return path_join(result, sub);
|
||||
#else
|
||||
/* TODO(sergey): What that should be on Windows? */
|
||||
return path_user_get(path_join("cache", sub));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
string path_xdg_home_get(const string& sub = "");
|
||||
#endif
|
||||
|
||||
string path_filename(const string& path)
|
||||
{
|
||||
size_t index = find_last_slash(path);
|
||||
|
|
|
@ -35,6 +35,7 @@ CCL_NAMESPACE_BEGIN
|
|||
void path_init(const string& path = "", const string& user_path = "");
|
||||
string path_get(const string& sub = "");
|
||||
string path_user_get(const string& sub = "");
|
||||
string path_cache_get(const string& sub = "");
|
||||
|
||||
/* path string manipulation */
|
||||
string path_filename(const string& path);
|
||||
|
|
|
@ -25,6 +25,10 @@ CCL_NAMESPACE_BEGIN
|
|||
#ifndef __KERNEL_GPU__
|
||||
# if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
||||
/* C++11 has built-in static_assert() */
|
||||
# elif defined(static_assert)
|
||||
/* Some platforms might have static_assert() defined even tho their
|
||||
* C++ support wouldn't be declared to be C++11.
|
||||
*/
|
||||
# else /* C++11 or MSVC2015 */
|
||||
template <bool Test> class StaticAssertFailure;
|
||||
template <> class StaticAssertFailure<true> {};
|
||||
|
|
|
@ -838,7 +838,7 @@ GHOST_SystemX11::processEvent(XEvent *xe)
|
|||
case KeyRelease:
|
||||
{
|
||||
XKeyEvent *xke = &(xe->xkey);
|
||||
KeySym key_sym = XK_VoidSymbol;
|
||||
KeySym key_sym;
|
||||
KeySym key_sym_str;
|
||||
char ascii;
|
||||
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
|
||||
|
@ -891,16 +891,60 @@ GHOST_SystemX11::processEvent(XEvent *xe)
|
|||
if ((xke->keycode >= 10 && xke->keycode < 20) && ((xke->state & number_hack_forbidden_kmods_mask) == 0)) {
|
||||
key_sym = XLookupKeysym(xke, ShiftMask);
|
||||
if (!((key_sym >= XK_0) && (key_sym <= XK_9))) {
|
||||
key_sym = XK_VoidSymbol;
|
||||
key_sym = XLookupKeysym(xke, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
key_sym = XLookupKeysym(xke, 0);
|
||||
}
|
||||
|
||||
if (!XLookupString(xke, &ascii, 1, &key_sym_str, NULL)) {
|
||||
ascii = '\0';
|
||||
}
|
||||
|
||||
if ((gkey = convertXKey(key_sym)) == GHOST_kKeyUnknown) {
|
||||
gkey = convertXKey(key_sym_str);
|
||||
/* Only allow a limited set of keys from XLookupKeysym, all others we take from XLookupString,
|
||||
* unless it gives unknown key... */
|
||||
gkey = convertXKey(key_sym);
|
||||
switch (gkey) {
|
||||
case GHOST_kKeyRightAlt:
|
||||
case GHOST_kKeyLeftAlt:
|
||||
case GHOST_kKeyRightShift:
|
||||
case GHOST_kKeyLeftShift:
|
||||
case GHOST_kKeyRightControl:
|
||||
case GHOST_kKeyLeftControl:
|
||||
case GHOST_kKeyOS:
|
||||
case GHOST_kKey0:
|
||||
case GHOST_kKey1:
|
||||
case GHOST_kKey2:
|
||||
case GHOST_kKey3:
|
||||
case GHOST_kKey4:
|
||||
case GHOST_kKey5:
|
||||
case GHOST_kKey6:
|
||||
case GHOST_kKey7:
|
||||
case GHOST_kKey8:
|
||||
case GHOST_kKey9:
|
||||
case GHOST_kKeyNumpad0:
|
||||
case GHOST_kKeyNumpad1:
|
||||
case GHOST_kKeyNumpad2:
|
||||
case GHOST_kKeyNumpad3:
|
||||
case GHOST_kKeyNumpad4:
|
||||
case GHOST_kKeyNumpad5:
|
||||
case GHOST_kKeyNumpad6:
|
||||
case GHOST_kKeyNumpad7:
|
||||
case GHOST_kKeyNumpad8:
|
||||
case GHOST_kKeyNumpad9:
|
||||
case GHOST_kKeyNumpadPeriod:
|
||||
case GHOST_kKeyNumpadEnter:
|
||||
case GHOST_kKeyNumpadPlus:
|
||||
case GHOST_kKeyNumpadMinus:
|
||||
case GHOST_kKeyNumpadAsterisk:
|
||||
case GHOST_kKeyNumpadSlash:
|
||||
break;
|
||||
default:
|
||||
GHOST_TKey gkey_str = convertXKey(key_sym_str);
|
||||
if (gkey_str != GHOST_kKeyUnknown) {
|
||||
gkey = gkey_str;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* In keyboards like latin ones,
|
||||
|
@ -1582,6 +1626,7 @@ convertXKey(KeySym key)
|
|||
switch (key) {
|
||||
GXMAP(type, XK_BackSpace, GHOST_kKeyBackSpace);
|
||||
GXMAP(type, XK_Tab, GHOST_kKeyTab);
|
||||
GXMAP(type, XK_ISO_Left_Tab, GHOST_kKeyTab);
|
||||
GXMAP(type, XK_Return, GHOST_kKeyEnter);
|
||||
GXMAP(type, XK_Escape, GHOST_kKeyEsc);
|
||||
GXMAP(type, XK_space, GHOST_kKeySpace);
|
||||
|
|
|
@ -64,7 +64,9 @@ OPENSUBDIV_DEFINE_COMPONENT(OPENSUBDIV_HAS_OPENMP)
|
|||
OPENSUBDIV_DEFINE_COMPONENT(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK)
|
||||
OPENSUBDIV_DEFINE_COMPONENT(OPENSUBDIV_HAS_GLSL_COMPUTE)
|
||||
|
||||
data_to_c_simple(gpu_shader_opensubd_display.glsl SRC)
|
||||
data_to_c_simple(gpu_shader_opensubdiv_vertex.glsl SRC)
|
||||
data_to_c_simple(gpu_shader_opensubdiv_geometry.glsl SRC)
|
||||
data_to_c_simple(gpu_shader_opensubdiv_fragment.glsl SRC)
|
||||
|
||||
add_definitions(-DGLEW_STATIC)
|
||||
|
||||
|
|
|
@ -29,170 +29,6 @@ struct VertexData {
|
|||
vec2 uv;
|
||||
};
|
||||
|
||||
#ifdef VERTEX_SHADER // ---------------------
|
||||
|
||||
in vec3 normal;
|
||||
in vec4 position;
|
||||
|
||||
uniform mat4 modelViewMatrix;
|
||||
uniform mat3 normalMatrix;
|
||||
|
||||
out block {
|
||||
VertexData v;
|
||||
} outpt;
|
||||
|
||||
void main()
|
||||
{
|
||||
outpt.v.position = modelViewMatrix * position;
|
||||
outpt.v.normal = normalize(normalMatrix * normal);
|
||||
|
||||
#if __VERSION__ < 140
|
||||
/* Some compilers expects gl_Position to be written.
|
||||
* It's not needed once we explicitly switch to GLSL 1.40 or above.
|
||||
*/
|
||||
gl_Position = outpt.v.position;
|
||||
#endif
|
||||
}
|
||||
|
||||
#elif defined GEOMETRY_SHADER // ---------------------
|
||||
|
||||
#if __VERSION__ >= 150
|
||||
layout(lines_adjacency) in;
|
||||
#ifdef WIREFRAME
|
||||
layout(line_strip, max_vertices = 8) out;
|
||||
#else
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
#endif
|
||||
#else
|
||||
#extension GL_EXT_geometry_shader4: require
|
||||
/* application provides input/output layout info */
|
||||
#endif
|
||||
|
||||
#if __VERSION__ < 140
|
||||
#extension GL_ARB_uniform_buffer_object: require
|
||||
#extension GL_ARB_texture_buffer_object: enable
|
||||
#extension GL_EXT_texture_buffer_object: enable
|
||||
#endif
|
||||
|
||||
uniform mat4 modelViewMatrix;
|
||||
uniform mat4 projectionMatrix;
|
||||
uniform int PrimitiveIdBase;
|
||||
uniform int osd_fvar_count;
|
||||
uniform int osd_active_uv_offset;
|
||||
|
||||
in block {
|
||||
VertexData v;
|
||||
} inpt[];
|
||||
|
||||
#define INTERP_FACE_VARYING_2(result, fvarOffset, tessCoord) \
|
||||
{ \
|
||||
vec2 v[4]; \
|
||||
int primOffset = (gl_PrimitiveID + PrimitiveIdBase) * 4; \
|
||||
for (int i = 0; i < 4; ++i) { \
|
||||
int index = (primOffset + i) * osd_fvar_count + fvarOffset; \
|
||||
v[i] = vec2(texelFetch(FVarDataBuffer, index).s, \
|
||||
texelFetch(FVarDataBuffer, index + 1).s); \
|
||||
} \
|
||||
result = mix(mix(v[0], v[1], tessCoord.s), \
|
||||
mix(v[3], v[2], tessCoord.s), \
|
||||
tessCoord.t); \
|
||||
}
|
||||
|
||||
uniform samplerBuffer FVarDataBuffer;
|
||||
uniform isamplerBuffer FVarDataOffsetBuffer;
|
||||
|
||||
out block {
|
||||
VertexData v;
|
||||
} outpt;
|
||||
|
||||
#ifdef FLAT_SHADING
|
||||
void emit(int index, vec3 normal)
|
||||
{
|
||||
outpt.v.position = inpt[index].v.position;
|
||||
outpt.v.normal = normal;
|
||||
|
||||
/* TODO(sergey): Only uniform subdivisions atm. */
|
||||
vec2 quadst[4] = vec2[](vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1));
|
||||
vec2 st = quadst[index];
|
||||
|
||||
INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
|
||||
|
||||
gl_Position = projectionMatrix * inpt[index].v.position;
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
# ifdef WIREFRAME
|
||||
void emit_edge(int v0, int v1, vec3 normal)
|
||||
{
|
||||
emit(v0, normal);
|
||||
emit(v1, normal);
|
||||
}
|
||||
# endif
|
||||
|
||||
#else
|
||||
void emit(int index)
|
||||
{
|
||||
outpt.v.position = inpt[index].v.position;
|
||||
outpt.v.normal = inpt[index].v.normal;
|
||||
|
||||
/* TODO(sergey): Only uniform subdivisions atm. */
|
||||
vec2 quadst[4] = vec2[](vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1));
|
||||
vec2 st = quadst[index];
|
||||
|
||||
INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
|
||||
|
||||
gl_Position = projectionMatrix * inpt[index].v.position;
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
# ifdef WIREFRAME
|
||||
void emit_edge(int v0, int v1)
|
||||
{
|
||||
emit(v0);
|
||||
emit(v1);
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_PrimitiveID = gl_PrimitiveIDIn;
|
||||
|
||||
#ifdef FLAT_SHADING
|
||||
vec3 A = (inpt[0].v.position - inpt[1].v.position).xyz;
|
||||
vec3 B = (inpt[3].v.position - inpt[1].v.position).xyz;
|
||||
vec3 flat_normal = normalize(cross(B, A));
|
||||
# ifndef WIREFRAME
|
||||
emit(0, flat_normal);
|
||||
emit(1, flat_normal);
|
||||
emit(3, flat_normal);
|
||||
emit(2, flat_normal);
|
||||
# else
|
||||
emit_edge(0, 1, flat_normal);
|
||||
emit_edge(1, 2, flat_normal);
|
||||
emit_edge(2, 3, flat_normal);
|
||||
emit_edge(3, 0, flat_normal);
|
||||
# endif
|
||||
#else
|
||||
# ifndef WIREFRAME
|
||||
emit(0);
|
||||
emit(1);
|
||||
emit(3);
|
||||
emit(2);
|
||||
# else
|
||||
emit_edge(0, 1);
|
||||
emit_edge(1, 2);
|
||||
emit_edge(2, 3);
|
||||
emit_edge(3, 0);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
#elif defined FRAGMENT_SHADER // ---------------------
|
||||
|
||||
#define MAX_LIGHTS 8
|
||||
#define NUM_SOLID_LIGHTS 3
|
||||
|
||||
|
@ -334,5 +170,3 @@ void main()
|
|||
gl_FragColor = vec4(L, diffuse.a);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // ---------------------
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2014 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Sergey Sharybin
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
struct VertexData {
|
||||
vec4 position;
|
||||
vec3 normal;
|
||||
vec2 uv;
|
||||
};
|
||||
|
||||
#if __VERSION__ >= 150
|
||||
layout(lines_adjacency) in;
|
||||
#ifdef WIREFRAME
|
||||
layout(line_strip, max_vertices = 8) out;
|
||||
#else
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
#endif
|
||||
#else
|
||||
#extension GL_EXT_geometry_shader4: require
|
||||
/* application provides input/output layout info */
|
||||
#endif
|
||||
|
||||
#if __VERSION__ < 140
|
||||
#extension GL_ARB_uniform_buffer_object: require
|
||||
#extension GL_ARB_texture_buffer_object: enable
|
||||
#extension GL_EXT_texture_buffer_object: enable
|
||||
#endif
|
||||
|
||||
uniform mat4 modelViewMatrix;
|
||||
uniform mat4 projectionMatrix;
|
||||
uniform int PrimitiveIdBase;
|
||||
uniform int osd_fvar_count;
|
||||
uniform int osd_active_uv_offset;
|
||||
|
||||
in block {
|
||||
VertexData v;
|
||||
} inpt[];
|
||||
|
||||
#define INTERP_FACE_VARYING_2(result, fvarOffset, tessCoord) \
|
||||
{ \
|
||||
vec2 v[4]; \
|
||||
int primOffset = (gl_PrimitiveID + PrimitiveIdBase) * 4; \
|
||||
for (int i = 0; i < 4; ++i) { \
|
||||
int index = (primOffset + i) * osd_fvar_count + fvarOffset; \
|
||||
v[i] = vec2(texelFetch(FVarDataBuffer, index).s, \
|
||||
texelFetch(FVarDataBuffer, index + 1).s); \
|
||||
} \
|
||||
result = mix(mix(v[0], v[1], tessCoord.s), \
|
||||
mix(v[3], v[2], tessCoord.s), \
|
||||
tessCoord.t); \
|
||||
}
|
||||
|
||||
uniform samplerBuffer FVarDataBuffer;
|
||||
uniform isamplerBuffer FVarDataOffsetBuffer;
|
||||
|
||||
out block {
|
||||
VertexData v;
|
||||
} outpt;
|
||||
|
||||
#ifdef FLAT_SHADING
|
||||
void emit(int index, vec3 normal)
|
||||
{
|
||||
outpt.v.position = inpt[index].v.position;
|
||||
outpt.v.normal = normal;
|
||||
|
||||
/* TODO(sergey): Only uniform subdivisions atm. */
|
||||
vec2 quadst[4] = vec2[](vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1));
|
||||
vec2 st = quadst[index];
|
||||
|
||||
INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
|
||||
|
||||
gl_Position = projectionMatrix * inpt[index].v.position;
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
# ifdef WIREFRAME
|
||||
void emit_edge(int v0, int v1, vec3 normal)
|
||||
{
|
||||
emit(v0, normal);
|
||||
emit(v1, normal);
|
||||
}
|
||||
# endif
|
||||
|
||||
#else
|
||||
void emit(int index)
|
||||
{
|
||||
outpt.v.position = inpt[index].v.position;
|
||||
outpt.v.normal = inpt[index].v.normal;
|
||||
|
||||
/* TODO(sergey): Only uniform subdivisions atm. */
|
||||
vec2 quadst[4] = vec2[](vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1));
|
||||
vec2 st = quadst[index];
|
||||
|
||||
INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
|
||||
|
||||
gl_Position = projectionMatrix * inpt[index].v.position;
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
# ifdef WIREFRAME
|
||||
void emit_edge(int v0, int v1)
|
||||
{
|
||||
emit(v0);
|
||||
emit(v1);
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_PrimitiveID = gl_PrimitiveIDIn;
|
||||
|
||||
#ifdef FLAT_SHADING
|
||||
vec3 A = (inpt[0].v.position - inpt[1].v.position).xyz;
|
||||
vec3 B = (inpt[3].v.position - inpt[1].v.position).xyz;
|
||||
vec3 flat_normal = normalize(cross(B, A));
|
||||
# ifndef WIREFRAME
|
||||
emit(0, flat_normal);
|
||||
emit(1, flat_normal);
|
||||
emit(3, flat_normal);
|
||||
emit(2, flat_normal);
|
||||
# else
|
||||
emit_edge(0, 1, flat_normal);
|
||||
emit_edge(1, 2, flat_normal);
|
||||
emit_edge(2, 3, flat_normal);
|
||||
emit_edge(3, 0, flat_normal);
|
||||
# endif
|
||||
#else
|
||||
# ifndef WIREFRAME
|
||||
emit(0);
|
||||
emit(1);
|
||||
emit(3);
|
||||
emit(2);
|
||||
# else
|
||||
emit_edge(0, 1);
|
||||
emit_edge(1, 2);
|
||||
emit_edge(2, 3);
|
||||
emit_edge(3, 0);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
EndPrimitive();
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2014 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Sergey Sharybin
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
struct VertexData {
|
||||
vec4 position;
|
||||
vec3 normal;
|
||||
vec2 uv;
|
||||
};
|
||||
|
||||
in vec3 normal;
|
||||
in vec4 position;
|
||||
|
||||
uniform mat4 modelViewMatrix;
|
||||
uniform mat3 normalMatrix;
|
||||
|
||||
out block {
|
||||
VertexData v;
|
||||
} outpt;
|
||||
|
||||
void main()
|
||||
{
|
||||
outpt.v.position = modelViewMatrix * position;
|
||||
outpt.v.normal = normalize(normalMatrix * normal);
|
||||
|
||||
#if __VERSION__ < 140
|
||||
/* Some compilers expects gl_Position to be written.
|
||||
* It's not needed once we explicitly switch to GLSL 1.40 or above.
|
||||
*/
|
||||
gl_Position = outpt.v.position;
|
||||
#endif
|
||||
}
|
|
@ -165,7 +165,7 @@ static void interpolate_fvar_data(OpenSubdiv::Far::TopologyRefiner& refiner,
|
|||
const int max_level = refiner.GetMaxLevel();
|
||||
size_t fvar_data_offset = 0, values_offset = 0;
|
||||
for (int channel = 0; channel < refiner.GetNumFVarChannels(); ++channel) {
|
||||
const int num_values = refiner.GetLevel(0).GetNumFVarValues(0) * 2,
|
||||
const int num_values = refiner.GetLevel(0).GetNumFVarValues(channel) * 2,
|
||||
num_values_max = refiner.GetLevel(max_level).GetNumFVarValues(channel),
|
||||
num_values_total = refiner.GetNumFVarValuesTotal(channel);
|
||||
if (num_values_total <= 0) {
|
||||
|
|
|
@ -49,7 +49,9 @@
|
|||
|
||||
using OpenSubdiv::Osd::GLMeshInterface;
|
||||
|
||||
extern "C" char datatoc_gpu_shader_opensubd_display_glsl[];
|
||||
extern "C" char datatoc_gpu_shader_opensubdiv_vertex_glsl[];
|
||||
extern "C" char datatoc_gpu_shader_opensubdiv_geometry_glsl[];
|
||||
extern "C" char datatoc_gpu_shader_opensubdiv_fragment_glsl[];
|
||||
|
||||
/* TODO(sergey): This is bit of bad level calls :S */
|
||||
extern "C" {
|
||||
|
@ -206,25 +208,23 @@ struct OpenSubdiv_GLMeshFVarData
|
|||
namespace {
|
||||
|
||||
GLuint compileShader(GLenum shaderType,
|
||||
const char *section,
|
||||
const char *version,
|
||||
const char *define)
|
||||
const char *define,
|
||||
const char *source)
|
||||
{
|
||||
char sdefine[64];
|
||||
sprintf(sdefine, "#define %s\n", section);
|
||||
|
||||
const char *sources[] = {
|
||||
version,
|
||||
define,
|
||||
sdefine,
|
||||
#ifdef SUPPORT_COLOR_MATERIAL
|
||||
"#define SUPPORT_COLOR_MATERIAL\n",
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
datatoc_gpu_shader_opensubd_display_glsl
|
||||
source,
|
||||
};
|
||||
|
||||
GLuint shader = glCreateShader(shaderType);
|
||||
glShaderSource(shader, 5, sources, NULL);
|
||||
glShaderSource(shader, 4, sources, NULL);
|
||||
glCompileShader(shader);
|
||||
|
||||
GLint status;
|
||||
|
@ -232,10 +232,10 @@ GLuint compileShader(GLenum shaderType,
|
|||
if (status == GL_FALSE) {
|
||||
GLchar emsg[1024];
|
||||
glGetShaderInfoLog(shader, sizeof(emsg), 0, emsg);
|
||||
fprintf(stderr, "Error compiling GLSL %s: %s\n", section, emsg);
|
||||
fprintf(stderr, "Error compiling GLSL: %s\n", emsg);
|
||||
fprintf(stderr, "Version: %s\n", version);
|
||||
fprintf(stderr, "Defines: %s\n", define);
|
||||
fprintf(stderr, "Source: %s\n", datatoc_gpu_shader_opensubd_display_glsl);
|
||||
fprintf(stderr, "Source: %s\n", source);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -245,23 +245,23 @@ GLuint compileShader(GLenum shaderType,
|
|||
GLuint linkProgram(const char *version, const char *define)
|
||||
{
|
||||
GLuint vertexShader = compileShader(GL_VERTEX_SHADER,
|
||||
"VERTEX_SHADER",
|
||||
version,
|
||||
define);
|
||||
define,
|
||||
datatoc_gpu_shader_opensubdiv_vertex_glsl);
|
||||
if (vertexShader == 0) {
|
||||
return 0;
|
||||
}
|
||||
GLuint geometryShader = compileShader(GL_GEOMETRY_SHADER,
|
||||
"GEOMETRY_SHADER",
|
||||
version,
|
||||
define);
|
||||
define,
|
||||
datatoc_gpu_shader_opensubdiv_geometry_glsl);
|
||||
if (geometryShader == 0) {
|
||||
return 0;
|
||||
}
|
||||
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER,
|
||||
"FRAGMENT_SHADER",
|
||||
version,
|
||||
define);
|
||||
define,
|
||||
datatoc_gpu_shader_opensubdiv_fragment_glsl );
|
||||
if (fragmentShader == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
|
154
make.bat
154
make.bat
|
@ -8,42 +8,6 @@ set BUILD_DIR=%BLENDER_DIR%..\build_windows
|
|||
set BUILD_TYPE=Release
|
||||
set BUILD_CMAKE_ARGS=
|
||||
|
||||
REM Detect MSVC Installation
|
||||
if DEFINED VisualStudioVersion goto msvc_detect_finally
|
||||
set VALUE_NAME=ProductDir
|
||||
REM Check 64 bits
|
||||
set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\12.0\Setup\VC"
|
||||
for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO set MSVC_VC_DIR=%%C
|
||||
if DEFINED MSVC_VC_DIR goto msvc_detect_finally
|
||||
REM Check 32 bits
|
||||
set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\12.0\Setup\VC"
|
||||
for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO set MSVC_VC_DIR=%%C
|
||||
if DEFINED MSVC_VC_DIR goto msvc_detect_finally
|
||||
:msvc_detect_finally
|
||||
if DEFINED MSVC_VC_DIR call "%MSVC_VC_DIR%\vcvarsall.bat"
|
||||
|
||||
|
||||
REM Sanity Checks
|
||||
where /Q msbuild
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo Error: "MSBuild" command not in the PATH.
|
||||
echo You must have MSVC installed and run this from the "Developer Command Prompt"
|
||||
echo ^(available from Visual Studio's Start menu entry^), aborting!
|
||||
goto EOF
|
||||
)
|
||||
where /Q cmake
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo Error: "CMake" command not in the PATH.
|
||||
echo You must have CMake installed and added to your PATH, aborting!
|
||||
goto EOF
|
||||
)
|
||||
if NOT EXIST %BLENDER_DIR%..\lib\nul (
|
||||
echo Error: Path to libraries not found "%BLENDER_DIR%..\lib\"
|
||||
echo This is needed for building, aborting!
|
||||
goto EOF
|
||||
)
|
||||
|
||||
|
||||
:argv_loop
|
||||
if NOT "%1" == "" (
|
||||
|
||||
|
@ -51,6 +15,7 @@ if NOT "%1" == "" (
|
|||
if "%1" == "help" (
|
||||
echo.
|
||||
echo Convenience targets
|
||||
echo - release
|
||||
echo - debug
|
||||
echo - full
|
||||
echo - lite
|
||||
|
@ -61,6 +26,16 @@ if NOT "%1" == "" (
|
|||
echo Utilities ^(not associated with building^)
|
||||
echo - clean
|
||||
echo - update
|
||||
echo - nobuild ^(only generate project files^)
|
||||
echo - showhash ^(Show git hashes of source tree^)
|
||||
echo.
|
||||
echo Configuration options
|
||||
echo - packagename [newname] ^(override default cpack package name^)
|
||||
echo - x86 ^(override host autodetect and build 32 bit code^)
|
||||
echo - x64 ^(override host autodetect and build 64 bit code^)
|
||||
echo - 2013 ^(build with visual studio 2013^)
|
||||
echo - 2015 ^(build with visual studio 2015^) [EXPERIMENTAL]
|
||||
echo.
|
||||
goto EOF
|
||||
)
|
||||
|
||||
|
@ -90,7 +65,44 @@ if NOT "%1" == "" (
|
|||
set BUILD_DIR=%BUILD_DIR%_bpy
|
||||
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
|
||||
-C"%BLENDER_DIR%\build_files\cmake\config\bpy_module.cmake"
|
||||
|
||||
) else if "%1" == "release" (
|
||||
if "%CUDA_PATH_V7_5%"=="" (
|
||||
echo Cuda 7.5 Not found, aborting!
|
||||
goto EOF
|
||||
)
|
||||
if "%CUDA_PATH_V8_0%"=="" (
|
||||
echo Cuda 8.0 Not found, aborting!
|
||||
goto EOF
|
||||
)
|
||||
set BUILD_DIR=%BUILD_DIR%_Release
|
||||
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
|
||||
-C"%BLENDER_DIR%\build_files\cmake\config\blender_release.cmake" -DCUDA_NVCC_EXECUTABLE:FILEPATH=%CUDA_PATH_V7_5%/bin/nvcc.exe -DCUDA_NVCC8_EXECUTABLE:FILEPATH=%CUDA_PATH_V8_0%/bin/nvcc.exe
|
||||
) else if "%1" == "x86" (
|
||||
set BUILD_ARCH=x86
|
||||
set BUILD_DIR=%BUILD_DIR%_x86
|
||||
) else if "%1" == "x64" (
|
||||
set BUILD_ARCH=x64
|
||||
set BUILD_DIR=%BUILD_DIR%_x64
|
||||
) else if "%1" == "2015" (
|
||||
set BUILD_VS_VER=14
|
||||
set BUILD_VS_YEAR=2015
|
||||
) else if "%1" == "2013" (
|
||||
set BUILD_VS_VER=12
|
||||
set BUILD_VS_YEAR=2013
|
||||
) else if "%1" == "packagename" (
|
||||
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DCPACK_OVERRIDE_PACKAGENAME="%2"
|
||||
shift /1
|
||||
) else if "%1" == "nobuild" (
|
||||
set NOBUILD=1
|
||||
) else if "%1" == "showhash" (
|
||||
for /f "delims=" %%i in ('git rev-parse HEAD') do echo Branch_hash=%%i
|
||||
cd release/datafiles/locale
|
||||
for /f "delims=" %%i in ('git rev-parse HEAD') do echo Locale_hash=%%i
|
||||
cd %~dp0
|
||||
cd release/scripts/addons
|
||||
for /f "delims=" %%i in ('git rev-parse HEAD') do echo Addons_Hash=%%i
|
||||
cd %~dp0
|
||||
goto EOF
|
||||
REM Non-Build Commands
|
||||
) else if "%1" == "update" (
|
||||
svn up ../lib/*
|
||||
|
@ -115,22 +127,71 @@ if NOT "%1" == "" (
|
|||
shift /1
|
||||
goto argv_loop
|
||||
)
|
||||
if "%BUILD_ARCH%"=="" (
|
||||
if "%PROCESSOR_ARCHITECTURE%" == "AMD64" (
|
||||
set WINDOWS_ARCH= Win64
|
||||
) else if "%PROCESSOR_ARCHITEW6432%" == "AMD64" (
|
||||
set WINDOWS_ARCH= Win64
|
||||
) else (
|
||||
set WINDOWS_ARCH=
|
||||
)
|
||||
) else if "%BUILD_ARCH%"=="x64" (
|
||||
set WINDOWS_ARCH= Win64
|
||||
) else if "%BUILD_ARCH%"=="x86" (
|
||||
set WINDOWS_ARCH=
|
||||
)
|
||||
|
||||
if "%PROCESSOR_ARCHITECTURE%" == "AMD64" (
|
||||
set WINDOWS_ARCH=Win64
|
||||
) else if "%PROCESSOR_ARCHITEW6432%" == "AMD64" (
|
||||
set WINDOWS_ARCH=Win64
|
||||
) else (
|
||||
set WINDOWS_ARCH=
|
||||
if "%BUILD_VS_VER%"=="" (
|
||||
set BUILD_VS_VER=12
|
||||
set BUILD_VS_YEAR=2013
|
||||
)
|
||||
|
||||
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Visual Studio 12 2013 %WINDOWS_ARCH%"
|
||||
set BUILD_DIR=%BUILD_DIR%_vc%BUILD_VS_VER%
|
||||
|
||||
REM Detect MSVC Installation
|
||||
if DEFINED VisualStudioVersion goto msvc_detect_finally
|
||||
set VALUE_NAME=ProductDir
|
||||
REM Check 64 bits
|
||||
set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%BUILD_VS_VER%.0\Setup\VC"
|
||||
for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO set MSVC_VC_DIR=%%C
|
||||
if DEFINED MSVC_VC_DIR goto msvc_detect_finally
|
||||
REM Check 32 bits
|
||||
set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\%BUILD_VS_VER%.0\Setup\VC"
|
||||
for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO set MSVC_VC_DIR=%%C
|
||||
if DEFINED MSVC_VC_DIR goto msvc_detect_finally
|
||||
:msvc_detect_finally
|
||||
if DEFINED MSVC_VC_DIR call "%MSVC_VC_DIR%\vcvarsall.bat"
|
||||
|
||||
REM Sanity Checks
|
||||
where /Q msbuild
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo Error: "MSBuild" command not in the PATH.
|
||||
echo You must have MSVC installed and run this from the "Developer Command Prompt"
|
||||
echo ^(available from Visual Studio's Start menu entry^), aborting!
|
||||
goto EOF
|
||||
)
|
||||
where /Q cmake
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo Error: "CMake" command not in the PATH.
|
||||
echo You must have CMake installed and added to your PATH, aborting!
|
||||
goto EOF
|
||||
)
|
||||
if NOT EXIST %BLENDER_DIR%..\lib\nul (
|
||||
echo Error: Path to libraries not found "%BLENDER_DIR%..\lib\"
|
||||
echo This is needed for building, aborting!
|
||||
goto EOF
|
||||
)
|
||||
|
||||
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Visual Studio %BUILD_VS_VER% %BUILD_VS_YEAR%%WINDOWS_ARCH%"
|
||||
if NOT EXIST %BUILD_DIR%\nul (
|
||||
mkdir %BUILD_DIR%
|
||||
)
|
||||
|
||||
REM Only configure on first run
|
||||
if NOT EXIST %BUILD_DIR%\Blender.sln (
|
||||
REM Only configure on first run or when called with nobuild
|
||||
if NOT EXIST %BUILD_DIR%\Blender.sln set MUST_CONFIGURE=1
|
||||
if "%NOBUILD%"=="1" set MUST_CONFIGURE=1
|
||||
|
||||
if "%MUST_CONFIGURE%"=="1" (
|
||||
cmake ^
|
||||
%BUILD_CMAKE_ARGS% ^
|
||||
-H%BLENDER_DIR% ^
|
||||
|
@ -142,6 +203,7 @@ if NOT EXIST %BUILD_DIR%\Blender.sln (
|
|||
goto EOF
|
||||
)
|
||||
)
|
||||
if "%NOBUILD%"=="1" goto EOF
|
||||
|
||||
msbuild ^
|
||||
%BUILD_DIR%\Blender.sln ^
|
||||
|
|
|
@ -247,6 +247,7 @@ colorspaces:
|
|||
allocation: uniform
|
||||
allocationvars: [-0.125, 4.875]
|
||||
to_reference: !<FileTransform> {src: srgb.spi1d, interpolation: linear}
|
||||
from_reference: !<FileTransform> {src: srgb_inv.spi1d, interpolation: linear}
|
||||
|
||||
- !<ColorSpace>
|
||||
name: VD16
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,18 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Use this script to generate splash.png from splash_2x.png.
|
||||
# Supposed to give best quality image.
|
||||
#
|
||||
# Based on ImageMagic documentation, which is interesting
|
||||
# to read anyway:
|
||||
#
|
||||
# http://www.imagemagick.org/Usage/filter
|
||||
# http://www.imagemagick.org/Usage/filter/nicolas/
|
||||
|
||||
convert \
|
||||
splash_2x.png \
|
||||
-colorspace RGB \
|
||||
-filter Cosine \
|
||||
-resize 50% \
|
||||
-colorspace sRGB \
|
||||
splash.png
|
|
@ -49,7 +49,7 @@ def bake_action(frame_start,
|
|||
:type frame_end: int
|
||||
:arg frame_step: Frame step.
|
||||
:type frame_step: int
|
||||
:arg only_selected: Only bake selected data.
|
||||
:arg only_selected: Only bake selected bones.
|
||||
:type only_selected: bool
|
||||
:arg do_pose: Bake pose channels.
|
||||
:type do_pose: bool
|
||||
|
|
|
@ -222,7 +222,7 @@ class BakeAction(Operator):
|
|||
)
|
||||
only_selected = BoolProperty(
|
||||
name="Only Selected",
|
||||
description="Only key selected object/bones",
|
||||
description="Only key selected bones (Pose baking only)",
|
||||
default=True,
|
||||
)
|
||||
visual_keying = BoolProperty(
|
||||
|
|
|
@ -201,6 +201,10 @@ class DATA_PT_pose_library(ArmatureButtonsPanel, Panel):
|
|||
|
||||
col.operator("poselib.action_sanitize", icon='HELP', text="") # XXX: put in menu?
|
||||
|
||||
if pose_marker_active is not None:
|
||||
col.operator("poselib.pose_move", icon='TRIA_UP', text="").direction = 'UP'
|
||||
col.operator("poselib.pose_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
|
||||
|
||||
|
||||
# TODO: this panel will soon be deprecated too
|
||||
class DATA_PT_ghost(ArmatureButtonsPanel, Panel):
|
||||
|
|
|
@ -216,8 +216,18 @@ class GreasePencilStrokeEditPanel:
|
|||
col.operator_menu_enum("gpencil.stroke_arrange", text="Arrange Strokes...", property="direction")
|
||||
col.operator("gpencil.stroke_change_color", text="Move to Color")
|
||||
|
||||
if is_3d_view:
|
||||
layout.separator()
|
||||
col = layout.column(align=True)
|
||||
col.operator("gpencil.interpolate", text="Interpolate")
|
||||
col.operator("gpencil.interpolate_sequence", text="Sequence")
|
||||
settings = context.tool_settings.gpencil_sculpt
|
||||
col.prop(settings, "interpolate_all_layers")
|
||||
col.prop(settings, "interpolate_selected_only")
|
||||
|
||||
layout.separator()
|
||||
col = layout.column(align=True)
|
||||
col.operator("gpencil.stroke_subdivide", text="Subdivide")
|
||||
col.operator("gpencil.stroke_join", text="Join").type = 'JOIN'
|
||||
col.operator("gpencil.stroke_join", text="Join & Copy").type = 'JOINCOPY'
|
||||
col.operator("gpencil.stroke_flip", text="Flip Direction")
|
||||
|
@ -641,6 +651,28 @@ class GPENCIL_MT_snap(Menu):
|
|||
layout.operator("view3d.snap_cursor_to_grid", text="Cursor to Grid")
|
||||
|
||||
|
||||
class GPENCIL_MT_gpencil_edit_specials(Menu):
|
||||
bl_label = "GPencil Specials"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
is_3d_view = context.space_data.type == 'VIEW_3D'
|
||||
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
|
||||
layout.operator("gpencil.stroke_subdivide", text="Subdivide")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.stroke_join", text="Join").type = 'JOIN'
|
||||
layout.operator("gpencil.stroke_join", text="Join & Copy").type = 'JOINCOPY'
|
||||
layout.operator("gpencil.stroke_flip", text="Flip Direction")
|
||||
|
||||
if is_3d_view:
|
||||
layout.separator()
|
||||
layout.operator("gpencil.reproject")
|
||||
|
||||
|
||||
###############################
|
||||
|
||||
|
||||
|
@ -763,6 +795,7 @@ class GPENCIL_MT_palettecolor_specials(Menu):
|
|||
layout.separator()
|
||||
|
||||
layout.operator("gpencil.palettecolor_select", icon='COLOR', text="Select Strokes")
|
||||
layout.operator("gpencil.stroke_change_color", icon='MAN_TRANS', text="Move to Color")
|
||||
|
||||
|
||||
class GreasePencilDataPanel:
|
||||
|
|
|
@ -408,6 +408,20 @@ class VIEW3D_MT_uv_map(Menu):
|
|||
layout.operator("uv.reset")
|
||||
|
||||
|
||||
class VIEW3D_MT_edit_proportional(Menu):
|
||||
bl_label = "Proportional Editing"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.props_enum(context.tool_settings, "proportional_edit")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.label("Falloff:")
|
||||
layout.props_enum(context.tool_settings, "proportional_edit_falloff")
|
||||
|
||||
|
||||
# ********** View menus **********
|
||||
|
||||
|
||||
|
@ -2200,8 +2214,7 @@ class VIEW3D_MT_edit_mesh(Menu):
|
|||
layout.separator()
|
||||
|
||||
layout.prop(toolsettings, "use_mesh_automerge")
|
||||
layout.prop_menu_enum(toolsettings, "proportional_edit")
|
||||
layout.prop_menu_enum(toolsettings, "proportional_edit_falloff")
|
||||
layout.menu("VIEW3D_MT_edit_proportional")
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
@ -2316,6 +2329,8 @@ class VIEW3D_MT_edit_mesh_vertices(Menu):
|
|||
layout = self.layout
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
|
||||
with_bullet = bpy.app.build_options.bullet
|
||||
|
||||
layout.operator("mesh.merge")
|
||||
layout.operator("mesh.rip_move")
|
||||
layout.operator("mesh.rip_move_fill")
|
||||
|
@ -2336,7 +2351,8 @@ class VIEW3D_MT_edit_mesh_vertices(Menu):
|
|||
layout.separator()
|
||||
|
||||
layout.operator("mesh.bevel").vertex_only = True
|
||||
layout.operator("mesh.convex_hull")
|
||||
if with_bullet:
|
||||
layout.operator("mesh.convex_hull")
|
||||
layout.operator("mesh.vertices_smooth")
|
||||
layout.operator("mesh.remove_doubles")
|
||||
|
||||
|
@ -2570,8 +2586,7 @@ def draw_curve(self, context):
|
|||
|
||||
layout.separator()
|
||||
|
||||
layout.prop_menu_enum(toolsettings, "proportional_edit")
|
||||
layout.prop_menu_enum(toolsettings, "proportional_edit_falloff")
|
||||
layout.menu("VIEW3D_MT_edit_proportional")
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
@ -2730,8 +2745,7 @@ class VIEW3D_MT_edit_meta(Menu):
|
|||
|
||||
layout.separator()
|
||||
|
||||
layout.prop_menu_enum(toolsettings, "proportional_edit")
|
||||
layout.prop_menu_enum(toolsettings, "proportional_edit_falloff")
|
||||
layout.menu("VIEW3D_MT_edit_proportional")
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
@ -2768,8 +2782,7 @@ class VIEW3D_MT_edit_lattice(Menu):
|
|||
|
||||
layout.separator()
|
||||
|
||||
layout.prop_menu_enum(toolsettings, "proportional_edit")
|
||||
layout.prop_menu_enum(toolsettings, "proportional_edit_falloff")
|
||||
layout.menu("VIEW3D_MT_edit_proportional")
|
||||
|
||||
|
||||
class VIEW3D_MT_edit_armature(Menu):
|
||||
|
@ -2929,8 +2942,7 @@ class VIEW3D_MT_edit_gpencil(Menu):
|
|||
|
||||
layout.separator()
|
||||
|
||||
layout.prop_menu_enum(toolsettings, "proportional_edit")
|
||||
layout.prop_menu_enum(toolsettings, "proportional_edit_falloff")
|
||||
layout.menu("VIEW3D_MT_edit_proportional")
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
|
|
@ -64,8 +64,12 @@ struct AlembicExportParams {
|
|||
unsigned int face_sets : 1;
|
||||
unsigned int use_subdiv_schema : 1;
|
||||
unsigned int packuv : 1;
|
||||
unsigned int triangulate : 1;
|
||||
|
||||
unsigned int compression_type : 1;
|
||||
|
||||
int quad_method;
|
||||
int ngon_method;
|
||||
float global_scale;
|
||||
};
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ set(INC
|
|||
../blenkernel
|
||||
../blenlib
|
||||
../blenloader
|
||||
../bmesh
|
||||
../editors/include
|
||||
../makesdna
|
||||
../makesrna
|
||||
|
@ -48,6 +49,7 @@ if(APPLE OR WIN32)
|
|||
endif()
|
||||
|
||||
set(SRC
|
||||
intern/abc_archive.cc
|
||||
intern/abc_camera.cc
|
||||
intern/abc_customdata.cc
|
||||
intern/abc_curves.cc
|
||||
|
@ -62,6 +64,7 @@ set(SRC
|
|||
intern/alembic_capi.cc
|
||||
|
||||
ABC_alembic.h
|
||||
intern/abc_archive.h
|
||||
intern/abc_camera.h
|
||||
intern/abc_customdata.h
|
||||
intern/abc_curves.h
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2016 Kévin Dietrich.
|
||||
* All rights reserved.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*
|
||||
*/
|
||||
|
||||
#include "abc_archive.h"
|
||||
|
||||
#ifdef WIN32
|
||||
# include "utfconv.h"
|
||||
#endif
|
||||
|
||||
using Alembic::Abc::Exception;
|
||||
using Alembic::Abc::ErrorHandler;
|
||||
using Alembic::Abc::IArchive;
|
||||
using Alembic::Abc::kWrapExisting;
|
||||
using Alembic::Abc::OArchive;
|
||||
|
||||
static IArchive open_archive(const std::string &filename,
|
||||
const std::vector<std::istream *> &input_streams,
|
||||
bool &is_hdf5)
|
||||
{
|
||||
try {
|
||||
is_hdf5 = false;
|
||||
Alembic::AbcCoreOgawa::ReadArchive archive_reader(input_streams);
|
||||
|
||||
return IArchive(archive_reader(filename),
|
||||
kWrapExisting,
|
||||
ErrorHandler::kThrowPolicy);
|
||||
}
|
||||
catch (const Exception &e) {
|
||||
std::cerr << e.what() << '\n';
|
||||
|
||||
#ifdef WITH_ALEMBIC_HDF5
|
||||
try {
|
||||
is_hdf5 = true;
|
||||
Alembic::AbcCoreAbstract::ReadArraySampleCachePtr cache_ptr;
|
||||
|
||||
return IArchive(Alembic::AbcCoreHDF5::ReadArchive(),
|
||||
filename.c_str(), ErrorHandler::kThrowPolicy,
|
||||
cache_ptr);
|
||||
}
|
||||
catch (const Exception &) {
|
||||
std::cerr << e.what() << '\n';
|
||||
return IArchive();
|
||||
}
|
||||
#else
|
||||
return IArchive();
|
||||
#endif
|
||||
}
|
||||
|
||||
return IArchive();
|
||||
}
|
||||
|
||||
ArchiveReader::ArchiveReader(const char *filename)
|
||||
{
|
||||
#ifdef WIN32
|
||||
UTF16_ENCODE(filename);
|
||||
std::wstring wstr(filename_16);
|
||||
m_infile.open(wstr.c_str(), std::ios::in | std::ios::binary);
|
||||
UTF16_UN_ENCODE(filename);
|
||||
#else
|
||||
m_infile.open(filename, std::ios::in | std::ios::binary);
|
||||
#endif
|
||||
|
||||
m_streams.push_back(&m_infile);
|
||||
|
||||
bool is_hdf5;
|
||||
m_archive = open_archive(filename, m_streams, is_hdf5);
|
||||
|
||||
/* We can't open an HDF5 file from a stream, so close it. */
|
||||
if (is_hdf5) {
|
||||
m_infile.close();
|
||||
m_streams.clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool ArchiveReader::valid() const
|
||||
{
|
||||
return m_archive.valid();
|
||||
}
|
||||
|
||||
Alembic::Abc::IObject ArchiveReader::getTop()
|
||||
{
|
||||
return m_archive.getTop();
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
|
||||
/* This kinda duplicates CreateArchiveWithInfo, but Alembic does not seem to
|
||||
* have a version supporting streams. */
|
||||
static OArchive create_archive(std::ostream *ostream,
|
||||
const std::string &filename,
|
||||
const std::string &scene_name,
|
||||
Alembic::Abc::MetaData &md,
|
||||
bool ogawa)
|
||||
{
|
||||
md.set(Alembic::Abc::kApplicationNameKey, "Blender");
|
||||
md.set(Alembic::Abc::kUserDescriptionKey, scene_name);
|
||||
|
||||
time_t raw_time;
|
||||
time(&raw_time);
|
||||
char buffer[128];
|
||||
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
ctime_s(buffer, 128, &raw_time);
|
||||
#else
|
||||
ctime_r(&raw_time, buffer);
|
||||
#endif
|
||||
|
||||
const std::size_t buffer_len = strlen(buffer);
|
||||
if (buffer_len > 0 && buffer[buffer_len - 1] == '\n') {
|
||||
buffer[buffer_len - 1] = '\0';
|
||||
}
|
||||
|
||||
md.set(Alembic::Abc::kDateWrittenKey, buffer);
|
||||
|
||||
ErrorHandler::Policy policy = ErrorHandler::kThrowPolicy;
|
||||
|
||||
#ifdef WITH_ALEMBIC_HDF5
|
||||
if (!ogawa) {
|
||||
return OArchive(Alembic::AbcCoreHDF5::WriteArchive(), filename, md, policy);
|
||||
}
|
||||
#else
|
||||
static_cast<void>(filename);
|
||||
static_cast<void>(ogawa);
|
||||
#endif
|
||||
|
||||
Alembic::AbcCoreOgawa::WriteArchive archive_writer;
|
||||
return OArchive(archive_writer(ostream, md), kWrapExisting, policy);
|
||||
}
|
||||
|
||||
ArchiveWriter::ArchiveWriter(const char *filename, const char *scene, bool do_ogawa, Alembic::Abc::MetaData &md)
|
||||
{
|
||||
/* Use stream to support unicode character paths on Windows. */
|
||||
if (do_ogawa) {
|
||||
#ifdef WIN32
|
||||
UTF16_ENCODE(filename);
|
||||
std::wstring wstr(filename_16);
|
||||
m_outfile.open(wstr.c_str(), std::ios::out | std::ios::binary);
|
||||
UTF16_UN_ENCODE(filename);
|
||||
#else
|
||||
m_outfile.open(filename, std::ios::out | std::ios::binary);
|
||||
#endif
|
||||
}
|
||||
|
||||
m_archive = create_archive(&m_outfile,
|
||||
filename,
|
||||
scene,
|
||||
md,
|
||||
do_ogawa);
|
||||
}
|
||||
|
||||
OArchive &ArchiveWriter::archive()
|
||||
{
|
||||
return m_archive;
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2016 Kévin Dietrich.
|
||||
* All rights reserved.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ABC_ARCHIVE_H__
|
||||
#define __ABC_ARCHIVE_H__
|
||||
|
||||
#include <Alembic/Abc/All.h>
|
||||
|
||||
#ifdef WITH_ALEMBIC_HDF5
|
||||
# include <Alembic/AbcCoreHDF5/All.h>
|
||||
#endif
|
||||
|
||||
#include <Alembic/AbcCoreOgawa/All.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
/* Wrappers around input and output archives. The goal is to be able to use
|
||||
* streams so that unicode paths work on Windows (T49112), and to make sure that
|
||||
* the stream objects remain valid as long as the archives are open.
|
||||
*/
|
||||
|
||||
class ArchiveReader {
|
||||
Alembic::Abc::IArchive m_archive;
|
||||
std::ifstream m_infile;
|
||||
std::vector<std::istream *> m_streams;
|
||||
|
||||
public:
|
||||
explicit ArchiveReader(const char *filename);
|
||||
|
||||
bool valid() const;
|
||||
|
||||
Alembic::Abc::IObject getTop();
|
||||
};
|
||||
|
||||
class ArchiveWriter {
|
||||
std::ofstream m_outfile;
|
||||
Alembic::Abc::OArchive m_archive;
|
||||
|
||||
public:
|
||||
explicit ArchiveWriter(const char *filename, const char *scene, bool do_ogawa, Alembic::Abc::MetaData &md);
|
||||
|
||||
Alembic::Abc::OArchive &archive();
|
||||
};
|
||||
|
||||
#endif /* __ABC_ARCHIVE_H__ */
|
|
@ -63,6 +63,11 @@ struct CDStreamConfig {
|
|||
void *user_data;
|
||||
void *(*add_customdata_cb)(void *user_data, const char *name, int data_type);
|
||||
|
||||
float weight;
|
||||
float time;
|
||||
int index;
|
||||
int ceil_index;
|
||||
|
||||
CDStreamConfig()
|
||||
: mloop(NULL)
|
||||
, totloop(0)
|
||||
|
@ -72,6 +77,10 @@ struct CDStreamConfig {
|
|||
, pack_uvs(false)
|
||||
, user_data(NULL)
|
||||
, add_customdata_cb(NULL)
|
||||
, weight(0.0f)
|
||||
, time(0.0f)
|
||||
, index(0)
|
||||
, ceil_index(0)
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -24,16 +24,7 @@
|
|||
|
||||
#include <cmath>
|
||||
|
||||
#ifdef WITH_ALEMBIC_HDF5
|
||||
# include <Alembic/AbcCoreHDF5/All.h>
|
||||
#endif
|
||||
|
||||
#include <Alembic/AbcCoreOgawa/All.h>
|
||||
|
||||
#ifdef WIN32
|
||||
# include "utfconv.h"
|
||||
#endif
|
||||
|
||||
#include "abc_archive.h"
|
||||
#include "abc_camera.h"
|
||||
#include "abc_curves.h"
|
||||
#include "abc_hair.h"
|
||||
|
@ -70,54 +61,6 @@ extern "C" {
|
|||
using Alembic::Abc::TimeSamplingPtr;
|
||||
using Alembic::Abc::OBox3dProperty;
|
||||
|
||||
|
||||
/* ************************************************************************** */
|
||||
|
||||
/* This kinda duplicates CreateArchiveWithInfo, but Alembic does not seem to
|
||||
* have a version supporting streams. */
|
||||
static Alembic::Abc::OArchive create_archive(std::ostream *ostream,
|
||||
const std::string &filename,
|
||||
const std::string &scene_name,
|
||||
const Alembic::Abc::Argument &arg0,
|
||||
const Alembic::Abc::Argument &arg1,
|
||||
bool ogawa)
|
||||
{
|
||||
Alembic::Abc::MetaData md = GetMetaData(arg0, arg1);
|
||||
md.set(Alembic::Abc::kApplicationNameKey, "Blender");
|
||||
md.set(Alembic::Abc::kUserDescriptionKey, scene_name);
|
||||
|
||||
time_t raw_time;
|
||||
time(&raw_time);
|
||||
char buffer[128];
|
||||
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
ctime_s(buffer, 128, &raw_time);
|
||||
#else
|
||||
ctime_r(&raw_time, buffer);
|
||||
#endif
|
||||
|
||||
const std::size_t buffer_len = strlen(buffer);
|
||||
if (buffer_len > 0 && buffer[buffer_len - 1] == '\n') {
|
||||
buffer[buffer_len - 1] = '\0';
|
||||
}
|
||||
|
||||
md.set(Alembic::Abc::kDateWrittenKey, buffer);
|
||||
|
||||
Alembic::Abc::ErrorHandler::Policy policy = GetErrorHandlerPolicyFromArgs(arg0, arg1);
|
||||
|
||||
#ifdef WITH_ALEMBIC_HDF5
|
||||
if (!ogawa) {
|
||||
return Alembic::Abc::OArchive(Alembic::AbcCoreHDF5::WriteArchive(), filename, md, policy);
|
||||
}
|
||||
#else
|
||||
static_cast<void>(filename);
|
||||
static_cast<void>(ogawa);
|
||||
#endif
|
||||
|
||||
Alembic::AbcCoreOgawa::WriteArchive archive_writer;
|
||||
return Alembic::Abc::OArchive(archive_writer(ostream, md), Alembic::Abc::kWrapExisting, policy);
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
|
||||
ExportSettings::ExportSettings()
|
||||
|
@ -144,6 +87,9 @@ ExportSettings::ExportSettings()
|
|||
, export_ogawa(true)
|
||||
, pack_uv(false)
|
||||
, do_convert_axis(false)
|
||||
, triangulate(false)
|
||||
, quad_method(0)
|
||||
, ngon_method(0)
|
||||
{}
|
||||
|
||||
static bool object_is_smoke_sim(Object *ob)
|
||||
|
@ -201,6 +147,7 @@ AbcExporter::AbcExporter(Scene *scene, const char *filename, ExportSettings &set
|
|||
, m_trans_sampling_index(0)
|
||||
, m_shape_sampling_index(0)
|
||||
, m_scene(scene)
|
||||
, m_writer(NULL)
|
||||
{}
|
||||
|
||||
AbcExporter::~AbcExporter()
|
||||
|
@ -213,6 +160,8 @@ AbcExporter::~AbcExporter()
|
|||
for (int i = 0, e = m_shapes.size(); i != e; ++i) {
|
||||
delete m_shapes[i];
|
||||
}
|
||||
|
||||
delete m_writer;
|
||||
}
|
||||
|
||||
void AbcExporter::getShutterSamples(double step, bool time_relative,
|
||||
|
@ -296,32 +245,13 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled)
|
|||
Alembic::AbcCoreAbstract::MetaData md;
|
||||
md.set("FramesPerTimeUnit", str_fps);
|
||||
|
||||
Alembic::Abc::Argument arg(md);
|
||||
|
||||
/* Use stream to support unicode character paths on Windows. */
|
||||
if (m_settings.export_ogawa) {
|
||||
#ifdef WIN32
|
||||
UTF16_ENCODE(m_filename);
|
||||
std::wstring wstr(m_filename_16);
|
||||
m_out_file.open(wstr.c_str(), std::ios::out | std::ios::binary);
|
||||
UTF16_UN_ENCODE(m_filename);
|
||||
#else
|
||||
m_out_file.open(m_filename, std::ios::out | std::ios::binary);
|
||||
#endif
|
||||
}
|
||||
|
||||
m_archive = create_archive(&m_out_file,
|
||||
m_filename,
|
||||
scene_name,
|
||||
Alembic::Abc::ErrorHandler::kThrowPolicy,
|
||||
arg,
|
||||
m_settings.export_ogawa);
|
||||
m_writer = new ArchiveWriter(m_filename, scene_name.c_str(), m_settings.export_ogawa, md);
|
||||
|
||||
/* Create time samplings for transforms and shapes. */
|
||||
|
||||
TimeSamplingPtr trans_time = createTimeSampling(m_settings.frame_step_xform);
|
||||
|
||||
m_trans_sampling_index = m_archive.addTimeSampling(*trans_time);
|
||||
m_trans_sampling_index = m_writer->archive().addTimeSampling(*trans_time);
|
||||
|
||||
TimeSamplingPtr shape_time;
|
||||
|
||||
|
@ -333,10 +263,10 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled)
|
|||
}
|
||||
else {
|
||||
shape_time = createTimeSampling(m_settings.frame_step_shape);
|
||||
m_shape_sampling_index = m_archive.addTimeSampling(*shape_time);
|
||||
m_shape_sampling_index = m_writer->archive().addTimeSampling(*shape_time);
|
||||
}
|
||||
|
||||
OBox3dProperty archive_bounds_prop = Alembic::AbcGeom::CreateOArchiveBounds(m_archive, m_trans_sampling_index);
|
||||
OBox3dProperty archive_bounds_prop = Alembic::AbcGeom::CreateOArchiveBounds(m_writer->archive(), m_trans_sampling_index);
|
||||
|
||||
if (m_settings.flatten_hierarchy) {
|
||||
createTransformWritersFlat();
|
||||
|
@ -442,7 +372,7 @@ void AbcExporter::createTransformWritersFlat()
|
|||
|
||||
if (export_object(&m_settings, ob) && object_is_shape(ob)) {
|
||||
std::string name = get_id_name(ob);
|
||||
m_xforms[name] = new AbcTransformWriter(ob, m_archive.getTop(), 0, m_trans_sampling_index, m_settings);
|
||||
m_xforms[name] = new AbcTransformWriter(ob, m_writer->archive().getTop(), 0, m_trans_sampling_index, m_settings);
|
||||
}
|
||||
|
||||
base = base->next;
|
||||
|
@ -508,7 +438,7 @@ void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupl
|
|||
m_xforms[name]->setParent(parent);
|
||||
}
|
||||
else {
|
||||
m_xforms[name] = new AbcTransformWriter(ob, m_archive.getTop(), NULL, m_trans_sampling_index, m_settings);
|
||||
m_xforms[name] = new AbcTransformWriter(ob, m_writer->archive().getTop(), NULL, m_trans_sampling_index, m_settings);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,13 +24,13 @@
|
|||
#define __ABC_EXPORTER_H__
|
||||
|
||||
#include <Alembic/Abc/All.h>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
class AbcObjectWriter;
|
||||
class AbcTransformWriter;
|
||||
class ArchiveWriter;
|
||||
|
||||
struct EvaluationContext;
|
||||
struct Main;
|
||||
|
@ -66,6 +66,10 @@ struct ExportSettings {
|
|||
bool export_child_hairs;
|
||||
bool export_ogawa;
|
||||
bool pack_uv;
|
||||
bool triangulate;
|
||||
|
||||
int quad_method;
|
||||
int ngon_method;
|
||||
|
||||
bool do_convert_axis;
|
||||
float convert_matrix[3][3];
|
||||
|
@ -76,12 +80,12 @@ class AbcExporter {
|
|||
|
||||
const char *m_filename;
|
||||
|
||||
std::ofstream m_out_file;
|
||||
Alembic::Abc::OArchive m_archive;
|
||||
unsigned int m_trans_sampling_index, m_shape_sampling_index;
|
||||
|
||||
Scene *m_scene;
|
||||
|
||||
ArchiveWriter *m_writer;
|
||||
|
||||
std::map<std::string, AbcTransformWriter *> m_xforms;
|
||||
std::vector<AbcObjectWriter *> m_shapes;
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ AbcHairWriter::AbcHairWriter(Scene *scene,
|
|||
{
|
||||
m_psys = NULL; // = psys;
|
||||
|
||||
OCurves curves(parent->alembicXform(), m_name, m_time_sampling);
|
||||
OCurves curves(parent->alembicXform(), psys->name, m_time_sampling);
|
||||
m_schema = curves.getSchema();
|
||||
}
|
||||
|
||||
|
|
|
@ -37,8 +37,8 @@ extern "C" {
|
|||
#include "BLI_math_geom.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "BKE_cdderivedmesh.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_mesh.h"
|
||||
|
@ -49,6 +49,9 @@ extern "C" {
|
|||
#include "WM_types.h"
|
||||
|
||||
#include "ED_mesh.h"
|
||||
|
||||
#include "bmesh.h"
|
||||
#include "bmesh_tools.h"
|
||||
}
|
||||
|
||||
using Alembic::Abc::FloatArraySample;
|
||||
|
@ -538,6 +541,23 @@ DerivedMesh *AbcMeshWriter::getFinalMesh()
|
|||
m_subsurf_mod->mode &= ~eModifierMode_DisableTemporary;
|
||||
}
|
||||
|
||||
if (m_settings.triangulate) {
|
||||
const bool tag_only = false;
|
||||
const int quad_method = m_settings.quad_method;
|
||||
const int ngon_method = m_settings.ngon_method;
|
||||
|
||||
BMesh *bm = DM_to_bmesh(dm, true);
|
||||
|
||||
BM_mesh_triangulate(bm, quad_method, ngon_method, tag_only, NULL, NULL, NULL);
|
||||
|
||||
DerivedMesh *result = CDDM_from_bmesh(bm, false);
|
||||
BM_mesh_free(bm);
|
||||
|
||||
freeMesh(dm);
|
||||
|
||||
dm = result;
|
||||
}
|
||||
|
||||
m_custom_data_config.pack_uvs = m_settings.pack_uv;
|
||||
m_custom_data_config.mpoly = dm->getPolyArray(dm);
|
||||
m_custom_data_config.mloop = dm->getLoopArray(dm);
|
||||
|
@ -784,6 +804,7 @@ struct AbcMeshData {
|
|||
Int32ArraySamplePtr face_counts;
|
||||
|
||||
P3fArraySamplePtr positions;
|
||||
P3fArraySamplePtr ceil_positions;
|
||||
|
||||
N3fArraySamplePtr vertex_normals;
|
||||
N3fArraySamplePtr face_normals;
|
||||
|
@ -831,12 +852,32 @@ CDStreamConfig create_config(Mesh *mesh)
|
|||
return config;
|
||||
}
|
||||
|
||||
static void read_mverts_interp(MVert *mverts, const P3fArraySamplePtr &positions, const P3fArraySamplePtr &ceil_positions, const float weight)
|
||||
{
|
||||
float tmp[3];
|
||||
for (int i = 0; i < positions->size(); ++i) {
|
||||
MVert &mvert = mverts[i];
|
||||
const Imath::V3f &floor_pos = (*positions)[i];
|
||||
const Imath::V3f &ceil_pos = (*ceil_positions)[i];
|
||||
|
||||
interp_v3_v3v3(tmp, floor_pos.getValue(), ceil_pos.getValue(), weight);
|
||||
copy_yup_zup(mvert.co, tmp);
|
||||
|
||||
mvert.bweight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void read_mverts(CDStreamConfig &config, const AbcMeshData &mesh_data)
|
||||
{
|
||||
MVert *mverts = config.mvert;
|
||||
const P3fArraySamplePtr &positions = mesh_data.positions;
|
||||
const N3fArraySamplePtr &normals = mesh_data.vertex_normals;
|
||||
|
||||
if (config.weight != 0.0f && mesh_data.ceil_positions) {
|
||||
read_mverts_interp(mverts, positions, mesh_data.ceil_positions, config.weight);
|
||||
return;
|
||||
}
|
||||
|
||||
read_mverts(mverts, positions, normals);
|
||||
}
|
||||
|
||||
|
@ -1063,6 +1104,46 @@ void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_star
|
|||
utils::assign_materials(bmain, m_object, mat_map);
|
||||
}
|
||||
|
||||
typedef std::pair<Alembic::AbcCoreAbstract::index_t, float> index_time_pair_t;
|
||||
|
||||
static void get_weight_and_index(CDStreamConfig &config,
|
||||
Alembic::AbcCoreAbstract::TimeSamplingPtr time_sampling,
|
||||
size_t samples_number)
|
||||
{
|
||||
if (samples_number == 0) {
|
||||
samples_number = 1;
|
||||
}
|
||||
|
||||
index_time_pair_t floor_index = time_sampling->getFloorIndex(config.time, samples_number);
|
||||
|
||||
config.index = floor_index.first;
|
||||
config.ceil_index = config.index;
|
||||
|
||||
if (fabs(config.time - floor_index.second) < 0.0001f) {
|
||||
config.weight = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
index_time_pair_t ceil_index = time_sampling->getCeilIndex(config.time, samples_number);
|
||||
|
||||
if (config.index == ceil_index.first) {
|
||||
config.weight = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
config.ceil_index = ceil_index.first;
|
||||
|
||||
float alpha = (config.time - floor_index.second) / (ceil_index.second - floor_index.second);
|
||||
|
||||
/* Since we so closely match the ceiling, we'll just use it. */
|
||||
if (fabs(1.0f - alpha) < 0.0001f) {
|
||||
config.index = config.ceil_index;
|
||||
alpha = 0.0f;
|
||||
}
|
||||
|
||||
config.weight = alpha;
|
||||
}
|
||||
|
||||
void read_mesh_sample(ImportSettings *settings,
|
||||
const IPolyMeshSchema &schema,
|
||||
const ISampleSelector &selector,
|
||||
|
@ -1080,6 +1161,14 @@ void read_mesh_sample(ImportSettings *settings,
|
|||
|
||||
do_normals = (abc_mesh_data.face_normals != NULL);
|
||||
|
||||
get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples());
|
||||
|
||||
if (config.weight != 0.0f) {
|
||||
Alembic::AbcGeom::IPolyMeshSchema::Sample ceil_sample;
|
||||
schema.get(ceil_sample, Alembic::Abc::ISampleSelector(static_cast<Alembic::AbcCoreAbstract::index_t>(config.ceil_index)));
|
||||
abc_mesh_data.ceil_positions = ceil_sample.getPositions();
|
||||
}
|
||||
|
||||
if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) {
|
||||
read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector);
|
||||
}
|
||||
|
@ -1195,6 +1284,14 @@ void read_subd_sample(ImportSettings *settings,
|
|||
abc_mesh_data.face_normals = N3fArraySamplePtr();
|
||||
abc_mesh_data.positions = sample.getPositions();
|
||||
|
||||
get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples());
|
||||
|
||||
if (config.weight != 0.0f) {
|
||||
Alembic::AbcGeom::ISubDSchema::Sample ceil_sample;
|
||||
schema.get(ceil_sample, Alembic::Abc::ISampleSelector(static_cast<Alembic::AbcCoreAbstract::index_t>(config.ceil_index)));
|
||||
abc_mesh_data.ceil_positions = ceil_sample.getPositions();
|
||||
}
|
||||
|
||||
if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) {
|
||||
read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector);
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ AbcPointsWriter::AbcPointsWriter(Scene *scene,
|
|||
{
|
||||
m_psys = NULL; // = psys;
|
||||
|
||||
OPoints points(parent->alembicXform(), m_name, m_time_sampling);
|
||||
OPoints points(parent->alembicXform(), psys->name, m_time_sampling);
|
||||
m_schema = points.getSchema();
|
||||
}
|
||||
|
||||
|
|
|
@ -22,19 +22,9 @@
|
|||
|
||||
#include "../ABC_alembic.h"
|
||||
|
||||
#ifdef WITH_ALEMBIC_HDF5
|
||||
# include <Alembic/AbcCoreHDF5/All.h>
|
||||
#endif
|
||||
|
||||
#include <Alembic/AbcCoreOgawa/All.h>
|
||||
#include <Alembic/AbcMaterial/IMaterial.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#ifdef WIN32
|
||||
# include "utfconv.h"
|
||||
#endif
|
||||
|
||||
#include "abc_archive.h"
|
||||
#include "abc_camera.h"
|
||||
#include "abc_curves.h"
|
||||
#include "abc_hair.h"
|
||||
|
@ -83,13 +73,10 @@ extern "C" {
|
|||
using Alembic::Abc::Int32ArraySamplePtr;
|
||||
using Alembic::Abc::ObjectHeader;
|
||||
|
||||
using Alembic::AbcGeom::ErrorHandler;
|
||||
using Alembic::AbcGeom::Exception;
|
||||
using Alembic::AbcGeom::MetaData;
|
||||
using Alembic::AbcGeom::P3fArraySamplePtr;
|
||||
using Alembic::AbcGeom::kWrapExisting;
|
||||
|
||||
using Alembic::AbcGeom::IArchive;
|
||||
using Alembic::AbcGeom::ICamera;
|
||||
using Alembic::AbcGeom::ICurves;
|
||||
using Alembic::AbcGeom::ICurvesSchema;
|
||||
|
@ -115,95 +102,16 @@ using Alembic::AbcGeom::V3fArraySamplePtr;
|
|||
|
||||
using Alembic::AbcMaterial::IMaterial;
|
||||
|
||||
static IArchive open_archive(const std::string &filename,
|
||||
const std::vector<std::istream *> &input_streams,
|
||||
bool &is_hdf5)
|
||||
{
|
||||
try {
|
||||
is_hdf5 = false;
|
||||
Alembic::AbcCoreOgawa::ReadArchive archive_reader(input_streams);
|
||||
|
||||
return IArchive(archive_reader(filename),
|
||||
kWrapExisting,
|
||||
ErrorHandler::kThrowPolicy);
|
||||
}
|
||||
catch (const Exception &e) {
|
||||
std::cerr << e.what() << '\n';
|
||||
|
||||
#ifdef WITH_ALEMBIC_HDF5
|
||||
try {
|
||||
is_hdf5 = true;
|
||||
Alembic::AbcCoreAbstract::ReadArraySampleCachePtr cache_ptr;
|
||||
|
||||
return IArchive(Alembic::AbcCoreHDF5::ReadArchive(),
|
||||
filename.c_str(), ErrorHandler::kThrowPolicy,
|
||||
cache_ptr);
|
||||
}
|
||||
catch (const Exception &) {
|
||||
std::cerr << e.what() << '\n';
|
||||
return IArchive();
|
||||
}
|
||||
#else
|
||||
return IArchive();
|
||||
#endif
|
||||
}
|
||||
|
||||
return IArchive();
|
||||
}
|
||||
|
||||
/* Wrapper around an archive to be able to use streams so that unicode paths
|
||||
* work on Windows (T49112), and to make sure the input stream remains valid as
|
||||
* long as the archive is open. */
|
||||
class ArchiveWrapper {
|
||||
IArchive m_archive;
|
||||
std::ifstream m_infile;
|
||||
std::vector<std::istream *> m_streams;
|
||||
|
||||
public:
|
||||
explicit ArchiveWrapper(const char *filename)
|
||||
{
|
||||
#ifdef WIN32
|
||||
UTF16_ENCODE(filename);
|
||||
std::wstring wstr(filename_16);
|
||||
m_infile.open(wstr.c_str(), std::ios::in | std::ios::binary);
|
||||
UTF16_UN_ENCODE(filename);
|
||||
#else
|
||||
m_infile.open(filename, std::ios::in | std::ios::binary);
|
||||
#endif
|
||||
|
||||
m_streams.push_back(&m_infile);
|
||||
|
||||
bool is_hdf5;
|
||||
m_archive = open_archive(filename, m_streams, is_hdf5);
|
||||
|
||||
/* We can't open an HDF5 file from a stream, so close it. */
|
||||
if (is_hdf5) {
|
||||
m_infile.close();
|
||||
m_streams.clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool valid() const
|
||||
{
|
||||
return m_archive.valid();
|
||||
}
|
||||
|
||||
IObject getTop()
|
||||
{
|
||||
return m_archive.getTop();
|
||||
}
|
||||
};
|
||||
|
||||
struct AbcArchiveHandle {
|
||||
int unused;
|
||||
};
|
||||
|
||||
ABC_INLINE ArchiveWrapper *archive_from_handle(AbcArchiveHandle *handle)
|
||||
ABC_INLINE ArchiveReader *archive_from_handle(AbcArchiveHandle *handle)
|
||||
{
|
||||
return reinterpret_cast<ArchiveWrapper *>(handle);
|
||||
return reinterpret_cast<ArchiveReader *>(handle);
|
||||
}
|
||||
|
||||
ABC_INLINE AbcArchiveHandle *handle_from_archive(ArchiveWrapper *archive)
|
||||
ABC_INLINE AbcArchiveHandle *handle_from_archive(ArchiveReader *archive)
|
||||
{
|
||||
return reinterpret_cast<AbcArchiveHandle *>(archive);
|
||||
}
|
||||
|
@ -301,7 +209,7 @@ static void gather_objects_paths(const IObject &object, ListBase *object_paths)
|
|||
|
||||
AbcArchiveHandle *ABC_create_handle(const char *filename, ListBase *object_paths)
|
||||
{
|
||||
ArchiveWrapper *archive = new ArchiveWrapper(filename);
|
||||
ArchiveReader *archive = new ArchiveReader(filename);
|
||||
|
||||
if (!archive->valid()) {
|
||||
delete archive;
|
||||
|
@ -443,6 +351,9 @@ void ABC_export(
|
|||
job->settings.export_ogawa = (params->compression_type == ABC_ARCHIVE_OGAWA);
|
||||
job->settings.pack_uv = params->packuv;
|
||||
job->settings.global_scale = params->global_scale;
|
||||
job->settings.triangulate = params->triangulate;
|
||||
job->settings.quad_method = params->quad_method;
|
||||
job->settings.ngon_method = params->ngon_method;
|
||||
|
||||
if (job->settings.frame_start > job->settings.frame_end) {
|
||||
std::swap(job->settings.frame_start, job->settings.frame_end);
|
||||
|
@ -599,10 +510,6 @@ struct ImportJobData {
|
|||
|
||||
ABC_INLINE bool is_mesh_and_strands(const IObject &object)
|
||||
{
|
||||
if (object.getNumChildren() != 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool has_mesh = false;
|
||||
bool has_curve = false;
|
||||
|
||||
|
@ -624,6 +531,9 @@ ABC_INLINE bool is_mesh_and_strands(const IObject &object)
|
|||
else if (ICurves::matches(md)) {
|
||||
has_curve = true;
|
||||
}
|
||||
else if (IPoints::matches(md)) {
|
||||
has_curve = true;
|
||||
}
|
||||
}
|
||||
|
||||
return has_mesh && has_curve;
|
||||
|
@ -637,7 +547,7 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa
|
|||
data->do_update = do_update;
|
||||
data->progress = progress;
|
||||
|
||||
ArchiveWrapper *archive = new ArchiveWrapper(data->filename);
|
||||
ArchiveReader *archive = new ArchiveReader(data->filename);
|
||||
|
||||
if (!archive->valid()) {
|
||||
delete archive;
|
||||
|
@ -865,7 +775,7 @@ void ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence
|
|||
|
||||
void ABC_get_transform(AbcArchiveHandle *handle, Object *ob, const char *object_path, float r_mat[4][4], float time, float scale)
|
||||
{
|
||||
ArchiveWrapper *archive = archive_from_handle(handle);
|
||||
ArchiveReader *archive = archive_from_handle(handle);
|
||||
|
||||
if (!archive || !archive->valid()) {
|
||||
return;
|
||||
|
@ -988,6 +898,7 @@ static DerivedMesh *read_mesh_sample(DerivedMesh *dm, const IObject &iobject, co
|
|||
}
|
||||
|
||||
CDStreamConfig config = get_config(new_dm ? new_dm : dm);
|
||||
config.time = time;
|
||||
|
||||
bool do_normals = false;
|
||||
read_mesh_sample(&settings, schema, sample_sel, config, do_normals);
|
||||
|
@ -1042,6 +953,7 @@ static DerivedMesh *read_subd_sample(DerivedMesh *dm, const IObject &iobject, co
|
|||
|
||||
/* Only read point data when streaming meshes, unless we need to create new ones. */
|
||||
CDStreamConfig config = get_config(new_dm ? new_dm : dm);
|
||||
config.time = time;
|
||||
read_subd_sample(&settings, schema, sample_sel, config);
|
||||
|
||||
if (new_dm) {
|
||||
|
@ -1141,7 +1053,7 @@ DerivedMesh *ABC_read_mesh(AbcArchiveHandle *handle,
|
|||
const char **err_str,
|
||||
int read_flag)
|
||||
{
|
||||
ArchiveWrapper *archive = archive_from_handle(handle);
|
||||
ArchiveReader *archive = archive_from_handle(handle);
|
||||
|
||||
if (!archive || !archive->valid()) {
|
||||
*err_str = "Invalid archive!";
|
||||
|
|
|
@ -783,6 +783,7 @@ void DM_vertex_attributes_from_gpu(
|
|||
struct GPUVertexAttribs *gattribs, DMVertexAttribs *attribs);
|
||||
|
||||
void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert, int loop);
|
||||
void DM_draw_attrib_vertex_uniforms(const DMVertexAttribs *attribs);
|
||||
|
||||
void DM_calc_tangents_names_from_gpu(
|
||||
const struct GPUVertexAttribs *gattribs,
|
||||
|
|
|
@ -37,6 +37,7 @@ struct ID;
|
|||
void BKE_copybuffer_begin(struct Main *bmain_src);
|
||||
void BKE_copybuffer_tag_ID(struct ID *id);
|
||||
bool BKE_copybuffer_save(struct Main *bmain_src, const char *filename, struct ReportList *reports);
|
||||
bool BKE_copybuffer_read(struct Main *bmain_dst, const char *libname, struct ReportList *reports);
|
||||
bool BKE_copybuffer_paste(struct bContext *C, const char *libname, const short flag, struct ReportList *reports);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
/* can be left blank, otherwise a,b,c... etc with no quotes */
|
||||
#define BLENDER_VERSION_CHAR
|
||||
/* alpha/beta/rc/release, docs use this */
|
||||
#define BLENDER_VERSION_CYCLE rc
|
||||
#define BLENDER_VERSION_CYCLE alpha
|
||||
|
||||
extern char versionstr[]; /* from blender.c */
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ enum {
|
|||
* (like e.g. Object->data). */
|
||||
ID_REMAP_FLAG_NEVER_NULL_USAGE = 1 << 2,
|
||||
/* This tells the callback func to force setting IDs using target one with a 'never NULL' pointer to NULL.
|
||||
* WARNING! Use with extreme care, this will leave database in broken state! */
|
||||
* WARNING! Use with extreme care, this will leave database in broken state and can cause crashes very easily! */
|
||||
ID_REMAP_FORCE_NEVER_NULL_USAGE = 1 << 3,
|
||||
};
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm);
|
|||
#include "GPU_shader.h"
|
||||
|
||||
#ifdef WITH_OPENSUBDIV
|
||||
# include "BKE_depsgraph.h"
|
||||
# include "DNA_userdef_types.h"
|
||||
#endif
|
||||
|
||||
|
@ -2566,7 +2567,7 @@ static void editbmesh_calc_modifiers(
|
|||
* playback performance is kept as high as possible.
|
||||
*/
|
||||
static bool calc_modifiers_skip_orco(Scene *scene,
|
||||
const Object *ob,
|
||||
Object *ob,
|
||||
bool use_render_params)
|
||||
{
|
||||
ModifierData *last_md = ob->modifiers.last;
|
||||
|
@ -2575,9 +2576,18 @@ static bool calc_modifiers_skip_orco(Scene *scene,
|
|||
last_md->type == eModifierType_Subsurf &&
|
||||
modifier_isEnabled(scene, last_md, required_mode))
|
||||
{
|
||||
if (U.opensubdiv_compute_type == USER_OPENSUBDIV_COMPUTE_NONE) {
|
||||
return false;
|
||||
}
|
||||
else if ((ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) != 0) {
|
||||
return false;
|
||||
}
|
||||
else if ((DAG_get_eval_flags_for_object(scene, ob) & DAG_EVAL_NEED_CPU) != 0) {
|
||||
return false;
|
||||
}
|
||||
SubsurfModifierData *smd = (SubsurfModifierData *)last_md;
|
||||
/* TODO(sergey): Deduplicate this with checks from subsurf_ccg.c. */
|
||||
return smd->use_opensubdiv && U.opensubdiv_compute_type != USER_OPENSUBDIV_COMPUTE_NONE;
|
||||
return smd->use_opensubdiv != 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -3464,13 +3474,17 @@ void DM_calc_loop_tangents(
|
|||
|
||||
/* Update active layer index */
|
||||
uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, act_uv_n);
|
||||
tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[uv_index].name);
|
||||
CustomData_set_layer_active_index(&dm->loopData, CD_TANGENT, tan_index);
|
||||
if (uv_index != -1) {
|
||||
tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[uv_index].name);
|
||||
CustomData_set_layer_active_index(&dm->loopData, CD_TANGENT, tan_index);
|
||||
}
|
||||
|
||||
/* Update render layer index */
|
||||
uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, ren_uv_n);
|
||||
tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[uv_index].name);
|
||||
CustomData_set_layer_render_index(&dm->loopData, CD_TANGENT, tan_index);
|
||||
if (uv_index != -1) {
|
||||
tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[uv_index].name);
|
||||
CustomData_set_layer_render_index(&dm->loopData, CD_TANGENT, tan_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3797,7 +3811,6 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert,
|
|||
glTexCoord3fv(orco);
|
||||
else
|
||||
glVertexAttrib3fv(attribs->orco.gl_index, orco);
|
||||
glUniform1i(attribs->orco.gl_info_index, 0);
|
||||
}
|
||||
|
||||
/* uv texture coordinates */
|
||||
|
@ -3816,7 +3829,6 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert,
|
|||
glTexCoord2fv(uv);
|
||||
else
|
||||
glVertexAttrib2fv(attribs->tface[b].gl_index, uv);
|
||||
glUniform1i(attribs->tface[b].gl_info_index, 0);
|
||||
}
|
||||
|
||||
/* vertex colors */
|
||||
|
@ -3832,17 +3844,33 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert,
|
|||
}
|
||||
|
||||
glVertexAttrib4fv(attribs->mcol[b].gl_index, col);
|
||||
glUniform1i(attribs->mcol[b].gl_info_index, GPU_ATTR_INFO_SRGB);
|
||||
}
|
||||
|
||||
/* tangent for normal mapping */
|
||||
for (b = 0; b < attribs->tottang; b++) {
|
||||
if (attribs->tang[b].array) {
|
||||
/*const*/ float (*array)[4] = attribs->tang[b].array;
|
||||
const float *tang = (array) ? array[a * 4 + vert] : zero;
|
||||
const float *tang = (array) ? array[loop] : zero;
|
||||
glVertexAttrib4fv(attribs->tang[b].gl_index, tang);
|
||||
}
|
||||
glUniform1i(attribs->tang[b].gl_info_index, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void DM_draw_attrib_vertex_uniforms(const DMVertexAttribs *attribs)
|
||||
{
|
||||
int i;
|
||||
if (attribs->totorco) {
|
||||
glUniform1i(attribs->orco.gl_info_index, 0);
|
||||
}
|
||||
for (i = 0; i < attribs->tottface; i++) {
|
||||
glUniform1i(attribs->tface[i].gl_info_index, 0);
|
||||
}
|
||||
for (i = 0; i < attribs->totmcol; i++) {
|
||||
glUniform1i(attribs->mcol[i].gl_info_index, GPU_ATTR_INFO_SRGB);
|
||||
}
|
||||
|
||||
for (i = 0; i < attribs->tottang; i++) {
|
||||
glUniform1i(attribs->tang[i].gl_info_index, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -85,6 +85,31 @@ bool BKE_copybuffer_save(Main *bmain_src, const char *filename, ReportList *repo
|
|||
return retval;
|
||||
}
|
||||
|
||||
bool BKE_copybuffer_read(Main *bmain_dst, const char *libname, ReportList *reports)
|
||||
{
|
||||
BlendHandle *bh = BLO_blendhandle_from_file(libname, reports);
|
||||
if (bh == NULL) {
|
||||
/* Error reports will have been made by BLO_blendhandle_from_file(). */
|
||||
return false;
|
||||
}
|
||||
/* Here appending/linking starts. */
|
||||
Main *mainl = BLO_library_link_begin(bmain_dst, &bh, libname);
|
||||
BLO_library_link_copypaste(mainl, bh);
|
||||
BLO_library_link_end(mainl, &bh, 0, NULL, NULL);
|
||||
/* Mark all library linked objects to be updated. */
|
||||
BKE_main_lib_objects_recalc_all(bmain_dst);
|
||||
IMB_colormanagement_check_file_config(bmain_dst);
|
||||
/* Append, rather than linking. */
|
||||
Library *lib = BLI_findstring(&bmain_dst->library, libname, offsetof(Library, filepath));
|
||||
BKE_library_make_local(bmain_dst, lib, true, false);
|
||||
/* Important we unset, otherwise these object wont
|
||||
* link into other scenes from this blend file.
|
||||
*/
|
||||
BKE_main_id_tag_all(bmain_dst, LIB_TAG_PRE_EXISTING, false);
|
||||
BLO_blendhandle_close(bh);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return Success.
|
||||
*/
|
||||
|
|
|
@ -121,7 +121,12 @@ static void setup_app_data(
|
|||
LOAD_UNDO,
|
||||
} mode;
|
||||
|
||||
if (BLI_listbase_is_empty(&bfd->main->screen)) {
|
||||
/* may happen with library files - UNDO file should never have NULL cursccene... */
|
||||
if (ELEM(NULL, bfd->curscreen, bfd->curscene)) {
|
||||
BKE_report(reports, RPT_WARNING, "Library file, loading empty scene");
|
||||
mode = LOAD_UI_OFF;
|
||||
}
|
||||
else if (BLI_listbase_is_empty(&bfd->main->screen)) {
|
||||
mode = LOAD_UNDO;
|
||||
}
|
||||
else if (G.fileflags & G_FILE_NO_UI) {
|
||||
|
@ -131,14 +136,6 @@ static void setup_app_data(
|
|||
mode = LOAD_UI;
|
||||
}
|
||||
|
||||
if (mode != LOAD_UNDO) {
|
||||
/* may happen with library files */
|
||||
if (ELEM(NULL, bfd->curscreen, bfd->curscene)) {
|
||||
BKE_report(reports, RPT_WARNING, "Library file, loading empty scene");
|
||||
mode = LOAD_UI_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free all render results, without this stale data gets displayed after loading files */
|
||||
if (mode != LOAD_UNDO) {
|
||||
RE_FreeAllRenderResults();
|
||||
|
@ -511,6 +508,10 @@ bool BKE_blendfile_write_partial(
|
|||
void *path_list_backup = NULL;
|
||||
const int path_list_flag = (BKE_BPATH_TRAVERSE_SKIP_LIBRARY | BKE_BPATH_TRAVERSE_SKIP_MULTIFILE);
|
||||
|
||||
/* This is needed to be able to load that file as a real one later
|
||||
* (otherwise main->name will not be set at read time). */
|
||||
BLI_strncpy(bmain_dst->name, bmain_src->name, sizeof(bmain_dst->name));
|
||||
|
||||
if (write_flags & G_FILE_RELATIVE_REMAP) {
|
||||
path_list_backup = BKE_bpath_list_backup(bmain_src, path_list_flag);
|
||||
}
|
||||
|
|
|
@ -941,8 +941,10 @@ static void cdDM_drawMappedFacesGLSL(
|
|||
|
||||
matnr = new_matnr;
|
||||
do_draw = setMaterial(matnr + 1, &gattribs);
|
||||
if (do_draw)
|
||||
if (do_draw) {
|
||||
DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
|
||||
DM_draw_attrib_vertex_uniforms(&attribs);
|
||||
}
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
}
|
||||
|
@ -1210,6 +1212,7 @@ static void cdDM_drawMappedFacesMat(
|
|||
|
||||
setMaterial(userData, matnr = new_matnr, &gattribs);
|
||||
DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
|
||||
DM_draw_attrib_vertex_uniforms(&attribs);
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
}
|
||||
|
|
|
@ -1410,24 +1410,6 @@ static void emDM_drawMappedFacesTex(
|
|||
emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
|
||||
}
|
||||
|
||||
static void emdm_pass_attrib_update_uniforms(const DMVertexAttribs *attribs)
|
||||
{
|
||||
int i;
|
||||
if (attribs->totorco) {
|
||||
glUniform1i(attribs->orco.gl_info_index, 0);
|
||||
}
|
||||
for (i = 0; i < attribs->tottface; i++) {
|
||||
glUniform1i(attribs->tface[i].gl_info_index, 0);
|
||||
}
|
||||
for (i = 0; i < attribs->totmcol; i++) {
|
||||
glUniform1i(attribs->mcol[i].gl_info_index, GPU_ATTR_INFO_SRGB);
|
||||
}
|
||||
|
||||
for (i = 0; i < attribs->tottang; i++) {
|
||||
glUniform1i(attribs->tang[i].gl_info_index, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \note
|
||||
*
|
||||
|
@ -1548,7 +1530,7 @@ static void emDM_drawMappedFacesGLSL(
|
|||
do_draw = setMaterial(matnr = new_matnr, &gattribs);
|
||||
if (do_draw) {
|
||||
DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
|
||||
emdm_pass_attrib_update_uniforms(&attribs);
|
||||
DM_draw_attrib_vertex_uniforms(&attribs);
|
||||
if (UNLIKELY(attribs.tottang && bm->elem_index_dirty & BM_LOOP)) {
|
||||
BM_mesh_elem_index_ensure(bm, BM_LOOP);
|
||||
}
|
||||
|
|
|
@ -153,7 +153,7 @@ enum {
|
|||
ID_REMAP_IS_USER_ONE_SKIPPED = 1 << 1, /* There was some skipped 'user_one' usages of old_id. */
|
||||
};
|
||||
|
||||
static int foreach_libblock_remap_callback(void *user_data, ID *UNUSED(id_self), ID **id_p, int cb_flag)
|
||||
static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id_p, int cb_flag)
|
||||
{
|
||||
IDRemap *id_remap_data = user_data;
|
||||
ID *old_id = id_remap_data->old_id;
|
||||
|
@ -211,6 +211,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *UNUSED(id_self),
|
|||
else {
|
||||
if (!is_never_null) {
|
||||
*id_p = new_id;
|
||||
DAG_id_tag_update(id_self, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
|
||||
}
|
||||
if (cb_flag & IDWALK_USER) {
|
||||
id_us_min(old_id);
|
||||
|
|
|
@ -2333,7 +2333,7 @@ Mesh *BKE_mesh_new_from_object(
|
|||
DerivedMesh *dm;
|
||||
/* CustomDataMask mask = CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL; */
|
||||
CustomDataMask mask = CD_MASK_MESH; /* this seems more suitable, exporter,
|
||||
* for example, needs CD_MASK_MDEFORMVERT */
|
||||
* for example, needs CD_MASK_MDEFORMVERT */
|
||||
|
||||
if (calc_undeformed)
|
||||
mask |= CD_MASK_ORCO;
|
||||
|
|
|
@ -2820,12 +2820,13 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
|
|||
int matnr = -1;
|
||||
int do_draw = 0;
|
||||
|
||||
#define PASSATTRIB(dx, dy, vert) { \
|
||||
if (attribs.totorco) \
|
||||
index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize); \
|
||||
else \
|
||||
index = 0; \
|
||||
DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert); \
|
||||
#define PASSATTRIB(dx, dy, vert) { \
|
||||
if (attribs.totorco) \
|
||||
index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize); \
|
||||
else \
|
||||
index = 0; \
|
||||
DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert); \
|
||||
DM_draw_attrib_vertex_uniforms(&attribs); \
|
||||
} (void)0
|
||||
|
||||
totpoly = ccgSubSurf_getNumFaces(ss);
|
||||
|
@ -3194,24 +3195,62 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm,
|
|||
|
||||
#ifdef WITH_OPENSUBDIV
|
||||
if (ccgdm->useGpuBackend) {
|
||||
int new_matnr;
|
||||
bool draw_smooth;
|
||||
const int level = ccgSubSurf_getSubdivisionLevels(ss);
|
||||
const int face_side = 1 << level;
|
||||
const int grid_side = 1 << (level - 1);
|
||||
const int face_patches = face_side * face_side;
|
||||
const int grid_patches = grid_side * grid_side;
|
||||
const int num_base_faces = ccgSubSurf_getNumGLMeshBaseFaces(ss);
|
||||
int current_patch = 0;
|
||||
int mat_nr = -1;
|
||||
bool draw_smooth = false;
|
||||
int start_draw_patch = -1, num_draw_patches = 0;
|
||||
GPU_draw_update_fvar_offset(dm);
|
||||
if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true, -1) == false)) {
|
||||
return;
|
||||
}
|
||||
/* TODO(sergey): Single matierial currently. */
|
||||
if (faceFlags) {
|
||||
draw_smooth = (faceFlags[0].flag & ME_SMOOTH);
|
||||
new_matnr = (faceFlags[0].mat_nr + 1);
|
||||
for (i = 0; i < num_base_faces; ++i) {
|
||||
const int num_face_verts = ccgSubSurf_getNumGLMeshBaseFaceVerts(ss, i);
|
||||
const int num_patches = (num_face_verts == 4) ? face_patches
|
||||
: num_face_verts * grid_patches;
|
||||
int new_matnr;
|
||||
bool new_draw_smooth;
|
||||
|
||||
if (faceFlags) {
|
||||
new_draw_smooth = (faceFlags[i].flag & ME_SMOOTH);
|
||||
new_matnr = (faceFlags[i].mat_nr + 1);
|
||||
}
|
||||
else {
|
||||
new_draw_smooth = true;
|
||||
new_matnr = 1;
|
||||
}
|
||||
if (new_draw_smooth != draw_smooth || new_matnr != mat_nr) {
|
||||
if (num_draw_patches != 0) {
|
||||
setMaterial(userData, mat_nr, &gattribs);
|
||||
glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
|
||||
ccgSubSurf_drawGLMesh(ss,
|
||||
true,
|
||||
start_draw_patch,
|
||||
num_draw_patches);
|
||||
}
|
||||
start_draw_patch = current_patch;
|
||||
num_draw_patches = num_patches;
|
||||
mat_nr = new_matnr;
|
||||
draw_smooth = new_draw_smooth;
|
||||
}
|
||||
else {
|
||||
num_draw_patches += num_patches;
|
||||
}
|
||||
current_patch += num_patches;
|
||||
}
|
||||
else {
|
||||
draw_smooth = true;
|
||||
new_matnr = 1;
|
||||
if (num_draw_patches != 0) {
|
||||
setMaterial(userData, mat_nr, &gattribs);
|
||||
glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
|
||||
ccgSubSurf_drawGLMesh(ss,
|
||||
true,
|
||||
start_draw_patch,
|
||||
num_draw_patches);
|
||||
}
|
||||
glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
|
||||
setMaterial(userData, new_matnr, &gattribs);
|
||||
ccgSubSurf_drawGLMesh(ss, true, -1, -1);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
return;
|
||||
}
|
||||
|
@ -3222,12 +3261,13 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm,
|
|||
|
||||
matnr = -1;
|
||||
|
||||
#define PASSATTRIB(dx, dy, vert) { \
|
||||
if (attribs.totorco) \
|
||||
index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize); \
|
||||
else \
|
||||
index = 0; \
|
||||
DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert); \
|
||||
#define PASSATTRIB(dx, dy, vert) { \
|
||||
if (attribs.totorco) \
|
||||
index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize); \
|
||||
else \
|
||||
index = 0; \
|
||||
DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert); \
|
||||
DM_draw_attrib_vertex_uniforms(&attribs); \
|
||||
} (void)0
|
||||
|
||||
totface = ccgSubSurf_getNumFaces(ss);
|
||||
|
|
|
@ -780,9 +780,10 @@ BLI_INLINE bool parallel_range_next_iter_get(
|
|||
ParallelRangeState * __restrict state,
|
||||
int * __restrict iter, int * __restrict count)
|
||||
{
|
||||
uint32_t previter = atomic_fetch_and_add_uint32((uint32_t *)(&state->iter), state->chunk_size);
|
||||
uint32_t uval = atomic_fetch_and_add_uint32((uint32_t *)(&state->iter), state->chunk_size);
|
||||
int previter = *(int32_t*)&uval;
|
||||
|
||||
*iter = (int)previter;
|
||||
*iter = previter;
|
||||
*count = max_ii(0, min_ii(state->chunk_size, state->stop - previter));
|
||||
|
||||
return (previter < state->stop);
|
||||
|
|
|
@ -2194,10 +2194,13 @@ static void fill_vmesh_fracs(VMesh *vm, float *frac, int i)
|
|||
total += len_v3v3(mesh_vert(vm, i, 0, k)->co, mesh_vert(vm, i, 0, k + 1)->co);
|
||||
frac[k + 1] = total;
|
||||
}
|
||||
if (total > BEVEL_EPSILON) {
|
||||
if (total > 0.0f) {
|
||||
for (k = 1; k <= ns; k++)
|
||||
frac[k] /= total;
|
||||
}
|
||||
else {
|
||||
frac[ns] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* Like fill_vmesh_fracs but want fractions for profile points of bndv, with ns segments */
|
||||
|
@ -2215,11 +2218,14 @@ static void fill_profile_fracs(BevelParams *bp, BoundVert *bndv, float *frac, in
|
|||
frac[k + 1] = total;
|
||||
copy_v3_v3(co, nextco);
|
||||
}
|
||||
if (total > BEVEL_EPSILON) {
|
||||
if (total > 0.0f) {
|
||||
for (k = 1; k <= ns; k++) {
|
||||
frac[k] /= total;
|
||||
}
|
||||
}
|
||||
else {
|
||||
frac[ns] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return i such that frac[i] <= f <= frac[i + 1], where frac[n] == 1.0
|
||||
|
|
|
@ -113,6 +113,32 @@ namespace DEG {
|
|||
/* ***************** */
|
||||
/* Relations Builder */
|
||||
|
||||
/* TODO(sergey): This is somewhat weak, but we don't want neither false-positive
|
||||
* time dependencies nor special exceptions in the depsgraph evaluation.
|
||||
*/
|
||||
static bool python_driver_depends_on_time(ChannelDriver *driver)
|
||||
{
|
||||
if (driver->expression[0] == '\0') {
|
||||
/* Empty expression depends on nothing. */
|
||||
return false;
|
||||
}
|
||||
if (strchr(driver->expression, '(') != NULL) {
|
||||
/* Function calls are considered dependent on a time. */
|
||||
return true;
|
||||
}
|
||||
if (strstr(driver->expression, "time") != NULL) {
|
||||
/* Variable `time` depends on time. */
|
||||
/* TODO(sergey): This is a bit weak, but not sure about better way of
|
||||
* handling this.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
/* Possible indirect time relation s should be handled via variable
|
||||
* targets.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
/* **** General purpose functions **** */
|
||||
|
||||
RNAPathKey::RNAPathKey(ID *id, const char *path) :
|
||||
|
@ -994,7 +1020,9 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
|
|||
* so for now we'll be quite conservative here about optimization and consider
|
||||
* all python drivers to be depending on time.
|
||||
*/
|
||||
if (driver->type == DRIVER_TYPE_PYTHON) {
|
||||
if ((driver->type == DRIVER_TYPE_PYTHON) &&
|
||||
python_driver_depends_on_time(driver))
|
||||
{
|
||||
TimeSourceKey time_src_key;
|
||||
add_relation(time_src_key, driver_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Driver]");
|
||||
}
|
||||
|
|
|
@ -304,7 +304,7 @@ static void schedule_node(TaskPool *pool, Depsgraph *graph, unsigned int layers,
|
|||
deg_task_run_func,
|
||||
node,
|
||||
false,
|
||||
TASK_PRIORITY_HIGH,
|
||||
TASK_PRIORITY_LOW,
|
||||
thread_id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -528,7 +528,10 @@ static bool acf_scene_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale)
|
|||
case ACHANNEL_SETTING_SELECT:
|
||||
case ACHANNEL_SETTING_EXPAND:
|
||||
return true;
|
||||
|
||||
|
||||
case ACHANNEL_SETTING_ALWAYS_VISIBLE:
|
||||
return false;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -554,7 +557,7 @@ static int acf_scene_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Setting
|
|||
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
|
||||
*neg = true;
|
||||
return ADT_CURVES_NOT_VISIBLE;
|
||||
|
||||
|
||||
default: /* unsupported */
|
||||
return 0;
|
||||
}
|
||||
|
@ -681,7 +684,10 @@ static bool acf_object_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnim
|
|||
case ACHANNEL_SETTING_SELECT:
|
||||
case ACHANNEL_SETTING_EXPAND:
|
||||
return true;
|
||||
|
||||
|
||||
case ACHANNEL_SETTING_ALWAYS_VISIBLE:
|
||||
return ((ac) && (ac->spacetype == SPACE_IPO) && (ob->adt));
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -707,7 +713,10 @@ static int acf_object_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settin
|
|||
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
|
||||
*neg = true;
|
||||
return ADT_CURVES_NOT_VISIBLE;
|
||||
|
||||
|
||||
case ACHANNEL_SETTING_ALWAYS_VISIBLE:
|
||||
return ADT_CURVES_ALWAYS_VISIBLE;
|
||||
|
||||
default: /* unsupported */
|
||||
return 0;
|
||||
}
|
||||
|
@ -731,6 +740,7 @@ static void *acf_object_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings se
|
|||
|
||||
case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
|
||||
case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
|
||||
case ACHANNEL_SETTING_ALWAYS_VISIBLE:
|
||||
if (ob->adt)
|
||||
return GET_ACF_FLAG_PTR(ob->adt->flag, type);
|
||||
return NULL;
|
||||
|
@ -838,7 +848,10 @@ static bool acf_group_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale)
|
|||
/* conditionally supported */
|
||||
case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
|
||||
return (ac->spacetype == SPACE_IPO);
|
||||
|
||||
|
||||
case ACHANNEL_SETTING_ALWAYS_VISIBLE:
|
||||
return (ac->spacetype == SPACE_IPO);
|
||||
|
||||
default: /* always supported */
|
||||
return true;
|
||||
}
|
||||
|
@ -878,7 +891,10 @@ static int acf_group_setting_flag(bAnimContext *ac, eAnimChannel_Settings settin
|
|||
case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
|
||||
*neg = 1;
|
||||
return AGRP_NOTVISIBLE;
|
||||
|
||||
|
||||
case ACHANNEL_SETTING_ALWAYS_VISIBLE:
|
||||
return ADT_CURVES_ALWAYS_VISIBLE;
|
||||
|
||||
default:
|
||||
/* this shouldn't happen */
|
||||
return 0;
|
||||
|
@ -964,7 +980,10 @@ static bool acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnim
|
|||
|
||||
case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
|
||||
return (ac->spacetype == SPACE_IPO);
|
||||
|
||||
|
||||
case ACHANNEL_SETTING_ALWAYS_VISIBLE:
|
||||
return false;
|
||||
|
||||
/* always available */
|
||||
default:
|
||||
return true;
|
||||
|
@ -3670,7 +3689,9 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
|
|||
* - in Grease Pencil mode, color swatches for layer color
|
||||
*/
|
||||
if (ac->sl) {
|
||||
if ((ac->spacetype == SPACE_IPO) && acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
|
||||
if ((ac->spacetype == SPACE_IPO) &&
|
||||
(acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE) ||
|
||||
acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE))) {
|
||||
/* for F-Curves, draw color-preview of curve behind checkbox */
|
||||
if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
|
||||
FCurve *fcu = (FCurve *)ale->data;
|
||||
|
@ -3684,9 +3705,13 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
|
|||
*/
|
||||
glRectf(offset, yminc, offset + ICON_WIDTH, ymaxc);
|
||||
}
|
||||
|
||||
/* icon is drawn as widget now... */
|
||||
offset += ICON_WIDTH;
|
||||
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
|
||||
offset += ICON_WIDTH;
|
||||
}
|
||||
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE)) {
|
||||
offset += ICON_WIDTH;
|
||||
}
|
||||
}
|
||||
else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) {
|
||||
/* just skip - drawn as widget now */
|
||||
|
@ -4031,6 +4056,11 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, const bAni
|
|||
tooltip = TIP_("Channels are visible in Graph Editor for editing");
|
||||
break;
|
||||
|
||||
case ACHANNEL_SETTING_ALWAYS_VISIBLE:
|
||||
icon = ICON_UNPINNED;
|
||||
tooltip = TIP_("Channels are visible in Graph Editor for editing");
|
||||
break;
|
||||
|
||||
case ACHANNEL_SETTING_MOD_OFF: /* modifiers disabled */
|
||||
icon = ICON_MODIFIER;
|
||||
usetoggle = false;
|
||||
|
@ -4140,6 +4170,7 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, const bAni
|
|||
case ACHANNEL_SETTING_MUTE: /* General - muting flags */
|
||||
case ACHANNEL_SETTING_PINNED: /* NLA Actions - 'map/nomap' */
|
||||
case ACHANNEL_SETTING_MOD_OFF:
|
||||
case ACHANNEL_SETTING_ALWAYS_VISIBLE:
|
||||
UI_but_funcN_set(but, achannel_setting_flush_widget_cb, MEM_dupallocN(ale), SET_INT_IN_POINTER(setting));
|
||||
break;
|
||||
|
||||
|
@ -4203,10 +4234,20 @@ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListEle
|
|||
* - in Grease Pencil mode, color swatches for layer color
|
||||
*/
|
||||
if (ac->sl) {
|
||||
if ((ac->spacetype == SPACE_IPO) && acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
|
||||
if ((ac->spacetype == SPACE_IPO) &&
|
||||
(acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE) ||
|
||||
acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE)))
|
||||
{
|
||||
/* pin toggle */
|
||||
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE)) {
|
||||
draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_ALWAYS_VISIBLE);
|
||||
offset += ICON_WIDTH;
|
||||
}
|
||||
/* visibility toggle */
|
||||
draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_VISIBLE);
|
||||
offset += ICON_WIDTH;
|
||||
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
|
||||
draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_VISIBLE);
|
||||
offset += ICON_WIDTH;
|
||||
}
|
||||
}
|
||||
else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) {
|
||||
/* 'solo' setting for NLA Tracks */
|
||||
|
|
|
@ -431,7 +431,11 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn
|
|||
/* sanity check */
|
||||
if (ELEM(NULL, anim_data, anim_data->first))
|
||||
return;
|
||||
|
||||
|
||||
if (setting == ACHANNEL_SETTING_ALWAYS_VISIBLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* find the channel that got changed */
|
||||
for (ale = anim_data->first; ale; ale = ale->next) {
|
||||
/* compare data, and type as main way of identifying the channel */
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue