Merge branch 'master' into blender2.8

This commit is contained in:
Sergey Sharybin 2016-09-16 17:09:28 +02:00
commit d96b8e168f
153 changed files with 69529 additions and 1338 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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()

View File

@ -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()

View File

@ -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

View File

@ -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)

View File

@ -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()

View File

@ -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)

View File

@ -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()

View File

@ -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 */

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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();

View File

@ -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.";

View File

@ -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, \

View File

@ -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)) {

View File

@ -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)) {

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);
}
}
}
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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|

View File

@ -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;

View File

@ -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));
}
}

View File

@ -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);
}

View File

@ -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];

View File

@ -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__ */

View File

@ -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);

View File

@ -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

View File

@ -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,

View File

@ -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());

View File

@ -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);

View File

@ -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;

View File

@ -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++;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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; }

View File

@ -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");
}

View File

@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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> {};

View File

@ -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);

View File

@ -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)

View File

@ -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 // ---------------------

View File

@ -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();
}

View File

@ -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
}

View File

@ -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) {

View File

@ -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
View File

@ -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 ^

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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(

View File

@ -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):

View File

@ -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:

View File

@ -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()

View File

@ -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;
};

View File

@ -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

View File

@ -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;
}

View File

@ -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__ */

View File

@ -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)
{}
};

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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!";

View File

@ -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,

View File

@ -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

View File

@ -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 */

View File

@ -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,
};

View File

@ -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);
}
}

View File

@ -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.
*/

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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]");
}

View File

@ -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);
}
}

View File

@ -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 */

View File

@ -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