diff --git a/CMakeLists.txt b/CMakeLists.txt index b6630b6ad8d..e623cfe290e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,7 +135,6 @@ option(WITH_GAMEENGINE "Enable Game Engine" ON) option(WITH_PLAYER "Build Player" OFF) option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ON) option(WITH_COMPOSITOR "Enable the tile based nodal compositor" ON) -option(WITH_COMPOSITOR_LEGACY "Enable legacy compositor" OFF) # GHOST Windowing Library Options option(WITH_GHOST_DEBUG "Enable debugging output for the GHOST library" OFF) @@ -1330,6 +1329,11 @@ elseif(WIN32) optimized boost_locale-${BOOST_POSTFIX} debug boost_locale-${BOOST_DEBUG_POSTFIX}) endif() + if(WITH_CYCLES_OSL) + set(BOOST_LIBRARIES ${BOOST_LIBRARIES} + optimized boost_wave-${BOOST_POSTFIX} + debug boost_wave-${BOOST_DEBUG_POSTFIX}) + endif() set(BOOST_LIBPATH ${BOOST}/lib) set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB -DBOOST_THREAD_USE_LIB ") endif() diff --git a/SConstruct b/SConstruct index 171ebc8ddef..e3e58270cdd 100644 --- a/SConstruct +++ b/SConstruct @@ -575,6 +575,23 @@ data_to_c_simple("release/datafiles/brushicons/thumb.png") data_to_c_simple("release/datafiles/brushicons/twist.png") data_to_c_simple("release/datafiles/brushicons/vertexdraw.png") +data_to_c_simple("release/datafiles/matcaps/mc01.jpg") +data_to_c_simple("release/datafiles/matcaps/mc02.jpg") +data_to_c_simple("release/datafiles/matcaps/mc03.jpg") +data_to_c_simple("release/datafiles/matcaps/mc04.jpg") +data_to_c_simple("release/datafiles/matcaps/mc05.jpg") +data_to_c_simple("release/datafiles/matcaps/mc06.jpg") +data_to_c_simple("release/datafiles/matcaps/mc07.jpg") +data_to_c_simple("release/datafiles/matcaps/mc08.jpg") +data_to_c_simple("release/datafiles/matcaps/mc09.jpg") +data_to_c_simple("release/datafiles/matcaps/mc10.jpg") +data_to_c_simple("release/datafiles/matcaps/mc11.jpg") +data_to_c_simple("release/datafiles/matcaps/mc12.jpg") +data_to_c_simple("release/datafiles/matcaps/mc13.jpg") +data_to_c_simple("release/datafiles/matcaps/mc14.jpg") +data_to_c_simple("release/datafiles/matcaps/mc15.jpg") +data_to_c_simple("release/datafiles/matcaps/mc16.jpg") + ##### END DATAFILES ########## Help(opts.GenerateHelpText(env)) diff --git a/build_files/buildbot/master.cfg b/build_files/buildbot/master.cfg index 9d0839bd0d7..3cfea2a3abd 100644 --- a/build_files/buildbot/master.cfg +++ b/build_files/buildbot/master.cfg @@ -28,8 +28,8 @@ c['slavePortnum'] = 9989 from buildbot.changes.svnpoller import SVNPoller c['change_source'] = SVNPoller( - 'https://svn.blender.org/svnroot/bf-blender/trunk/', - pollinterval=1200) + 'https://svn.blender.org/svnroot/bf-blender/trunk/', + pollinterval=1200) # BUILDERS # @@ -74,9 +74,11 @@ def svn_step(branch=''): else: return SVN(baseURL='https://svn.blender.org/svnroot/bf-blender/%%BRANCH%%/blender', mode='update', defaultBranch='trunk', workdir='blender') + def lib_svn_step(dir): return SVN(name='lib svn', baseURL='https://svn.blender.org/svnroot/bf-blender/%%BRANCH%%/lib/' + dir, mode='update', defaultBranch='trunk', workdir='lib/' + dir) + def rsync_step(id, branch, rsync_script): return ShellCommand(name='rsync', command=['python', rsync_script, id, branch], description='uploading', descriptionDone='uploaded', workdir='install') @@ -155,9 +157,9 @@ for i in range(0, schedule_cycle): print(names) c['schedulers'].append(timed.Nightly(name='nightly' + str(i), - builderNames=names, - hour=3+i, - minute=0)) + builderNames=names, + hour=3 + i, + minute=0)) # STATUS TARGETS # diff --git a/build_files/buildbot/slave_rsync.py b/build_files/buildbot/slave_rsync.py index aea1b65e333..6936232a495 100644 --- a/build_files/buildbot/slave_rsync.py +++ b/build_files/buildbot/slave_rsync.py @@ -41,5 +41,3 @@ print(command) ret = os.system(command) sys.exit(ret) - - diff --git a/build_files/cmake/cmake_static_check_clang_array.py b/build_files/cmake/cmake_static_check_clang_array.py index 7f45cc6aadc..448454c2177 100644 --- a/build_files/cmake/cmake_static_check_clang_array.py +++ b/build_files/cmake/cmake_static_check_clang_array.py @@ -50,7 +50,7 @@ def main(): check_commands = [] for c, inc_dirs, defs in source_info: cmd = ([CHECKER_BIN] + - CHECKER_ARGS + + CHECKER_ARGS + [c] + [("-I%s" % i) for i in inc_dirs] + [("-D%s" % d) for d in defs] diff --git a/build_files/cmake/cmake_static_check_cppcheck.py b/build_files/cmake/cmake_static_check_cppcheck.py index d79145f8586..2f7ffa5c240 100644 --- a/build_files/cmake/cmake_static_check_cppcheck.py +++ b/build_files/cmake/cmake_static_check_cppcheck.py @@ -56,7 +56,7 @@ def main(): check_commands = [] for c, inc_dirs, defs in source_info: cmd = ([CHECKER_BIN] + - CHECKER_ARGS + + CHECKER_ARGS + [c] + [("-I%s" % i) for i in inc_dirs] + [("-D%s" % d) for d in defs] diff --git a/build_files/cmake/cmake_static_check_smatch.py b/build_files/cmake/cmake_static_check_smatch.py index 7535f1cc55a..2cf07b093fb 100644 --- a/build_files/cmake/cmake_static_check_smatch.py +++ b/build_files/cmake/cmake_static_check_smatch.py @@ -41,6 +41,7 @@ import os USE_QUIET = (os.environ.get("QUIET", None) is not None) + def main(): source_info = project_source_info.build_info(use_cxx=False, ignore_prefix_list=CHECKER_IGNORE_PREFIX) @@ -48,7 +49,7 @@ def main(): for c, inc_dirs, defs in source_info: cmd = ([CHECKER_BIN] + - CHECKER_ARGS + + CHECKER_ARGS + [c] + [("-I%s" % i) for i in inc_dirs] + [("-D%s" % d) for d in defs] diff --git a/build_files/cmake/cmake_static_check_sparse.py b/build_files/cmake/cmake_static_check_sparse.py index 06bef1a1327..8a3fb477239 100644 --- a/build_files/cmake/cmake_static_check_sparse.py +++ b/build_files/cmake/cmake_static_check_sparse.py @@ -47,7 +47,7 @@ def main(): for c, inc_dirs, defs in source_info: cmd = ([CHECKER_BIN] + - CHECKER_ARGS + + CHECKER_ARGS + [c] + [("-I%s" % i) for i in inc_dirs] + [("-D%s" % d) for d in defs] diff --git a/build_files/cmake/cmake_static_check_splint.py b/build_files/cmake/cmake_static_check_splint.py index 5b1207543f5..6ad03f2bdca 100644 --- a/build_files/cmake/cmake_static_check_splint.py +++ b/build_files/cmake/cmake_static_check_splint.py @@ -79,7 +79,7 @@ def main(): check_commands = [] for c, inc_dirs, defs in source_info: cmd = ([CHECKER_BIN] + - CHECKER_ARGS + + CHECKER_ARGS + [c] + [("-I%s" % i) for i in inc_dirs] + [("-D%s" % d) for d in defs] diff --git a/build_files/cmake/project_info.py b/build_files/cmake/project_info.py index e73b94a7051..73648be3f15 100755 --- a/build_files/cmake/project_info.py +++ b/build_files/cmake/project_info.py @@ -141,7 +141,7 @@ def cmake_advanced_info(): if sys.platform == "win32": cmd = 'cmake "%s" -G"Eclipse CDT4 - MinGW Makefiles"' % CMAKE_DIR else: - if make_exe_basename.startswith("make"): + if make_exe_basename.startswith(("make", "gmake")): cmd = 'cmake "%s" -G"Eclipse CDT4 - Unix Makefiles"' % CMAKE_DIR elif make_exe_basename.startswith("ninja"): cmd = 'cmake "%s" -G"Eclipse CDT4 - Ninja"' % CMAKE_DIR @@ -150,7 +150,6 @@ def cmake_advanced_info(): os.system(cmd) return join(CMAKE_DIR, ".cproject") - includes = [] defines = [] diff --git a/build_files/cmake/project_source_info.py b/build_files/cmake/project_source_info.py index 69d09b05ac7..90e240c35ef 100644 --- a/build_files/cmake/project_source_info.py +++ b/build_files/cmake/project_source_info.py @@ -86,15 +86,15 @@ def makefile_log(): make_exe = cmake_cache_var("CMAKE_MAKE_PROGRAM") make_exe_basename = os.path.basename(make_exe) - if make_exe_basename.startswith("make"): + if make_exe_basename.startswith(("make", "gmake")): print("running 'make' with --dry-run ...") process = subprocess.Popen([make_exe, "--always-make", "--dry-run", "--keep-going", "VERBOSE=1"], - stdout=subprocess.PIPE, + stdout=subprocess.PIPE, ) elif make_exe_basename.startswith("ninja"): print("running 'ninja' with -t commands ...") process = subprocess.Popen([make_exe, "-t", "commands"], - stdout=subprocess.PIPE, + stdout=subprocess.PIPE, ) while process.poll(): diff --git a/build_files/scons/config/Modules/FindPython.py b/build_files/scons/config/Modules/FindPython.py index c93a10351d5..01215753cf7 100644 --- a/build_files/scons/config/Modules/FindPython.py +++ b/build_files/scons/config/Modules/FindPython.py @@ -15,6 +15,13 @@ def FindPython(): abi_flags = cur_flags break + # Find config.h. In some distros, such as ubuntu 12.10 they are not in standard include dir. + incconf64 = os.path.join(include, "x86_64-linux-gnu", "python" + version + cur_flags, "pyconfig.h") + if os.path.exists(incconf64): + incconf = os.path.join(include, "x86_64-linux-gnu", "python" + version + cur_flags) + else: + incconf = '' + # Determine whether python is in /usr/lib or /usr/lib64 lib32 = os.path.join(python, "lib", "python" + version, "sysconfig.py") lib64 = os.path.join(python, "lib64", "python" + version, "sysconfig.py") @@ -29,4 +36,5 @@ def FindPython(): return {'PYTHON': python, "VERSION": version, 'LIBPATH': libpath, - 'ABI_FLAGS': abi_flags} + 'ABI_FLAGS': abi_flags, + 'CONFIG': incconf} diff --git a/build_files/scons/config/linux-config.py b/build_files/scons/config/linux-config.py index 05d846d7433..22e82662ae7 100644 --- a/build_files/scons/config/linux-config.py +++ b/build_files/scons/config/linux-config.py @@ -5,9 +5,10 @@ py = FindPython() BF_PYTHON_ABI_FLAGS = py['ABI_FLAGS'] BF_PYTHON = py['PYTHON'] BF_PYTHON_LIBPATH = py['LIBPATH'] +BF_PYTHON_CONFIG = py['CONFIG'] BF_PYTHON_VERSION = py['VERSION'] WITH_BF_STATICPYTHON = False -BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}${BF_PYTHON_ABI_FLAGS}' +BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}${BF_PYTHON_ABI_FLAGS} ' + BF_PYTHON_CONFIG BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}' BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}${BF_PYTHON_ABI_FLAGS}' # BF_PYTHON+'/lib/python'+BF_PYTHON_VERSION+'/config/libpython'+BF_PYTHON_VERSION+'.a' BF_PYTHON_LINKFLAGS = ['-Xlinker', '-export-dynamic'] @@ -193,7 +194,7 @@ BF_OCIO_LIB = 'OpenColorIO yaml-cpp tinyxml' BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a' BF_OCIO_LIBPATH = '${BF_OCIO}/lib' -WITH_BF_BOOST = False +WITH_BF_BOOST = True WITH_BF_STATICBOOST = False BF_BOOST = '/usr' BF_BOOST_INC = '${BF_BOOST}/include' diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py index 82d7350bfce..9a31ba650f5 100644 --- a/build_files/scons/tools/btools.py +++ b/build_files/scons/tools/btools.py @@ -108,7 +108,7 @@ def validate_arguments(args, bc): 'WITH_BF_STATICFFMPEG', 'BF_FFMPEG_LIB_STATIC', 'WITH_BF_OGG', 'BF_OGG', 'BF_OGG_LIB', 'WITH_BF_FRAMESERVER', - 'WITH_BF_COMPOSITOR', 'WITH_BF_COMPOSITOR_LEGACY', + 'WITH_BF_COMPOSITOR', 'WITH_BF_JPEG', 'BF_JPEG', 'BF_JPEG_INC', 'BF_JPEG_LIB', 'BF_JPEG_LIBPATH', 'WITH_BF_STATICJPEG', 'BF_JPEG_LIB_STATIC', 'WITH_BF_OPENJPEG', 'BF_OPENJPEG', 'BF_OPENJPEG_INC', 'BF_OPENJPEG_LIB', 'BF_OPENJPEG_LIBPATH', 'WITH_BF_REDCODE', 'BF_REDCODE', 'BF_REDCODE_INC', 'BF_REDCODE_LIB', 'BF_REDCODE_LIBPATH', @@ -602,7 +602,6 @@ def read_opts(env, cfg, args): ('BF_BOOST_LIB_STATIC', 'Boost static library', ''), (BoolVariable('WITH_GHOST_XDND', 'Build with drag-n-drop support on Linux platforms using XDND protocol', True)), - (BoolVariable('WITH_BF_COMPOSITOR_LEGACY', 'Enable the legacy compositor', False)), (BoolVariable('WITH_BF_CYCLES_OSL', 'Build with OSL sypport in Cycles', False)), (BoolVariable('WITH_BF_STATICOSL', 'Staticly link to OSL', False)), diff --git a/doc/python_api/examples/bpy.props.5.py b/doc/python_api/examples/bpy.props.5.py index e49d0f2a0a0..1f61e33c30f 100644 --- a/doc/python_api/examples/bpy.props.5.py +++ b/doc/python_api/examples/bpy.props.5.py @@ -16,6 +16,7 @@ import bpy def get_float(self): return self["testprop"] + def set_float(self, value): self["testprop"] = value @@ -36,6 +37,7 @@ bpy.types.Scene.test_date = bpy.props.StringProperty(get=get_date) def get_array(self): return (True, self["somebool"]) + def set_array(self, values): self["somebool"] = values[0] and values[1] @@ -51,10 +53,12 @@ test_items = [ ("YELLOW", "Red", "", 4), ] + def get_enum(self): import random return random.randint(1, 4) + def set_enum(self, value): print("setting value", value) @@ -66,16 +70,16 @@ bpy.types.Scene.test_enum = bpy.props.EnumProperty(items=test_items, get=get_enu scene = bpy.context.scene scene.test_float = 12.34 -print (scene.test_float) +print(scene.test_float) scene.test_array = (True, False) -print ([x for x in scene.test_array]) +print([x for x in scene.test_array]) #scene.test_date = "blah" # this would fail, property is read-only -print (scene.test_date) +print(scene.test_date) scene.test_enum = 'BLUE' -print (scene.test_enum) +print(scene.test_enum) # >>> 12.34000015258789 diff --git a/doc/python_api/examples/bpy.types.AddonPreferences.1.py b/doc/python_api/examples/bpy.types.AddonPreferences.1.py index 08de6f4f5a9..73f90acb3fa 100644 --- a/doc/python_api/examples/bpy.types.AddonPreferences.1.py +++ b/doc/python_api/examples/bpy.types.AddonPreferences.1.py @@ -17,6 +17,8 @@ from bpy.props import StringProperty, IntProperty, BoolProperty class ExampleAddonPreferences(AddonPreferences): + # this must match the addon name, use '__package__' + # when defining this in a submodule of a python package. bl_idname = __name__ filepath = StringProperty( diff --git a/doc/python_api/examples/bpy.types.UIList.py b/doc/python_api/examples/bpy.types.UIList.py index f2017e3883d..a37bbff726a 100644 --- a/doc/python_api/examples/bpy.types.UIList.py +++ b/doc/python_api/examples/bpy.types.UIList.py @@ -86,4 +86,4 @@ def unregister(): if __name__ == "__main__": - register() \ No newline at end of file + register() diff --git a/doc/python_api/rst/info_tutorial_addon.rst b/doc/python_api/rst/info_tutorial_addon.rst index 2a101041227..5637cf2f638 100644 --- a/doc/python_api/rst/info_tutorial_addon.rst +++ b/doc/python_api/rst/info_tutorial_addon.rst @@ -486,16 +486,14 @@ using :kbd:`Ctrl-Shift-Space` as the key shortcut to activate it. kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True) kmi.properties.total = 4 - addon_keymaps.append(km) + addon_keymaps.append((km, kmi)) def unregister(): # handle the keymap - wm = bpy.context.window_manager - for km in addon_keymaps: - wm.keyconfigs.addon.keymaps.remove(km) - # clear the list + for km, kmi in addon_keymaps: + km.keymap_items.remove(kmi) addon_keymaps.clear() @@ -568,18 +566,16 @@ Bringing it all together km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY') kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True) kmi.properties.total = 4 - addon_keymaps.append(km) + addon_keymaps.append((km, kmi)) def unregister(): bpy.utils.unregister_class(ObjectCursorArray) bpy.types.VIEW3D_MT_object.remove(menu_func) # handle the keymap - wm = bpy.context.window_manager - for km in addon_keymaps: - wm.keyconfigs.addon.keymaps.remove(km) - # clear the list - del addon_keymaps[:] + for km, kmi in addon_keymaps: + km.keymap_items.remove(kmi) + addon_keymaps.clear() if __name__ == "__main__": diff --git a/doc/python_api/rst_from_bmesh_opdefines.py b/doc/python_api/rst_from_bmesh_opdefines.py index c1b6643389d..3776ef7ce56 100644 --- a/doc/python_api/rst_from_bmesh_opdefines.py +++ b/doc/python_api/rst_from_bmesh_opdefines.py @@ -65,10 +65,10 @@ def main(): fsrc = open(FILE_OP_DEFINES_C, 'r', encoding="utf-8") blocks = [] - + is_block = False is_comment = False # /* global comments only */ - + comment_ctx = None block_ctx = None @@ -82,7 +82,7 @@ def main(): elif l.strip().startswith("/*"): is_comment = True comment_ctx = [] - + if is_block: if l.strip().startswith("//"): pass @@ -93,11 +93,11 @@ def main(): l = l[:cpp_comment] block_ctx.append(l) - + if l.strip() == "};": is_block = False comment_ctx = None - + if is_comment: c_comment_start = l.find("/*") if c_comment_start != -1: @@ -113,7 +113,6 @@ def main(): fsrc.close() del fsrc - # namespace hack vars = ( "BMO_OP_SLOT_ELEMENT_BUF", @@ -124,7 +123,7 @@ def main(): "BMO_OP_SLOT_VEC", "BMO_OP_SLOT_PTR", "BMO_OP_SLOT_MAPPING", - + "BMO_OP_SLOT_SUBTYPE_MAP_ELEM", "BMO_OP_SLOT_SUBTYPE_MAP_BOOL", "BMO_OP_SLOT_SUBTYPE_MAP_INT", @@ -157,23 +156,23 @@ def main(): for comment, b in blocks: # magic, translate into python b[0] = b[0].replace("static BMOpDefine ", "") - + for i, l in enumerate(b): l = l.strip() l = l.replace("{", "(") l = l.replace("}", ")") - + if l.startswith("/*"): l = l.replace("/*", "'''own <") else: l = l.replace("/*", "'''inline <") l = l.replace("*/", ">''',") - + # exec func. eg: bmo_rotate_edges_exec, if l.startswith("bmo_") and l.endswith("_exec,"): l = "None," b[i] = l - + #for l in b: # print(l) @@ -182,7 +181,7 @@ def main(): "__file__": "generated", "__name__": "__main__", } - + global_namespace.update(vars_dict) text_a, text_b = text.split("=", 1) @@ -191,7 +190,6 @@ def main(): # print(global_namespace["result"]) blocks_py.append((comment, global_namespace["result"])) - # --------------------- # Now convert into rst. fout = open(OUT_RST, 'w', encoding="utf-8") @@ -217,7 +215,7 @@ def main(): args_out_index[:] = [i for (i, a) in enumerate(args_out) if type(a) == tuple] fw(".. function:: %s(bm, %s)\n\n" % (b[0], ", ".join([args_in[i][0] for i in args_in_index]))) - + # -- wash the comment comment_washed = [] for i, l in enumerate(comment): @@ -236,7 +234,6 @@ def main(): fw("\n") # -- done - # get the args def get_args_wash(args, args_index, is_ret): args_wash = [] @@ -268,7 +265,7 @@ def main(): comment_next = comment_next[8:-1] # strip inline <...> else: comment_next = "" - + comment = "" if comment_prev: comment += comment_prev.strip() @@ -304,18 +301,21 @@ def main(): elif tp == BMO_OP_SLOT_ELEMENT_BUF: assert(tp_sub is not None) - + ls = [] - if tp_sub & BM_VERT: ls.append(":class:`bmesh.types.BMVert`") - if tp_sub & BM_EDGE: ls.append(":class:`bmesh.types.BMEdge`") - if tp_sub & BM_FACE: ls.append(":class:`bmesh.types.BMFace`") + if tp_sub & BM_VERT: + ls.append(":class:`bmesh.types.BMVert`") + if tp_sub & BM_EDGE: + ls.append(":class:`bmesh.types.BMEdge`") + if tp_sub & BM_FACE: + ls.append(":class:`bmesh.types.BMFace`") assert(ls) # must be at least one if tp_sub & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE: tp_str = "/".join(ls) else: tp_str = ("list of (%s)" % ", ".join(ls)) - + del ls elif tp == BMO_OP_SLOT_MAPPING: if tp_sub & BMO_OP_SLOT_SUBTYPE_MAP_EMPTY: @@ -356,21 +356,21 @@ def main(): fw(" :arg %s: %s\n" % (name, comment)) fw(" :type %s: %s\n" % (name, tp)) - + if args_out_wash: fw(" :return:\n\n") - + for (name, tp, comment) in args_out_wash: assert(name.endswith(".out")) name = name[:-4] fw(" - ``%s``: %s\n\n" % (name, comment)) fw(" **type** %s\n" % tp) - + fw("\n") fw(" :rtype: dict with string keys\n") fw("\n\n") - + fout.close() del fout print(OUT_RST) diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 89659c10add..4311ae56f8e 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -614,10 +614,10 @@ def pyfunc2sphinx(ident, fw, identifier, py_func, is_class=True): ''' function or class method to sphinx ''' - + if type(py_func) == type(bpy.types.Space.draw_handler_add): return - + arg_str = inspect.formatargspec(*inspect.getargspec(py_func)) if not is_class: @@ -992,6 +992,7 @@ context_type_map = { "world": ("World", False), } + def pycontext2sphinx(basepath): # Only use once. very irregular @@ -1019,7 +1020,6 @@ def pycontext2sphinx(basepath): "sequencer_context_dir", ) - unique = set() blend_cdll = ctypes.CDLL("") for ctx_str in context_strings: diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp index 0a3d0f8e85a..831e1998182 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp @@ -107,7 +107,7 @@ void AUD_FFMPEGReader::init() m_position = 0; m_pkgbuf_left = 0; - if(av_find_stream_info(m_formatCtx)<0) + if(avformat_find_stream_info(m_formatCtx, NULL) < 0) AUD_THROW(AUD_ERROR_FFMPEG, streaminfo_error); // find audio stream and codec @@ -133,7 +133,7 @@ void AUD_FFMPEGReader::init() if(!aCodec) AUD_THROW(AUD_ERROR_FFMPEG, nodecoder_error); - if(avcodec_open(m_codecCtx, aCodec)<0) + if(avcodec_open2(m_codecCtx, aCodec, NULL) < 0) AUD_THROW(AUD_ERROR_FFMPEG, codecopen_error); // XXX this prints file information to stdout: @@ -236,14 +236,7 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(boost::shared_ptr buffer) : AUD_FFMPEGReader::~AUD_FFMPEGReader() { avcodec_close(m_codecCtx); - - if(m_aviocontext) - { - avformat_close_input(&m_formatCtx); - av_free(m_aviocontext); - } - else - av_close_input_file(m_formatCtx); + avformat_close_input(&m_formatCtx); } int AUD_FFMPEGReader::read_packet(void* opaque, uint8_t* buf, int buf_size) diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp index 2b34348da81..55040e4db8e 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp @@ -55,10 +55,15 @@ AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs, { static const char* formats[] = { NULL, "ac3", "flac", "matroska", "mp2", "mp3", "ogg", "wav" }; - if(avformat_alloc_output_context2(&m_formatCtx, NULL, formats[format], filename.c_str())) - AUD_THROW(AUD_ERROR_FFMPEG, context_error); + m_formatCtx = avformat_alloc_context(); + if (!m_formatCtx) AUD_THROW(AUD_ERROR_FFMPEG, context_error); - m_outputFmt = m_formatCtx->oformat; + strcpy(m_formatCtx->filename, filename.c_str()); + m_outputFmt = m_formatCtx->oformat = av_guess_format(formats[format], filename.c_str(), NULL); + if (!m_outputFmt) { + avformat_free_context(m_formatCtx); + AUD_THROW(AUD_ERROR_FFMPEG, context_error); + } switch(codec) { @@ -116,7 +121,7 @@ AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs, if(m_outputFmt->audio_codec == CODEC_ID_NONE) AUD_THROW(AUD_ERROR_SPECS, codec_error); - m_stream = av_new_stream(m_formatCtx, 0); + m_stream = avformat_new_stream(m_formatCtx, NULL); if(!m_stream) AUD_THROW(AUD_ERROR_FFMPEG, stream_error); @@ -164,7 +169,7 @@ AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs, if(!codec) AUD_THROW(AUD_ERROR_FFMPEG, codec_error); - if(avcodec_open(m_codecCtx, codec)) + if(avcodec_open2(m_codecCtx, codec, NULL)) AUD_THROW(AUD_ERROR_FFMPEG, codec_error); m_output_buffer.resize(FF_MIN_BUFFER_SIZE); diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index 3242acf3edd..048a2a50a7f 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -47,10 +47,6 @@ if(WITH_CYCLES_OSL) include_directories(${OSL_INCLUDES}) endif() -if(WITH_CYCLES_CUDA_BINARIES) - add_definitions(-DWITH_CUDA_BINARIES) -endif() - add_definitions(-DWITH_OPENCL) add_definitions(-DWITH_CUDA) add_definitions(-DWITH_MULTI) diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript index dcb684c4be7..44a17ac0cd6 100644 --- a/intern/cycles/SConscript +++ b/intern/cycles/SConscript @@ -53,9 +53,6 @@ if env['WITH_BF_CYCLES_OSL']: defs.append('WITH_OSL') incs.append(cycles['BF_OSL_INC']) -if env['WITH_BF_CYCLES_CUDA_BINARIES']: - defs.append('WITH_CUDA_BINARIES') - incs.extend('. bvh render device kernel kernel/osl kernel/svm util subd'.split()) incs.extend('#intern/guardedalloc #source/blender/makesrna #source/blender/makesdna'.split()) incs.extend('#source/blender/blenloader ../../source/blender/makesrna/intern'.split()) diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index 5de9d71b8cc..40fbb7af556 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -233,16 +233,16 @@ static void xml_read_film(const XMLReadState& state, pugi::xml_node node) float aspect = (float)cam->width/(float)cam->height; if(cam->width >= cam->height) { - cam->left = -aspect; - cam->right = aspect; - cam->bottom = -1.0f; - cam->top = 1.0f; + cam->viewplane.left = -aspect; + cam->viewplane.right = aspect; + cam->viewplane.bottom = -1.0f; + cam->viewplane.top = 1.0f; } else { - cam->left = -1.0f; - cam->right = 1.0f; - cam->bottom = -1.0f/aspect; - cam->top = 1.0f/aspect; + cam->viewplane.left = -1.0f; + cam->viewplane.right = 1.0f; + cam->viewplane.bottom = -1.0f/aspect; + cam->viewplane.top = 1.0f/aspect; } cam->need_update = true; diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py index dddf7bafb14..36fb5c0418d 100644 --- a/intern/cycles/blender/addon/__init__.py +++ b/intern/cycles/blender/addon/__init__.py @@ -34,13 +34,13 @@ import bpy from . import engine + class CyclesRender(bpy.types.RenderEngine): bl_idname = 'CYCLES' bl_label = "Cycles Render" bl_use_shading_nodes = True def __init__(self): - engine.init() self.session = None def __del__(self): @@ -69,7 +69,7 @@ class CyclesRender(bpy.types.RenderEngine): def view_update(self, context): if not self.session: engine.create(self, context.blend_data, context.scene, - context.region, context.space_data, context.region_data) + context.region, context.space_data, context.region_data) engine.update(self, context.blend_data, context.scene) def view_draw(self, context): @@ -88,6 +88,8 @@ def register(): from . import properties from . import presets + engine.init() + properties.register() ui.register() presets.register() @@ -103,4 +105,3 @@ def unregister(): properties.unregister() presets.unregister() bpy.utils.unregister_module(__name__) - diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index 9641128d994..ef700ba26f1 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -18,6 +18,7 @@ # + def init(): import bpy import _cycles @@ -89,4 +90,3 @@ def available_devices(): def with_osl(): import _cycles return _cycles.with_osl - diff --git a/intern/cycles/blender/addon/osl.py b/intern/cycles/blender/addon/osl.py index 79ce3df20c3..0a67edac1e3 100644 --- a/intern/cycles/blender/addon/osl.py +++ b/intern/cycles/blender/addon/osl.py @@ -18,10 +18,13 @@ # -import bpy, _cycles, os, tempfile +import bpy +import _cycles + -# compile .osl file with given filepath to temporary .oso file def osl_compile(input_path, report): + """compile .osl file with given filepath to temporary .oso file""" + import tempfile output_file = tempfile.NamedTemporaryFile(mode='w', suffix=".oso", delete=False) output_path = output_file.name output_file.close() @@ -33,9 +36,12 @@ def osl_compile(input_path, report): return ok, output_path -# compile and update shader script node + def update_script_node(node, report): - import os, shutil + """compile and update shader script node""" + import os + import shutil + import tempfile if node.mode == 'EXTERNAL': # compile external script file @@ -103,7 +109,7 @@ def update_script_node(node, report): report({'ERROR'}, "Can't read OSO bytecode to store in node at %r" % oso_path) ok = False - + else: report({'WARNING'}, "No text or file specified in node, nothing to compile") return @@ -125,4 +131,3 @@ def update_script_node(node, report): pass return ok - diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 8b90b0bd4ff..3661274ae43 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -74,13 +74,14 @@ enum_curve_presets = ( enum_curve_primitives = ( ('TRIANGLES', "Triangles", "Create triangle geometry around strands"), ('LINE_SEGMENTS', "Line Segments", "Use line segment primitives"), - ('CURVE_SEGMENTS', "?Curve Segments?", "Use curve segment primitives (not implemented)"), + ('CURVE_SEGMENTS', "Curve Segments", "Use segmented cardinal curve primitives"), + ('CURVE_RIBBONS', "Curve Ribbons", "Use smooth cardinal curve ribbon primitives"), ) enum_triangle_curves = ( - ('CAMERA', "Planes", "Create individual triangles forming planes that face camera"), - ('RIBBONS', "Ribbons", "Create individual triangles forming ribbon"), - ('TESSELLATED', "Tessellated", "Create mesh surrounding each strand"), + ('CAMERA_TRIANGLES', "Planes", "Create individual triangles forming planes that face camera"), + ('RIBBON_TRIANGLES', "Ribbons", "Create individual triangles forming ribbon"), + ('TESSELLATED_TRIANGLES', "Tessellated", "Create mesh surrounding each strand"), ) enum_line_curves = ( @@ -95,7 +96,7 @@ enum_curves_interpolation = ( ('CARDINAL', "Cardinal interpolation", "Use cardinal interpolation between segments"), ('BSPLINE', "B-spline interpolation", "Use b-spline interpolation between segments"), ) - + enum_tile_order = ( ('CENTER', "Center", "Render from center to the edges"), ('RIGHT_TO_LEFT', "Right to Left", "Render from right to left"), @@ -104,6 +105,7 @@ enum_tile_order = ( ('BOTTOM_TO_TOP', "Bottom to Top", "Render from bottom to top"), ) + class CyclesRenderSettings(bpy.types.PropertyGroup): @classmethod def register(cls): @@ -619,6 +621,7 @@ class CyclesMeshSettings(bpy.types.PropertyGroup): del bpy.types.Curve.cycles del bpy.types.MetaBall.cycles + class CyclesCurveRenderSettings(bpy.types.PropertyGroup): @classmethod def register(cls): @@ -643,7 +646,7 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup): name="Mesh Geometry", description="Method for creating triangle geometry", items=enum_triangle_curves, - default='CAMERA', + default='CAMERA_TRIANGLES', ) cls.line_method = EnumProperty( name="Intersection Method", @@ -682,10 +685,6 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup): description="Correct the tangent normal for the strand's slope", default=False, ) - cls.use_cache = BoolProperty( - name="Export Cached data", - default=True, - ) cls.use_parents = BoolProperty( name="Use parent strands", description="Use parents with children", @@ -705,7 +704,7 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup): name="Use Cycles Hair Rendering", description="Activate Cycles hair rendering for particle system", default=True, - ) + ) cls.segments = IntProperty( name="Segments", description="Number of segments between path keys (note that this combines with the 'draw step' value)", @@ -730,11 +729,18 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup): min=0, max=100.0, default=1.01, ) + cls.subdivisions = IntProperty( + name="Subdivisions", + description="Number of subdivisions used in Cardinal curve intersection (power of 2)", + min=0, max=24, + default=3, + ) @classmethod def unregister(cls): del bpy.types.Scene.cycles_curves + class CyclesCurveSettings(bpy.types.PropertyGroup): @classmethod def register(cls): @@ -771,6 +777,7 @@ class CyclesCurveSettings(bpy.types.PropertyGroup): def unregister(cls): del bpy.types.ParticleSettings.cycles + def register(): bpy.utils.register_class(CyclesRenderSettings) bpy.utils.register_class(CyclesCameraSettings) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 6a3a0c63236..ccc2a0ecbda 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -976,84 +976,96 @@ class CyclesParticle_PT_textures(CyclesButtonsPanel, Panel): slot = part.texture_slots[part.active_texture_index] layout.template_ID(slot, "texture", new="texture.new") + class CyclesRender_PT_CurveRendering(CyclesButtonsPanel, Panel): bl_label = "Cycles Hair Rendering" bl_context = "particle" - + @classmethod def poll(cls, context): + scene = context.scene + cscene = scene.cycles psys = context.particle_system device_type = context.user_preferences.system.compute_device_type - experimental = context.scene.cycles.feature_set == 'EXPERIMENTAL' and (context.scene.cycles.device == 'CPU' or device_type == 'NONE') + experimental = ((cscene.feature_set == 'EXPERIMENTAL') and (cscene.device == 'CPU' or device_type == 'NONE')) return CyclesButtonsPanel.poll(context) and experimental and psys - + def draw_header(self, context): - cscene = context.scene.cycles_curves - self.layout.prop(cscene, "use_curves", text="") - + ccscene = context.scene.cycles_curves + self.layout.prop(ccscene, "use_curves", text="") + def draw(self, context): layout = self.layout - + scene = context.scene - cscene = scene.cycles_curves - - layout.active = cscene.use_curves - - layout.prop(cscene, "preset", text="Mode") - - if cscene.preset == 'CUSTOM': - layout.prop(cscene, "primitive", text="Primitive") - - if cscene.primitive == 'TRIANGLES': - layout.prop(cscene, "triangle_method", text="Method") - if cscene.triangle_method == 'TESSELLATED': - layout.prop(cscene, "resolution", text="Resolution") - layout.prop(cscene, "use_smooth", text="Smooth") - elif cscene.primitive == 'LINE_SEGMENTS': - layout.prop(cscene, "use_backfacing", text="Check back-faces") - + ccscene = scene.cycles_curves + + layout.active = ccscene.use_curves + + layout.prop(ccscene, "preset", text="Mode") + + if ccscene.preset == 'CUSTOM': + layout.prop(ccscene, "primitive", text="Primitive") + + if ccscene.primitive == 'TRIANGLES': + layout.prop(ccscene, "triangle_method", text="Method") + if ccscene.triangle_method == 'TESSELLATED_TRIANGLES': + layout.prop(ccscene, "resolution", text="Resolution") + layout.prop(ccscene, "use_smooth", text="Smooth") + elif ccscene.primitive == 'LINE_SEGMENTS': + layout.prop(ccscene, "use_backfacing", text="Check back-faces") + row = layout.row() - row.prop(cscene, "use_encasing", text="Exclude encasing") + row.prop(ccscene, "use_encasing", text="Exclude encasing") sub = row.row() - sub.active = cscene.use_encasing - sub.prop(cscene, "encasing_ratio", text="Ratio for encasing") - - layout.prop(cscene, "line_method", text="Method") - layout.prop(cscene, "use_tangent_normal", text="Use tangent normal as default") - layout.prop(cscene, "use_tangent_normal_geometry", text="Use tangent normal geometry") - layout.prop(cscene, "use_tangent_normal_correction", text="Correct tangent normal for slope") - layout.prop(cscene, "interpolation", text="Interpolation") - + sub.active = ccscene.use_encasing + sub.prop(ccscene, "encasing_ratio", text="Ratio for encasing") + + layout.prop(ccscene, "line_method", text="Method") + layout.prop(ccscene, "use_tangent_normal", text="Use tangent normal as default") + layout.prop(ccscene, "use_tangent_normal_geometry", text="Use tangent normal geometry") + layout.prop(ccscene, "use_tangent_normal_correction", text="Correct tangent normal for slope") + layout.prop(ccscene, "interpolation", text="Interpolation") + row = layout.row() - row.prop(cscene, "segments", text="Segments") - row.prop(cscene, "normalmix", text="Ray Mix") - + row.prop(ccscene, "segments", text="Segments") + row.prop(ccscene, "normalmix", text="Ray Mix") + elif ccscene.primitive in {'CURVE_SEGMENTS', 'CURVE_RIBBONS'}: + layout.prop(ccscene, "subdivisions", text="Curve subdivisions") + layout.prop(ccscene, "use_backfacing", text="Check back-faces") + + layout.prop(ccscene, "interpolation", text="Interpolation") + row = layout.row() + row.prop(ccscene, "segments", text="Segments") + row = layout.row() - row.prop(cscene, "use_cache", text="Export cache with children") - if cscene.use_cache: - row.prop(cscene, "use_parents", text="Include parents") - + row.prop(ccscene, "use_parents", text="Include parents") + + class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel): bl_label = "Cycles Hair Settings" bl_context = "particle" - + @classmethod def poll(cls, context): - use_curves = context.scene.cycles_curves.use_curves and context.particle_system + scene = context.scene + cscene = scene.cycles + ccscene = scene.cycles_curves + use_curves = ccscene.use_curves and context.particle_system device_type = context.user_preferences.system.compute_device_type - experimental = context.scene.cycles.feature_set == 'EXPERIMENTAL' and (context.scene.cycles.device == 'CPU' or device_type == 'NONE') + experimental = cscene.feature_set == 'EXPERIMENTAL' and (cscene.device == 'CPU' or device_type == 'NONE') return CyclesButtonsPanel.poll(context) and experimental and use_curves def draw(self, context): layout = self.layout - + psys = context.particle_settings cpsys = psys.cycles - + row = layout.row() row.prop(cpsys, "shape", text="Shape") row.prop(cpsys, "use_closetip", text="Close tip") - + layout.label(text="Width multiplier:") row = layout.row() row.prop(cpsys, "root_width", text="Root") @@ -1120,74 +1132,79 @@ def draw_pause(self, context): def get_panels(): + types = bpy.types return ( - bpy.types.RENDER_PT_render, - bpy.types.RENDER_PT_output, - bpy.types.RENDER_PT_encoding, - bpy.types.RENDER_PT_dimensions, - bpy.types.RENDER_PT_stamp, - bpy.types.SCENE_PT_scene, - bpy.types.SCENE_PT_audio, - bpy.types.SCENE_PT_unit, - bpy.types.SCENE_PT_keying_sets, - bpy.types.SCENE_PT_keying_set_paths, - bpy.types.SCENE_PT_physics, - bpy.types.WORLD_PT_context_world, - bpy.types.DATA_PT_context_mesh, - bpy.types.DATA_PT_context_camera, - bpy.types.DATA_PT_context_lamp, - bpy.types.DATA_PT_context_speaker, - bpy.types.DATA_PT_texture_space, - bpy.types.DATA_PT_curve_texture_space, - bpy.types.DATA_PT_mball_texture_space, - bpy.types.DATA_PT_vertex_groups, - bpy.types.DATA_PT_shape_keys, - bpy.types.DATA_PT_uv_texture, - bpy.types.DATA_PT_vertex_colors, - bpy.types.DATA_PT_camera, - bpy.types.DATA_PT_camera_display, - bpy.types.DATA_PT_lens, - bpy.types.DATA_PT_speaker, - bpy.types.DATA_PT_distance, - bpy.types.DATA_PT_cone, - bpy.types.DATA_PT_customdata, - bpy.types.DATA_PT_custom_props_mesh, - bpy.types.DATA_PT_custom_props_camera, - bpy.types.DATA_PT_custom_props_lamp, - bpy.types.DATA_PT_custom_props_speaker, - bpy.types.TEXTURE_PT_clouds, - bpy.types.TEXTURE_PT_wood, - bpy.types.TEXTURE_PT_marble, - bpy.types.TEXTURE_PT_magic, - bpy.types.TEXTURE_PT_blend, - bpy.types.TEXTURE_PT_stucci, - bpy.types.TEXTURE_PT_image, - bpy.types.TEXTURE_PT_image_sampling, - bpy.types.TEXTURE_PT_image_mapping, - bpy.types.TEXTURE_PT_musgrave, - bpy.types.TEXTURE_PT_voronoi, - bpy.types.TEXTURE_PT_distortednoise, - bpy.types.TEXTURE_PT_voxeldata, - bpy.types.TEXTURE_PT_pointdensity, - bpy.types.TEXTURE_PT_pointdensity_turbulence, - bpy.types.TEXTURE_PT_mapping, - bpy.types.TEXTURE_PT_influence, - bpy.types.TEXTURE_PT_colors, - bpy.types.PARTICLE_PT_context_particles, - bpy.types.PARTICLE_PT_emission, - bpy.types.PARTICLE_PT_hair_dynamics, - bpy.types.PARTICLE_PT_cache, - bpy.types.PARTICLE_PT_velocity, - bpy.types.PARTICLE_PT_rotation, - bpy.types.PARTICLE_PT_physics, - bpy.types.PARTICLE_PT_boidbrain, - bpy.types.PARTICLE_PT_render, - bpy.types.PARTICLE_PT_draw, - bpy.types.PARTICLE_PT_children, - bpy.types.PARTICLE_PT_field_weights, - bpy.types.PARTICLE_PT_force_fields, - bpy.types.PARTICLE_PT_vertexgroups, - bpy.types.PARTICLE_PT_custom_props, + types.RENDER_PT_render, + types.RENDER_PT_output, + types.RENDER_PT_encoding, + types.RENDER_PT_dimensions, + types.RENDER_PT_stamp, + types.SCENE_PT_scene, + types.SCENE_PT_color_management, + types.SCENE_PT_audio, + types.SCENE_PT_unit, + types.SCENE_PT_keying_sets, + types.SCENE_PT_keying_set_paths, + types.SCENE_PT_physics, + types.WORLD_PT_context_world, + types.DATA_PT_context_mesh, + types.DATA_PT_context_camera, + types.DATA_PT_context_lamp, + types.DATA_PT_context_speaker, + types.DATA_PT_texture_space, + types.DATA_PT_curve_texture_space, + types.DATA_PT_mball_texture_space, + types.DATA_PT_vertex_groups, + types.DATA_PT_shape_keys, + types.DATA_PT_uv_texture, + types.DATA_PT_vertex_colors, + types.DATA_PT_camera, + types.DATA_PT_camera_display, + types.DATA_PT_lens, + types.DATA_PT_speaker, + types.DATA_PT_distance, + types.DATA_PT_cone, + types.DATA_PT_customdata, + types.DATA_PT_custom_props_mesh, + types.DATA_PT_custom_props_camera, + types.DATA_PT_custom_props_lamp, + types.DATA_PT_custom_props_speaker, + types.TEXTURE_PT_clouds, + types.TEXTURE_PT_wood, + types.TEXTURE_PT_marble, + types.TEXTURE_PT_magic, + types.TEXTURE_PT_blend, + types.TEXTURE_PT_stucci, + types.TEXTURE_PT_image, + types.TEXTURE_PT_image_sampling, + types.TEXTURE_PT_image_mapping, + types.TEXTURE_PT_musgrave, + types.TEXTURE_PT_voronoi, + types.TEXTURE_PT_distortednoise, + types.TEXTURE_PT_voxeldata, + types.TEXTURE_PT_pointdensity, + types.TEXTURE_PT_pointdensity_turbulence, + types.TEXTURE_PT_mapping, + types.TEXTURE_PT_influence, + types.TEXTURE_PT_colors, + types.PARTICLE_PT_context_particles, + types.PARTICLE_PT_emission, + types.PARTICLE_PT_hair_dynamics, + types.PARTICLE_PT_cache, + types.PARTICLE_PT_velocity, + types.PARTICLE_PT_rotation, + types.PARTICLE_PT_physics, + types.SCENE_PT_rigid_body_world, + types.SCENE_PT_rigid_body_cache, + types.SCENE_PT_rigid_body_field_weights, + types.PARTICLE_PT_boidbrain, + types.PARTICLE_PT_render, + types.PARTICLE_PT_draw, + types.PARTICLE_PT_children, + types.PARTICLE_PT_field_weights, + types.PARTICLE_PT_force_fields, + types.PARTICLE_PT_vertexgroups, + types.PARTICLE_PT_custom_props, ) diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 41e1249dae7..cf2c018f1a2 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -37,8 +37,7 @@ void curveinterp_v3_v3v3v3v3(float3 *p, float3 *v1, float3 *v2, float3 *v3, floa void interp_weights(float t, float data[4], int type); float shaperadius(float shape, float root, float tip, float time); void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyloc, float *time, ParticleCurveData *CData, int interpolation); -bool ObtainParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData); -bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents); +bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents, int uv_num); bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents, int vcol_num); bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents); void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments, float3 RotCam); @@ -152,93 +151,6 @@ void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyl curveinterp_v3_v3v3v3v3(keyloc, &ckey_loc1, &ckey_loc2, &ckey_loc3, &ckey_loc4, t); } -bool ObtainParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData) -{ - - int curvenum = 0; - int keyno = 0; - - if(!(mesh && b_mesh && b_ob && CData)) - return false; - - BL::Object::modifiers_iterator b_mod; - for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) { - if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) { - - BL::ParticleSystemModifier psmd(b_mod->ptr); - - BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr); - - BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr); - - if((b_psys.settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys.settings().type()==BL::ParticleSettings::type_HAIR)) { - - int mi = clamp(b_psys.settings().material()-1, 0, mesh->used_shaders.size()-1); - int shader = mesh->used_shaders[mi]; - - int totcurves = b_psys.particles.length(); - - if(totcurves == 0) - continue; - - PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles"); - - CData->psys_firstcurve.push_back(curvenum); - CData->psys_curvenum.push_back(totcurves); - CData->psys_shader.push_back(shader); - - float radius = b_psys.settings().particle_size() * 0.5f; - - CData->psys_rootradius.push_back(radius * get_float(cpsys, "root_width")); - CData->psys_tipradius.push_back(radius * get_float(cpsys, "tip_width")); - CData->psys_shape.push_back(get_float(cpsys, "shape")); - CData->psys_closetip.push_back(get_boolean(cpsys, "use_closetip")); - - BL::ParticleSystem::particles_iterator b_pa; - for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) { - CData->curve_firstkey.push_back(keyno); - - int keylength = b_pa->hair_keys.length(); - CData->curve_keynum.push_back(keylength); - - float curve_length = 0.0f; - float3 pcKey; - int step_no = 0; - BL::Particle::hair_keys_iterator b_cKey; - for(b_pa->hair_keys.begin(b_cKey); b_cKey != b_pa->hair_keys.end(); ++b_cKey) { - float nco[3]; - b_cKey->co_object( *b_ob, psmd, *b_pa, nco); - float3 cKey = make_float3(nco[0],nco[1],nco[2]); - if(step_no > 0) - curve_length += len(cKey - pcKey); - CData->curvekey_co.push_back(cKey); - CData->curvekey_time.push_back(curve_length); - pcKey = cKey; - keyno++; - step_no++; - } - - CData->curve_length.push_back(curve_length); - /*add uvs*/ - BL::Mesh::tessface_uv_textures_iterator l; - b_mesh->tessface_uv_textures.begin(l); - - float3 uv = make_float3(0.0f, 0.0f, 0.0f); - if(b_mesh->tessface_uv_textures.length()) - b_pa->uv_on_emitter(psmd,&uv.x); - CData->curve_uv.push_back(uv); - - curvenum++; - - } - } - } - } - - return true; - -} - bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents) { @@ -328,7 +240,7 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par } -bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents) +bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents, int uv_num) { #if 0 int keyno = 0; @@ -342,6 +254,8 @@ bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Parti Transform itfm = transform_quick_inverse(tfm); #endif + CData->curve_uv.clear(); + BL::Object::modifiers_iterator b_mod; for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) { if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) { @@ -384,7 +298,7 @@ bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Parti float3 uv = make_float3(0.0f, 0.0f, 0.0f); if(b_mesh->tessface_uv_textures.length()) - b_psys.uv_on_emitter(psmd, *b_pa, pa_no, &uv.x); + b_psys.uv_on_emitter(psmd, *b_pa, pa_no, uv_num, &uv.x); CData->curve_uv.push_back(uv); if(pa_no < totparts && b_pa != b_psys.particles.end()) @@ -413,6 +327,8 @@ bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par Transform itfm = transform_quick_inverse(tfm); #endif + CData->curve_vcol.clear(); + BL::Object::modifiers_iterator b_mod; for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) { if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) { @@ -782,10 +698,8 @@ static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CDa if(!(mesh->curves.empty() && mesh->curve_keys.empty())) return; - Attribute *attr_uv = NULL, *attr_intercept = NULL; + Attribute *attr_intercept = NULL; - if(mesh->need_attribute(scene, ATTR_STD_UV)) - attr_uv = mesh->curve_attributes.add(ATTR_STD_UV); if(mesh->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT)) attr_intercept = mesh->curve_attributes.add(ATTR_STD_CURVE_INTERCEPT); @@ -831,9 +745,6 @@ static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CDa } mesh->add_curve(num_keys, num_curve_keys, CData->psys_shader[sys]); - if(attr_uv) - attr_uv->add(CData->curve_uv[curve]); - num_keys += num_curve_keys; num_curves++; } @@ -929,11 +840,11 @@ void BlenderSync::sync_curve_settings() curve_system_manager->resolution = get_int(csscene, "resolution"); curve_system_manager->segments = get_int(csscene, "segments"); curve_system_manager->use_smooth = get_boolean(csscene, "use_smooth"); + curve_system_manager->subdivisions = get_int(csscene, "subdivisions"); curve_system_manager->normalmix = get_float(csscene, "normalmix"); curve_system_manager->encasing_ratio = get_float(csscene, "encasing_ratio"); - curve_system_manager->use_cache = get_boolean(csscene, "use_cache"); curve_system_manager->use_parents = get_boolean(csscene, "use_parents"); curve_system_manager->use_encasing = get_boolean(csscene, "use_encasing"); curve_system_manager->use_backfacing = get_boolean(csscene, "use_backfacing"); @@ -947,7 +858,6 @@ void BlenderSync::sync_curve_settings() curve_system_manager->interpolation = CURVE_CARDINAL; curve_system_manager->normalmix = 1.0f; curve_system_manager->encasing_ratio = 1.01f; - curve_system_manager->use_cache = true; curve_system_manager->use_parents = false; curve_system_manager->segments = 1; curve_system_manager->use_joined = false; @@ -1028,7 +938,6 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool int resolution = scene->curve_system_manager->resolution; int segments = scene->curve_system_manager->segments; bool use_smooth = scene->curve_system_manager->use_smooth; - bool use_cache = scene->curve_system_manager->use_cache; bool use_parents = scene->curve_system_manager->use_parents; bool export_tgs = scene->curve_system_manager->use_joined; @@ -1036,12 +945,7 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool ParticleCurveData CData; - if(use_cache) { - ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, use_parents); - ObtainCacheParticleUV(mesh, &b_mesh, &b_ob, &CData, use_parents); - } - else - ObtainParticleData(mesh, &b_mesh, &b_ob, &CData); + ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, use_parents); /* attach strands to mesh */ BL::Object b_CamOb = b_scene.camera(); @@ -1055,11 +959,12 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool if(primitive == CURVE_TRIANGLES){ int vert_num = mesh->triangles.size() * 3; - if(triangle_method == CURVE_CAMERA) { + ObtainCacheParticleUV(mesh, &b_mesh, &b_ob, &CData, use_parents, 0); + if(triangle_method == CURVE_CAMERA_TRIANGLES) { ExportCurveTrianglePlanes(mesh, &CData, interpolation, use_smooth, segments, RotCam); ExportCurveTriangleUVs(mesh, &CData, interpolation, use_smooth, segments, vert_num, 1); } - else if(triangle_method == CURVE_RIBBONS) { + else if(triangle_method == CURVE_RIBBON_TRIANGLES) { ExportCurveTriangleRibbons(mesh, &CData, interpolation, use_smooth, segments); ExportCurveTriangleUVs(mesh, &CData, interpolation, use_smooth, segments, vert_num, 1); } @@ -1088,44 +993,74 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool /* generated coordinates from first key. we should ideally get this from * blender to handle deforming objects */ - if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) { - float3 loc, size; - mesh_texture_space(b_mesh, loc, size); + { + if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) { + float3 loc, size; + mesh_texture_space(b_mesh, loc, size); - Attribute *attr_generated = mesh->curve_attributes.add(ATTR_STD_GENERATED); - float3 *generated = attr_generated->data_float3(); - size_t i = 0; + Attribute *attr_generated = mesh->curve_attributes.add(ATTR_STD_GENERATED); + float3 *generated = attr_generated->data_float3(); + size_t i = 0; - foreach(Mesh::Curve& curve, mesh->curves) { - float3 co = mesh->curve_keys[curve.first_key].co; - generated[i++] = co*size - loc; + foreach(Mesh::Curve& curve, mesh->curves) { + float3 co = mesh->curve_keys[curve.first_key].co; + generated[i++] = co*size - loc; + } } } /* create vertex color attributes */ - BL::Mesh::tessface_vertex_colors_iterator l; - int vcol_num = 0; + { + BL::Mesh::tessface_vertex_colors_iterator l; + int vcol_num = 0; - for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l, vcol_num++) { - if(!mesh->need_attribute(scene, ustring(l->name().c_str()))) - continue; + for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l, vcol_num++) { + if(!mesh->need_attribute(scene, ustring(l->name().c_str()))) + continue; - /*error occurs with more than one vertex colour attribute so avoided*/ - if(vcol_num!=0) - break; + Attribute *attr_vcol = mesh->curve_attributes.add( + ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CURVE); - Attribute *attr_vcol = mesh->curve_attributes.add( - ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CURVE); + ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, use_parents, vcol_num); - ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, use_parents, 0); + float3 *vcol = attr_vcol->data_float3(); - float3 *vcol = attr_vcol->data_float3(); - - if(vcol) { - for(size_t curve = 0; curve < CData.curve_vcol.size() ;curve++) - vcol[curve] = color_srgb_to_scene_linear(CData.curve_vcol[curve]); + if(vcol) { + for(size_t curve = 0; curve < CData.curve_vcol.size() ;curve++) + vcol[curve] = color_srgb_to_scene_linear(CData.curve_vcol[curve]); + } } + } + /* create uv map attributes */ + { + BL::Mesh::tessface_uv_textures_iterator l; + int uv_num = 0; + + for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l, uv_num++) { + bool active_render = l->active_render(); + AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE; + ustring name = ustring(l->name().c_str()); + + /* UV map */ + if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) { + Attribute *attr; + + if(active_render) + attr = mesh->curve_attributes.add(std, name); + else + attr = mesh->curve_attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE); + + ObtainCacheParticleUV(mesh, &b_mesh, &b_ob, &CData, use_parents, uv_num); + + float3 *uv = attr->data_float3(); + + if(uv) { + for(size_t curve = 0; curve < CData.curve_uv.size() ;curve++) + uv[curve] = CData.curve_uv[curve]; + } + } + } } } diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index d0c7c06cbb3..3913323c21c 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -109,6 +109,11 @@ void BlenderSession::create_session() session->reset(buffer_params, session_params.samples); b_engine.use_highlight_tiles(session_params.progressive_refine == false); + + /* setup callbacks for builtin image support */ + scene->image_manager->builtin_image_info_cb = function_bind(&BlenderSession::builtin_image_info, this, _1, _2, _3, _4, _5); + scene->image_manager->builtin_image_pixels_cb = function_bind(&BlenderSession::builtin_image_pixels, this, _1, _2); + scene->image_manager->builtin_image_float_pixels_cb = function_bind(&BlenderSession::builtin_image_float_pixels, this, _1, _2); } void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_) @@ -607,5 +612,124 @@ void BlenderSession::test_cancel() session->progress.set_cancel("Cancelled"); } +/* builtin image file name is actually an image datablock name with + * absolute sequence frame number concatenated via '@' character + * + * this function splits image id name and frame number from a + * builtin image name + */ +void BlenderSession::builtin_name_split(const string &builtin_name, string &name, int &frame) +{ + int last = builtin_name.find_last_of('@'); + name = builtin_name.substr(0, last); + frame = atoi(builtin_name.substr(last + 1, builtin_name.size() - last - 1).c_str()); +} + +void BlenderSession::builtin_image_info(const string &builtin_name, bool &is_float, int &width, int &height, int &channels) +{ + string name; + int frame; + builtin_name_split(builtin_name, name, frame); + + BL::Image b_image = b_data.images[name]; + + if(b_image) { + is_float = b_image.is_float(); + width = b_image.size()[0]; + height = b_image.size()[1]; + channels = b_image.channels(); + } + else { + is_float = false; + width = 0; + height = 0; + channels = 0; + } +} + +bool BlenderSession::builtin_image_pixels(const string &builtin_name, unsigned char *pixels) +{ + string name; + int frame; + builtin_name_split(builtin_name, name, frame); + + BL::Image b_image = b_data.images[name]; + + if(b_image) { + int width = b_image.size()[0]; + int height = b_image.size()[1]; + int channels = b_image.channels(); + + unsigned char *image_pixels; + image_pixels = image_get_pixels_for_frame(b_image, frame); + + if(image_pixels) { + memcpy(pixels, image_pixels, width * height * channels * sizeof(unsigned char)); + MEM_freeN(image_pixels); + } + else { + if(channels == 1) { + memset(pixels, 0, width * height * sizeof(unsigned char)); + } + else { + unsigned char *cp = pixels; + for(int i = 0; i < width * height; i++, cp += channels) { + cp[0] = 255; + cp[1] = 0; + cp[2] = 255; + if(channels == 4) + cp[3] = 255; + } + } + } + + return true; + } + + return false; +} + +bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, float *pixels) +{ + string name; + int frame; + builtin_name_split(builtin_name, name, frame); + + BL::Image b_image = b_data.images[name]; + + if(b_image) { + int width = b_image.size()[0]; + int height = b_image.size()[1]; + int channels = b_image.channels(); + + float *image_pixels; + image_pixels = image_get_float_pixels_for_frame(b_image, frame); + + if(image_pixels) { + memcpy(pixels, image_pixels, width * height * channels * sizeof(float)); + MEM_freeN(image_pixels); + } + else { + if(channels == 1) { + memset(pixels, 0, width * height * sizeof(float)); + } + else { + float *fp = pixels; + for(int i = 0; i < width * height; i++, fp += channels) { + fp[0] = 1.0f; + fp[1] = 0.0f; + fp[2] = 1.0f; + if(channels == 4) + fp[3] = 1.0f; + } + } + } + + return true; + } + + return false; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index 7f3973ae873..686ff3d1be9 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -93,6 +93,11 @@ public: protected: void do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile, bool do_update_only); void do_write_update_render_tile(RenderTile& rtile, bool do_update_only); + + void builtin_name_split(const string &builtin_name, string &name, int &frame); + void builtin_image_info(const string &builtin_name, bool &is_float, int &width, int &height, int &channels); + bool builtin_image_pixels(const string &builtin_name, unsigned char *pixels); + bool builtin_image_float_pixels(const string &builtin_name, float *pixels); }; CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index ddbd7f935e4..b1eaedba47a 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -511,9 +511,31 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen BL::ShaderNodeTexImage b_image_node(b_node); BL::Image b_image(b_image_node.image()); ImageTextureNode *image = new ImageTextureNode(); - /* todo: handle generated/builtin images */ - if(b_image && b_image.source() != BL::Image::source_MOVIE) { - image->filename = image_user_file_path(b_image_node.image_user(), b_image, b_scene.frame_current()); + if(b_image) { + /* builtin images will use callback-based reading because + * they could only be loaded correct from blender side + */ + bool is_builtin = b_image.packed_file() || + b_image.source() == BL::Image::source_GENERATED || + b_image.source() == BL::Image::source_MOVIE; + + if(is_builtin) { + /* for builtin images we're using image datablock name to find an image to + * read pixels from later + * + * also store frame number as well, so there's no differences in handling + * builtin names for packed images and movies + */ + int scene_frame = b_scene.frame_current(); + int image_frame = image_user_frame_number(b_image_node.image_user(), scene_frame); + image->filename = b_image.name() + "@" + string_printf("%d", image_frame); + image->is_builtin = true; + } + else { + image->filename = image_user_file_path(b_image_node.image_user(), b_image, b_scene.frame_current()); + image->is_builtin = false; + } + image->animated = b_image_node.image_user().use_auto_refresh(); } image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()]; @@ -527,9 +549,21 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen BL::ShaderNodeTexEnvironment b_env_node(b_node); BL::Image b_image(b_env_node.image()); EnvironmentTextureNode *env = new EnvironmentTextureNode(); - if(b_image && b_image.source() != BL::Image::source_MOVIE) { - env->filename = image_user_file_path(b_env_node.image_user(), b_image, b_scene.frame_current()); - env->animated = b_env_node.image_user().use_auto_refresh(); + if(b_image) { + bool is_builtin = b_image.packed_file() || + b_image.source() == BL::Image::source_GENERATED || + b_image.source() == BL::Image::source_MOVIE; + + if(is_builtin) { + int scene_frame = b_scene.frame_current(); + int image_frame = image_user_frame_number(b_env_node.image_user(), scene_frame); + env->filename = b_image.name() + "@" + string_printf("%d", image_frame); + env->is_builtin = true; + } + else { + env->filename = image_user_file_path(b_env_node.image_user(), b_image, b_scene.frame_current()); + env->animated = b_env_node.image_user().use_auto_refresh(); + } } env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()]; env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()]; diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index a2a8c23404f..7ad663b7e26 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -359,22 +359,22 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use params.background = background; /* samples */ - if(get_boolean(cscene, "progressive")) { + if(get_boolean(cscene, "progressive") == 0 && params.device.type == DEVICE_CPU){ if(background) { - params.samples = get_int(cscene, "samples"); + params.samples = get_int(cscene, "aa_samples"); } else { - params.samples = get_int(cscene, "preview_samples"); + params.samples = get_int(cscene, "preview_aa_samples"); if(params.samples == 0) params.samples = INT_MAX; } } else { if(background) { - params.samples = get_int(cscene, "aa_samples"); + params.samples = get_int(cscene, "samples"); } else { - params.samples = get_int(cscene, "preview_aa_samples"); + params.samples = get_int(cscene, "preview_samples"); if(params.samples == 0) params.samples = INT_MAX; } diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index 88c98860794..f134416f2d0 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -33,6 +33,8 @@ extern "C" { void BLI_timestr(double _time, char *str); void BKE_image_user_frame_calc(void *iuser, int cfra, int fieldnr); void BKE_image_user_file_path(void *iuser, void *ima, char *path); +unsigned char *BKE_image_get_pixels_for_frame(void *image, int frame); +float *BKE_image_get_float_pixels_for_frame(void *image, int frame); } CCL_NAMESPACE_BEGIN @@ -100,6 +102,22 @@ static inline string image_user_file_path(BL::ImageUser iuser, BL::Image ima, in return string(filepath); } +static inline int image_user_frame_number(BL::ImageUser iuser, int cfra) +{ + BKE_image_user_frame_calc(iuser.ptr.data, cfra, 0); + return iuser.frame_current(); +} + +static inline unsigned char *image_get_pixels_for_frame(BL::Image image, int frame) +{ + return BKE_image_get_pixels_for_frame(image.ptr.data, frame); +} + +static inline float *image_get_float_pixels_for_frame(BL::Image image, int frame) +{ + return BKE_image_get_float_pixels_for_frame(image.ptr.data, frame); +} + /* Utilities */ static inline Transform get_transform(BL::Array array) diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index 412b44031e6..011406344ea 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -18,6 +18,7 @@ #include "mesh.h" #include "object.h" #include "scene.h" +#include "curves.h" #include "bvh.h" #include "bvh_build.h" @@ -631,8 +632,19 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility int k0 = mesh->curves[pidx - str_offset].first_key + pack.prim_segment[prim]; // XXX! int k1 = k0 + 1; - bbox.grow(mesh->curve_keys[k0].co, mesh->curve_keys[k0].radius); - bbox.grow(mesh->curve_keys[k1].co, mesh->curve_keys[k1].radius); + float3 p[4]; + p[0] = mesh->curve_keys[max(k0 - 1,mesh->curves[pidx - str_offset].first_key)].co; + p[1] = mesh->curve_keys[k0].co; + p[2] = mesh->curve_keys[k1].co; + p[3] = mesh->curve_keys[min(k1 + 1,mesh->curves[pidx - str_offset].first_key + mesh->curves[pidx - str_offset].num_keys - 1)].co; + float3 lower; + float3 upper; + curvebounds(&lower.x, &upper.x, p, 0); + curvebounds(&lower.y, &upper.y, p, 1); + curvebounds(&lower.z, &upper.z, p, 2); + float mr = max(mesh->curve_keys[k0].radius,mesh->curve_keys[k1].radius); + bbox.grow(lower, mr); + bbox.grow(upper, mr); } else { /* triangles */ diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index 38fb1a15a13..022c4c8d294 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -24,6 +24,7 @@ #include "mesh.h" #include "object.h" #include "scene.h" +#include "curves.h" #include "util_debug.h" #include "util_foreach.h" @@ -91,11 +92,20 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, for(int k = 0; k < curve.num_keys - 1; k++) { BoundBox bounds = BoundBox::empty; - float3 co0 = mesh->curve_keys[curve.first_key + k].co; - float3 co1 = mesh->curve_keys[curve.first_key + k + 1].co; + float3 co[4]; + co[0] = mesh->curve_keys[max(curve.first_key + k - 1,curve.first_key)].co; + co[1] = mesh->curve_keys[curve.first_key + k].co; + co[2] = mesh->curve_keys[curve.first_key + k + 1].co; + co[3] = mesh->curve_keys[min(curve.first_key + k + 2, curve.first_key + curve.num_keys - 1)].co; - bounds.grow(co0, mesh->curve_keys[curve.first_key + k].radius); - bounds.grow(co1, mesh->curve_keys[curve.first_key + k + 1].radius); + float3 lower; + float3 upper; + curvebounds(&lower.x, &upper.x, co, 0); + curvebounds(&lower.y, &upper.y, co, 1); + curvebounds(&lower.z, &upper.z, co, 2); + float mr = max(mesh->curve_keys[curve.first_key + k].radius, mesh->curve_keys[curve.first_key + k + 1].radius); + bounds.grow(lower, mr); + bounds.grow(upper, mr); if(bounds.valid()) { references.push_back(BVHReference(bounds, j, i, k)); diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 040f3044457..0c590645808 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -238,13 +238,16 @@ public: if(path_exists(cubin)) return cubin; -#if defined(WITH_CUDA_BINARIES) && defined(_WIN32) - if(major <= 1 && minor <= 2) - cuda_error(string_printf("CUDA device supported only compute capability 1.3 or up, found %d.%d.", major, minor)); - else - cuda_error(string_printf("CUDA binary kernel for this graphics card compute capability (%d.%d) not found.", major, minor)); - return ""; -#else +#ifdef _WIN32 + if(cuHavePrecompiledKernels()) { + if(major <= 1 && minor <= 2) + cuda_error(string_printf("CUDA device requires compute capability 1.3 or up, found %d.%d. Your GPU is not supported.", major, minor)); + else + cuda_error(string_printf("CUDA binary kernel for this graphics card compute capability (%d.%d) not found.", major, minor)); + return ""; + } +#endif + /* if not, find CUDA compiler */ string nvcc = cuCompilerPath(); @@ -282,7 +285,6 @@ public: printf("Kernel compilation finished in %.2lfs.\n", time_dt() - starttime); return cubin; -#endif } bool load_kernels(bool experimental) diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 69287f1a8bd..3ab5d9ee69b 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -303,7 +303,7 @@ public: string build_options = " -cl-fast-relaxed-math "; if(platform_name == "NVIDIA CUDA") - build_options += "-D__KERNEL_SHADING__ -D__KERNEL_OPENCL_NVIDIA__ -cl-nv-maxrregcount=24 -cl-nv-verbose "; + build_options += "-D__KERNEL_OPENCL_NVIDIA__ -cl-nv-maxrregcount=24 -cl-nv-verbose "; else if(platform_name == "Apple") build_options += "-D__CL_NO_FLOAT3__ -D__KERNEL_OPENCL_APPLE__ "; diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index d99beb8905a..86177301357 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -133,6 +133,10 @@ __device_inline void path_radiance_init(PathRadiance *L, int use_light_pass) L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f); L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f); + L->path_diffuse = make_float3(0.0f, 0.0f, 0.0f); + L->path_glossy = make_float3(0.0f, 0.0f, 0.0f); + L->path_transmission = make_float3(0.0f, 0.0f, 0.0f); + L->emission = make_float3(0.0f, 0.0f, 0.0f); L->background = make_float3(0.0f, 0.0f, 0.0f); L->ao = make_float3(0.0f, 0.0f, 0.0f); @@ -156,11 +160,11 @@ __device_inline void path_radiance_bsdf_bounce(PathRadiance *L, float3 *throughp /* first on directly visible surface */ float3 value = *throughput*inverse_pdf; - L->indirect_diffuse = bsdf_eval->diffuse*value; - L->indirect_glossy = bsdf_eval->glossy*value; - L->indirect_transmission = bsdf_eval->transmission*value; + L->path_diffuse = bsdf_eval->diffuse*value; + L->path_glossy = bsdf_eval->glossy*value; + L->path_transmission = bsdf_eval->transmission*value; - *throughput = L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission; + *throughput = L->path_diffuse + L->path_glossy + L->path_transmission; L->direct_throughput = *throughput; } @@ -266,22 +270,45 @@ __device_inline void path_radiance_accum_background(PathRadiance *L, float3 thro #endif } +__device_inline void path_radiance_sum_indirect(PathRadiance *L) +{ +#ifdef __PASSES__ + /* this division is a bit ugly, but means we only have to keep track of + * only a single throughput further along the path, here we recover just + * the indirect parth that is not influenced by any particular BSDF type */ + if(L->use_light_pass) { + L->direct_emission = safe_divide_color(L->direct_emission, L->direct_throughput); + L->direct_diffuse += L->path_diffuse*L->direct_emission; + L->direct_glossy += L->path_glossy*L->direct_emission; + L->direct_transmission += L->path_transmission*L->direct_emission; + + L->indirect = safe_divide_color(L->indirect, L->direct_throughput); + L->indirect_diffuse += L->path_diffuse*L->indirect; + L->indirect_glossy += L->path_glossy*L->indirect; + L->indirect_transmission += L->path_transmission*L->indirect; + } +#endif +} + +__device_inline void path_radiance_reset_indirect(PathRadiance *L) +{ +#ifdef __PASSES__ + if(L->use_light_pass) { + L->path_diffuse = make_float3(0.0f, 0.0f, 0.0f); + L->path_glossy = make_float3(0.0f, 0.0f, 0.0f); + L->path_transmission = make_float3(0.0f, 0.0f, 0.0f); + + L->direct_emission = make_float3(0.0f, 0.0f, 0.0f); + L->indirect = make_float3(0.0f, 0.0f, 0.0f); + } +#endif +} + __device_inline float3 path_radiance_sum(KernelGlobals *kg, PathRadiance *L) { #ifdef __PASSES__ if(L->use_light_pass) { - /* this division is a bit ugly, but means we only have to keep track of - * only a single throughput further along the path, here we recover just - * the indirect parth that is not influenced by any particular BSDF type */ - L->direct_emission = safe_divide_color(L->direct_emission, L->direct_throughput); - L->direct_diffuse += L->indirect_diffuse*L->direct_emission; - L->direct_glossy += L->indirect_glossy*L->direct_emission; - L->direct_transmission += L->indirect_transmission*L->direct_emission; - - L->indirect = safe_divide_color(L->indirect, L->direct_throughput); - L->indirect_diffuse *= L->indirect; - L->indirect_glossy *= L->indirect; - L->indirect_transmission *= L->indirect; + path_radiance_sum_indirect(L); float3 L_sum = L->emission + L->direct_diffuse + L->direct_glossy + L->direct_transmission diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h index 2cb29207b05..1a85b5bbefd 100644 --- a/intern/cycles/kernel/kernel_bvh.h +++ b/intern/cycles/kernel/kernel_bvh.h @@ -206,6 +206,317 @@ __device_inline void bvh_triangle_intersect(KernelGlobals *kg, Intersection *ise } #ifdef __HAIR__ +__device_inline void curvebounds(float *lower, float *upper, float *extremta, float *extrema, float *extremtb, float *extremb, float p0, float p1, float p2, float p3) +{ + float halfdiscroot = (p2 * p2 - 3 * p3 * p1); + float ta = -1.0f; + float tb = -1.0f; + *extremta = -1.0f; + *extremtb = -1.0f; + *upper = p0; + *lower = p0 + p1 + p2 + p3; + *extrema = *upper; + *extremb = *lower; + if(*lower >= *upper) { + *upper = *lower; + *lower = p0; + } + + if(halfdiscroot >= 0) { + halfdiscroot = sqrt(halfdiscroot); + ta = (-p2 - halfdiscroot) / (3 * p3); + tb = (-p2 + halfdiscroot) / (3 * p3); + } + + float t2; + float t3; + if(ta > 0.0f && ta < 1.0f) { + t2 = ta * ta; + t3 = t2 * ta; + *extremta = ta; + *extrema = p3 * t3 + p2 * t2 + p1 * ta + p0; + if(*extrema > *upper) { + *upper = *extrema; + } + if(*extrema < *lower) { + *lower = *extrema; + } + } + if(tb > 0.0f && tb < 1.0f) { + t2 = tb * tb; + t3 = t2 * tb; + *extremtb = tb; + *extremb = p3 * t3 + p2 * t2 + p1 * tb + p0; + if(*extremb >= *upper) { + *upper = *extremb; + } + if(*extremb <= *lower) { + *lower = *extremb; + } + } +} + +__device_inline void bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersection *isect, + float3 P, float3 idir, uint visibility, int object, int curveAddr, int segment) +{ + int depth = kernel_data.curve_kernel_data.subdivisions; + + /* curve Intersection check */ + float3 dir = 1.0f/idir; + + int flags = kernel_data.curve_kernel_data.curveflags; + + int prim = kernel_tex_fetch(__prim_index, curveAddr); + + float3 curve_coef[4]; + float r_st,r_en; + + /*obtain curve parameters*/ + { + /*ray transform created - this shold be created at beginning of intersection loop*/ + Transform htfm; + float d = sqrtf(dir.x * dir.x + dir.z * dir.z); + htfm = make_transform( + dir.z / d, 0, -dir.x /d, 0, + -dir.x * dir.y /d, d, -dir.y * dir.z /d, 0, + dir.x, dir.y, dir.z, 0, + 0, 0, 0, 1) * make_transform( + 1, 0, 0, -P.x, + 0, 1, 0, -P.y, + 0, 0, 1, -P.z, + 0, 0, 0, 1); + + float4 v00 = kernel_tex_fetch(__curves, prim); + + int k0 = __float_as_int(v00.x) + segment; + int k1 = k0 + 1; + + int ka = max(k0 - 1,__float_as_int(v00.x)); + int kb = min(k1 + 1,__float_as_int(v00.x) + __float_as_int(v00.y) - 1); + + float4 P0 = kernel_tex_fetch(__curve_keys, ka); + float4 P1 = kernel_tex_fetch(__curve_keys, k0); + float4 P2 = kernel_tex_fetch(__curve_keys, k1); + float4 P3 = kernel_tex_fetch(__curve_keys, kb); + + float3 p0 = transform_point(&htfm, float4_to_float3(P0)); + float3 p1 = transform_point(&htfm, float4_to_float3(P1)); + float3 p2 = transform_point(&htfm, float4_to_float3(P2)); + float3 p3 = transform_point(&htfm, float4_to_float3(P3)); + + float fc = 0.71f; + curve_coef[0] = p1; + curve_coef[1] = -fc*p0 + fc*p2; + curve_coef[2] = 2.0f * fc * p0 + (fc - 3.0f) * p1 + (3.0f - 2.0f * fc) * p2 - fc * p3; + curve_coef[3] = -fc * p0 + (2.0f - fc) * p1 + (fc - 2.0f) * p2 + fc * p3; + r_st = P1.w; + r_en = P2.w; + } + + + float r_curr = max(r_st, r_en); + + /*find bounds - this is slow for cubic curves*/ + float upper,lower; + float xextrem[4]; + curvebounds(&lower, &upper, &xextrem[0], &xextrem[1], &xextrem[2], &xextrem[3], curve_coef[0].x, curve_coef[1].x, curve_coef[2].x, curve_coef[3].x); + if(lower > r_curr || upper < -r_curr) + return; + + float yextrem[4]; + curvebounds(&lower, &upper, &yextrem[0], &yextrem[1], &yextrem[2], &yextrem[3], curve_coef[0].y, curve_coef[1].y, curve_coef[2].y, curve_coef[3].y); + if(lower > r_curr || upper < -r_curr) + return; + + float zextrem[4]; + curvebounds(&lower, &upper, &zextrem[0], &zextrem[1], &zextrem[2], &zextrem[3], curve_coef[0].z, curve_coef[1].z, curve_coef[2].z, curve_coef[3].z); + if(lower - r_curr > isect->t || upper + r_curr < 0.0f) + return; + + /*setup recurrent loop*/ + int level = 1 << depth; + int tree = 0; + float resol = 1.0f / (float)level; + + /*begin loop*/ + while(!(tree >> (depth))) { + float i_st = tree * resol; + float i_en = i_st + (level * resol); + float3 p_st = ((curve_coef[3] * i_st + curve_coef[2]) * i_st + curve_coef[1]) * i_st + curve_coef[0]; + float3 p_en = ((curve_coef[3] * i_en + curve_coef[2]) * i_en + curve_coef[1]) * i_en + curve_coef[0]; + + float bminx = min(p_st.x, p_en.x); + float bmaxx = max(p_st.x, p_en.x); + float bminy = min(p_st.y, p_en.y); + float bmaxy = max(p_st.y, p_en.y); + float bminz = min(p_st.z, p_en.z); + float bmaxz = max(p_st.z, p_en.z); + + if(xextrem[0] >= i_st && xextrem[0] <= i_en) { + bminx = min(bminx,xextrem[1]); + bmaxx = max(bmaxx,xextrem[1]); + } + if(xextrem[2] >= i_st && xextrem[2] <= i_en) { + bminx = min(bminx,xextrem[3]); + bmaxx = max(bmaxx,xextrem[3]); + } + if(yextrem[0] >= i_st && yextrem[0] <= i_en) { + bminy = min(bminy,yextrem[1]); + bmaxy = max(bmaxy,yextrem[1]); + } + if(yextrem[2] >= i_st && yextrem[2] <= i_en) { + bminy = min(bminy,yextrem[3]); + bmaxy = max(bmaxy,yextrem[3]); + } + if(zextrem[0] >= i_st && zextrem[0] <= i_en) { + bminz = min(bminz,zextrem[1]); + bmaxz = max(bmaxz,zextrem[1]); + } + if(zextrem[2] >= i_st && zextrem[2] <= i_en) { + bminz = min(bminz,zextrem[3]); + bmaxz = max(bmaxz,zextrem[3]); + } + + float r1 = r_st + (r_en - r_st) * i_st; + float r2 = r_st + (r_en - r_st) * i_en; + r_curr = max(r1, r2); + + if (bminz - r_curr > isect->t || bmaxz + r_curr < 0.0f|| bminx > r_curr || bmaxx < -r_curr || bminy > r_curr || bmaxy < -r_curr) { + /* the bounding box does not overlap the square centered at O.*/ + tree += level; + level = tree & -tree; + } + else if (level == 1) { + + /* the maximum recursion depth is reached. + * check if dP0.(Q-P0)>=0 and dPn.(Pn-Q)>=0. + * dP* is reversed if necessary.*/ + float t = isect->t; + float u = 0.0f; + if(flags & CURVE_KN_RIBBONS) { + float3 tg = (p_en - p_st); + float w = tg.x * tg.x + tg.y * tg.y; + if (w == 0) { + tree++; + level = tree & -tree; + continue; + } + w = -(p_st.x * tg.x + p_st.y * tg.y) / w; + w = clamp((float)w, 0.0f, 1.0f); + + /* compute u on the curve segment.*/ + u = i_st * (1 - w) + i_en * w; + r_curr = r_st + (r_en - r_st) * u; + /* compare x-y distances.*/ + float3 p_curr = ((curve_coef[3] * u + curve_coef[2]) * u + curve_coef[1]) * u + curve_coef[0]; + + float3 dp_st = (3 * curve_coef[3] * i_st + 2 * curve_coef[2]) * i_st + curve_coef[1]; + if (dot(tg, dp_st)< 0) + dp_st *= -1; + if (dot(dp_st, -p_st) + p_curr.z * dp_st.z < 0) { + tree++; + level = tree & -tree; + continue; + } + float3 dp_en = (3 * curve_coef[3] * i_en + 2 * curve_coef[2]) * i_en + curve_coef[1]; + if (dot(tg, dp_en) < 0) + dp_en *= -1; + if (dot(dp_en, p_en) - p_curr.z * dp_en.z < 0) { + tree++; + level = tree & -tree; + continue; + } + + if (p_curr.x * p_curr.x + p_curr.y * p_curr.y >= r_curr * r_curr || p_curr.z <= 0.0f) { + tree++; + level = tree & -tree; + continue; + } + /* compare z distances.*/ + if (isect->t < p_curr.z) { + tree++; + level = tree & -tree; + continue; + } + t = p_curr.z; + } + else { + float l = len(p_en - p_st); + float3 tg = (p_en - p_st) / l; + float gd = (r2 - r1) / l; + float difz = -dot(p_st,tg); + float cyla = 1.0f - (tg.z * tg.z * (1 + gd*gd)); + float halfb = (-p_st.z - tg.z*(difz + gd*(difz*gd + r1))); + float tcentre = -halfb/cyla; + float zcentre = difz + (tg.z * tcentre); + float3 tdif = - p_st; + tdif.z += tcentre; + float tdifz = dot(tdif,tg); + float tb = 2*(tdif.z - tg.z*(tdifz + gd*(tdifz*gd + r1))); + float tc = dot(tdif,tdif) - tdifz * tdifz * (1 + gd*gd) - r1*r1 - 2*r1*tdifz*gd; + float td = tb*tb - 4*cyla*tc; + if (td < 0.0f){ + tree++; + level = tree & -tree; + continue; + } + + float rootd = sqrtf(td); + float correction = ((-tb - rootd)/(2*cyla)); + t = tcentre + correction; + float w = (zcentre + (tg.z * correction))/l; + + float3 dp_st = (3 * curve_coef[3] * i_st + 2 * curve_coef[2]) * i_st + curve_coef[1]; + if (dot(tg, dp_st)< 0) + dp_st *= -1; + float3 dp_en = (3 * curve_coef[3] * i_en + 2 * curve_coef[2]) * i_en + curve_coef[1]; + if (dot(tg, dp_en) < 0) + dp_en *= -1; + + + if(flags & CURVE_KN_BACKFACING && (dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 || isect->t < t || t <= 0.0f)) { + correction = ((-tb + rootd)/(2*cyla)); + t = tcentre + correction; + w = (zcentre + (tg.z * correction))/l; + } + + if (dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 || isect->t < t || t <= 0.0f) { + tree++; + level = tree & -tree; + continue; + } + + w = clamp((float)w, 0.0f, 1.0f); + /* compute u on the curve segment.*/ + u = i_st * (1 - w) + i_en * w; + + } + /* we found a new intersection.*/ +#ifdef __VISIBILITY_FLAG__ + /* visibility flag test. we do it here under the assumption + * that most triangles are culled by node flags */ + if(kernel_tex_fetch(__prim_visibility, curveAddr) & visibility) +#endif + { + /* record intersection */ + isect->prim = curveAddr; + isect->segment = segment; + isect->object = object; + isect->u = u; + isect->v = 0.0f; + isect->t = t; + } + + tree++; + level = tree & -tree; + } + else { + /* split the curve into two curves and process */ + level = level >> 1; + } + } +} + __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect, float3 P, float3 idir, uint visibility, int object, int curveAddr, int segment) { @@ -222,7 +533,6 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect, float4 P1 = kernel_tex_fetch(__curve_keys, k0); float4 P2 = kernel_tex_fetch(__curve_keys, k1); - float l = len(P2 - P1); float r1 = P1.w; float r2 = P2.w; float mr = max(r1,r2); @@ -230,6 +540,7 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect, float3 p2 = float4_to_float3(P2); float3 dif = P - p1; float3 dir = 1.0f/idir; + float l = len(p2 - p1); float sp_r = mr + 0.5f * l; float3 sphere_dif = P - ((p1 + p2) * 0.5f); @@ -344,7 +655,7 @@ __device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect, } #endif -__device_inline bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect) +__device bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect) { /* traversal stack in CUDA thread-local memory */ int traversalStack[BVH_STACK_SIZE]; @@ -425,8 +736,12 @@ __device_inline bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint /* intersect ray against primitive */ #ifdef __HAIR__ uint segment = kernel_tex_fetch(__prim_segment, primAddr); - if(segment != ~0) - bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment); + if(segment != ~0) { + if(kernel_data.curve_kernel_data.curveflags & CURVE_KN_INTERPOLATE) + bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment); + else + bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment); + } else #endif bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr); @@ -470,7 +785,7 @@ __device_inline bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint } #ifdef __OBJECT_MOTION__ -__device_inline bool bvh_intersect_motion(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect) +__device bool bvh_intersect_motion(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect) { /* traversal stack in CUDA thread-local memory */ int traversalStack[BVH_STACK_SIZE]; @@ -551,8 +866,12 @@ __device_inline bool bvh_intersect_motion(KernelGlobals *kg, const Ray *ray, con /* intersect ray against primitive */ #ifdef __HAIR__ uint segment = kernel_tex_fetch(__prim_segment, primAddr); - if(segment != ~0) - bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment); + if(segment != ~0) { + if(kernel_data.curve_kernel_data.curveflags & CURVE_KN_INTERPOLATE) + bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment); + else + bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment); + } else #endif bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr); @@ -610,7 +929,7 @@ __device_inline float3 ray_offset(float3 P, float3 Ng) const float epsilon_f = 1e-5f; /* ideally this should match epsilon_f, but instancing/mblur * precision makes it problematic */ - const float epsilon_test = 1e-1f; + const float epsilon_test = 1.0f; const int epsilon_i = 32; float3 res; @@ -697,6 +1016,32 @@ __device_inline float3 bvh_triangle_refine(KernelGlobals *kg, ShaderData *sd, co } #ifdef __HAIR__ + +__device_inline float3 curvetangent(float t, float3 p0, float3 p1, float3 p2, float3 p3) +{ + float fc = 0.71f; + float data[4]; + float t2 = t * t; + data[0] = -3.0f * fc * t2 + 4.0f * fc * t - fc; + data[1] = 3.0f * (2.0f - fc) * t2 + 2.0f * (fc - 3.0f) * t; + data[2] = 3.0f * (fc - 2.0f) * t2 + 2.0f * (3.0f - 2.0f * fc) * t + fc; + data[3] = 3.0f * fc * t2 - 2.0f * fc * t; + return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3; +} + +__device_inline float3 curvepoint(float t, float3 p0, float3 p1, float3 p2, float3 p3) +{ + float data[4]; + float fc = 0.71f; + float t2 = t * t; + float t3 = t2 * t; + data[0] = -fc * t3 + 2.0f * fc * t2 - fc * t; + data[1] = (2.0f - fc) * t3 + (fc - 3.0f) * t2 + 1.0f; + data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t; + data[3] = fc * t3 - fc * t2; + return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3; +} + __device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray, float t) { int flag = kernel_data.curve_kernel_data.curveflags; @@ -723,64 +1068,92 @@ __device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, const float4 P1 = kernel_tex_fetch(__curve_keys, k0); float4 P2 = kernel_tex_fetch(__curve_keys, k1); - float l = len(P2 - P1); + float l = 1.0f; + float3 tg = normalize_len(float4_to_float3(P2 - P1),&l); float r1 = P1.w; float r2 = P2.w; - float3 tg = float4_to_float3(P2 - P1) / l; - float3 dif = P - float4_to_float3(P1) + t * D; float gd = ((r2 - r1)/l); - + P = P + D*t; - dif = P - float4_to_float3(P1); + if(flag & CURVE_KN_INTERPOLATE) { + int ka = max(k0 - 1,__float_as_int(v00.x)); + int kb = min(k1 + 1,__float_as_int(v00.x) + __float_as_int(v00.y) - 1); - #ifdef __UV__ - sd->u = dot(dif,tg)/l; - sd->v = 0.0f; - #endif + float4 P0 = kernel_tex_fetch(__curve_keys, ka); + float4 P3 = kernel_tex_fetch(__curve_keys, kb); - if (flag & CURVE_KN_TRUETANGENTGNORMAL) { - sd->Ng = -(D - tg * (dot(tg,D) * kernel_data.curve_kernel_data.normalmix)); - sd->Ng = normalize(sd->Ng); - if (flag & CURVE_KN_NORMALCORRECTION) - { - //sd->Ng = normalize(sd->Ng); + float3 p[4]; + p[0] = float4_to_float3(P0); + p[1] = float4_to_float3(P1); + p[2] = float4_to_float3(P2); + p[3] = float4_to_float3(P3); + + tg = normalize(curvetangent(isect->u,p[0],p[1],p[2],p[3])); + float3 p_curr = curvepoint(isect->u,p[0],p[1],p[2],p[3]); + +#ifdef __UV__ + sd->u = isect->u; + sd->v = 0.0f; +#endif + + if(kernel_data.curve_kernel_data.curveflags & CURVE_KN_RIBBONS) + sd->Ng = normalize(-(D - tg * (dot(tg,D)))); + else { + sd->Ng = normalize(P - p_curr); sd->Ng = sd->Ng - gd * tg; sd->Ng = normalize(sd->Ng); } + sd->N = sd->Ng; } else { - sd->Ng = (dif - tg * sd->u * l) / (P1.w + sd->u * l * gd); - if (gd != 0.0f) { - sd->Ng = sd->Ng - gd * tg ; + float3 dif = P - float4_to_float3(P1); + +#ifdef __UV__ + sd->u = dot(dif,tg)/l; + sd->v = 0.0f; +#endif + + if (flag & CURVE_KN_TRUETANGENTGNORMAL) { + sd->Ng = -(D - tg * (dot(tg,D) * kernel_data.curve_kernel_data.normalmix)); sd->Ng = normalize(sd->Ng); + if (flag & CURVE_KN_NORMALCORRECTION) { + sd->Ng = sd->Ng - gd * tg; + sd->Ng = normalize(sd->Ng); + } + } + else { + sd->Ng = (dif - tg * sd->u * l) / (P1.w + sd->u * l * gd); + if (gd != 0.0f) { + sd->Ng = sd->Ng - gd * tg ; + sd->Ng = normalize(sd->Ng); + } } - } - sd->N = sd->Ng; + sd->N = sd->Ng; - if (flag & CURVE_KN_TANGENTGNORMAL && !(flag & CURVE_KN_TRUETANGENTGNORMAL)) { - sd->N = -(D - tg * (dot(tg,D) * kernel_data.curve_kernel_data.normalmix)); - sd->N = normalize(sd->N); - if (flag & CURVE_KN_NORMALCORRECTION) { - //sd->N = normalize(sd->N); - sd->N = sd->N - gd * tg; + if (flag & CURVE_KN_TANGENTGNORMAL && !(flag & CURVE_KN_TRUETANGENTGNORMAL)) { + sd->N = -(D - tg * (dot(tg,D) * kernel_data.curve_kernel_data.normalmix)); sd->N = normalize(sd->N); + if (flag & CURVE_KN_NORMALCORRECTION) { + sd->N = sd->N - gd * tg; + sd->N = normalize(sd->N); + } } - } - if (!(flag & CURVE_KN_TANGENTGNORMAL) && flag & CURVE_KN_TRUETANGENTGNORMAL) { - sd->N = (dif - tg * sd->u * l) / (P1.w + sd->u * l * gd); - if (gd != 0.0f) { - sd->N = sd->N - gd * tg ; - sd->N = normalize(sd->N); + if (!(flag & CURVE_KN_TANGENTGNORMAL) && flag & CURVE_KN_TRUETANGENTGNORMAL) { + sd->N = (dif - tg * sd->u * l) / (P1.w + sd->u * l * gd); + if (gd != 0.0f) { + sd->N = sd->N - gd * tg ; + sd->N = normalize(sd->N); + } } } - #ifdef __DPDU__ +#ifdef __DPDU__ /* dPdu/dPdv */ sd->dPdu = tg; sd->dPdv = cross(tg,sd->Ng); - #endif +#endif if(isect->object != ~0) { #ifdef __OBJECT_MOTION__ diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index cd896ffe133..f9d5bd3dd3f 100644 --- a/intern/cycles/kernel/kernel_camera.h +++ b/intern/cycles/kernel/kernel_camera.h @@ -213,7 +213,7 @@ __device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, flo #ifdef __CAMERA_MOTION__ /* motion blur */ - if(kernel_data.cam.shuttertime == 0.0f) + if(kernel_data.cam.shuttertime == -1.0f) ray->time = TIME_INVALID; else ray->time = 0.5f + 0.5f*(time - 0.5f)*kernel_data.cam.shuttertime; diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index e0d0802ae84..6ba3e439329 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -233,8 +233,10 @@ __device void lamp_light_sample(KernelGlobals *kg, int lamp, if(radius > 0.0f) D = distant_light_sample(D, radius, randu, randv); +#ifdef __LAMP_MIS__ else ls->use_mis = false; +#endif ls->P = D; ls->Ng = D; @@ -255,6 +257,9 @@ __device void lamp_light_sample(KernelGlobals *kg, int lamp, ls->D = -D; ls->t = FLT_MAX; ls->eval_fac = 1.0f; +#ifndef __LAMP_MIS__ + ls->use_mis = true; +#endif } #endif else { @@ -266,8 +271,10 @@ __device void lamp_light_sample(KernelGlobals *kg, int lamp, if(radius > 0.0f) /* sphere light */ ls->P += sphere_light_sample(P, ls->P, radius, randu, randv); +#ifdef __LAMP_MIS__ else ls->use_mis = false; +#endif ls->D = normalize_len(ls->P - P, &ls->t); ls->Ng = -ls->D; @@ -298,7 +305,9 @@ __device void lamp_light_sample(KernelGlobals *kg, int lamp, float invarea = data2.x; if(invarea == 0.0f) { +#ifdef __LAMP_MIS__ ls->use_mis = false; +#endif invarea = 1.0f; } diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 532c32896d9..1a5df66e6c2 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -949,6 +949,11 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam kernel_path_indirect(kg, rng, sample*num_samples + j, bsdf_ray, buffer, tp*num_samples_inv, num_samples, min_ray_pdf, bsdf_pdf, ps, rng_offset+PRNG_BOUNCE_NUM, &L); + + /* for render passes, sum and reset indirect light pass variables + * for the next samples */ + path_radiance_sum_indirect(&L); + path_radiance_reset_indirect(&L); } } diff --git a/intern/cycles/kernel/kernel_primitive.h b/intern/cycles/kernel/kernel_primitive.h index 0851af21e87..323394cd9dc 100644 --- a/intern/cycles/kernel/kernel_primitive.h +++ b/intern/cycles/kernel/kernel_primitive.h @@ -106,7 +106,7 @@ __device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd) float3 data = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL); data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f); object_normal_transform(kg, sd, &data); - return cross(sd->N, normalize(cross(data, sd->N)));; + return cross(sd->N, normalize(cross(data, sd->N))); } else { /* otherwise use surface derivatives */ diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 0a5a2ab54b0..b7d87427bd3 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -53,7 +53,7 @@ __device_noinline void shader_setup_object_transforms(KernelGlobals *kg, ShaderD } #endif -__device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, +__device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray) { #ifdef __INSTANCING__ diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 102be440978..1236f43e018 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -43,12 +43,12 @@ CCL_NAMESPACE_BEGIN #ifdef __KERNEL_CPU__ #define __KERNEL_SHADING__ #define __KERNEL_ADV_SHADING__ +#define __NON_PROGRESSIVE__ +#define __LAMP_MIS__ +#define __HAIR__ #ifdef WITH_OSL #define __OSL__ #endif -#define __NON_PROGRESSIVE__ -#define __HAIR__ -#define __LAMP_MIS__ #endif #ifdef __KERNEL_CUDA__ @@ -56,6 +56,9 @@ CCL_NAMESPACE_BEGIN #if __CUDA_ARCH__ >= 200 #define __KERNEL_ADV_SHADING__ #endif +#if __CUDA_ARCH__ >= 210 +#define __LAMP_MIS__ +#endif #endif #ifdef __KERNEL_OPENCL__ @@ -114,8 +117,8 @@ CCL_NAMESPACE_BEGIN #define __PASSES__ #define __BACKGROUND_MIS__ #define __AO__ -#define __CAMERA_MOTION__ #define __ANISOTROPIC__ +#define __CAMERA_MOTION__ #define __OBJECT_MOTION__ #endif //#define __SOBOL_FULL_SCREEN__ @@ -255,6 +258,10 @@ typedef struct PathRadiance { float3 indirect_glossy; float3 indirect_transmission; + float3 path_diffuse; + float3 path_glossy; + float3 path_transmission; + float4 shadow; } PathRadiance; @@ -696,6 +703,7 @@ typedef enum CurveFlag { CURVE_KN_NORMALCORRECTION = 128, /* correct tangent normal for slope? */ CURVE_KN_TRUETANGENTGNORMAL = 256, /* use tangent normal for geometry? */ CURVE_KN_TANGENTGNORMAL = 512, /* use tangent normal for shader? */ + CURVE_KN_RIBBONS = 1024, /* use flat curve ribbons */ } CurveFlag; typedef struct KernelCurves { @@ -703,7 +711,7 @@ typedef struct KernelCurves { float normalmix; float encasing_ratio; int curveflags; - int pad; + int subdivisions; } KernelCurves; diff --git a/intern/cycles/kernel/shaders/node_normal_map.osl b/intern/cycles/kernel/shaders/node_normal_map.osl index dc25eb8539f..21382fab06f 100644 --- a/intern/cycles/kernel/shaders/node_normal_map.osl +++ b/intern/cycles/kernel/shaders/node_normal_map.osl @@ -31,15 +31,23 @@ shader node_normal_map( if (space == "Tangent") { vector tangent; + vector ninterp; float tangent_sign; - getattribute(attr_name, tangent); - getattribute(attr_sign_name, tangent_sign); + // get _unnormalized_ interpolated normal and tangent + if(!getattribute(attr_name, tangent) || + !getattribute(attr_sign_name, tangent_sign) || + !getattribute("geom:N", ninterp)) { + Normal = normal(0, 0, 0); + } + else { + // apply normal map + vector B = tangent_sign * cross(ninterp, tangent); + Normal = normalize(mcolor[0] * tangent + mcolor[1] * B + mcolor[2] * ninterp); - tangent = transform("object", "world", tangent); - - vector B = tangent_sign * cross(NormalIn, tangent); - Normal = normalize(mcolor[0] * tangent + mcolor[1] * B + mcolor[2] * NormalIn); + // transform to world space + Normal = normalize(transform("object", "world", Normal)); + } } else if (space == "Object") Normal = normalize(transform("object", "world", vector(mcolor))); diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h index 7a1af43b625..d793169261d 100644 --- a/intern/cycles/kernel/svm/svm_tex_coord.h +++ b/intern/cycles/kernel/svm/svm_tex_coord.h @@ -248,24 +248,27 @@ __device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stac } /* first try to get tangent attribute */ - AttributeElement attr_elem, attr_sign_elem; + AttributeElement attr_elem, attr_sign_elem, attr_normal_elem; int attr_offset = find_attribute(kg, sd, node.z, &attr_elem); int attr_sign_offset = find_attribute(kg, sd, node.w, &attr_sign_elem); + int attr_normal_offset = find_attribute(kg, sd, ATTR_STD_VERTEX_NORMAL, &attr_normal_elem); - if(attr_offset == ATTR_STD_NOT_FOUND || attr_sign_offset == ATTR_STD_NOT_FOUND) { + if(attr_offset == ATTR_STD_NOT_FOUND || attr_sign_offset == ATTR_STD_NOT_FOUND || attr_normal_offset == ATTR_STD_NOT_FOUND) { stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f)); return; } - /* ensure orthogonal and normalized (interpolation breaks it) */ + /* get _unnormalized_ interpolated normal and tangent */ float3 tangent = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL); float sign = primitive_attribute_float(kg, sd, attr_sign_elem, attr_sign_offset, NULL, NULL); + float3 normal = primitive_attribute_float3(kg, sd, attr_normal_elem, attr_normal_offset, NULL, NULL); - object_normal_transform(kg, sd, &tangent); - tangent = cross(sd->N, normalize(cross(tangent, sd->N)));; + /* apply normal map */ + float3 B = sign * cross(normal, tangent); + N = normalize(color.x * tangent + color.y * B + color.z * normal); - float3 B = sign * cross(sd->N, tangent); - N = normalize(color.x * tangent + color.y * B + color.z * sd->N); + /* transform to world space */ + object_normal_transform(kg, sd, &N); } else { /* object, world space */ diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index a78ede979b2..3ca19496b72 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -216,9 +216,9 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) /* motion blur */ #ifdef __CAMERA_MOTION__ - kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime: 0.0f; + kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime: -1.0f; #else - kcam->shuttertime = 0.0f; + kcam->shuttertime = -1.0f; #endif /* type */ diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 9696161180d..197a4da588c 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -90,7 +90,7 @@ public: Transform worldtocamera; Transform rastertocamera; - Transform cameratoraster;; + Transform cameratoraster; float3 dx; float3 dy; diff --git a/intern/cycles/render/curves.cpp b/intern/cycles/render/curves.cpp index 3299503b4ab..9fa867ae723 100644 --- a/intern/cycles/render/curves.cpp +++ b/intern/cycles/render/curves.cpp @@ -29,6 +29,52 @@ CCL_NAMESPACE_BEGIN +/* Curve functions */ + +void curvebounds(float *lower, float *upper, float3 *p, int dim) +{ + float *p0 = &p[0].x; + float *p1 = &p[1].x; + float *p2 = &p[2].x; + float *p3 = &p[3].x; + float fc = 0.71f; + float curve_coef[4]; + curve_coef[0] = p1[dim]; + curve_coef[1] = -fc*p0[dim] + fc*p2[dim]; + curve_coef[2] = 2.0f * fc * p0[dim] + (fc - 3.0f) * p1[dim] + (3.0f - 2.0f * fc) * p2[dim] - fc * p3[dim]; + curve_coef[3] = -fc * p0[dim] + (2.0f - fc) * p1[dim] + (fc - 2.0f) * p2[dim] + fc * p3[dim]; + float discroot = curve_coef[2] * curve_coef[2] - 3 * curve_coef[3] * curve_coef[1]; + float ta = -1.0f; + float tb = -1.0f; + if(discroot >= 0) { + discroot = sqrt(discroot); + ta = (-curve_coef[2] - discroot) / (3 * curve_coef[3]); + tb = (-curve_coef[2] + discroot) / (3 * curve_coef[3]); + ta = (ta > 1.0f || ta < 0.0f) ? -1.0f : ta; + tb = (tb > 1.0f || tb < 0.0f) ? -1.0f : tb; + } + + *upper = max(p1[dim],p2[dim]); + *lower = min(p1[dim],p2[dim]); + float exa = p1[dim]; + float exb = p2[dim]; + float t2; + float t3; + if(ta >= 0.0f) { + t2 = ta * ta; + t3 = t2 * ta; + exa = curve_coef[3] * t3 + curve_coef[2] * t2 + curve_coef[1] * ta + curve_coef[0]; + } + if(tb >= 0.0f) { + t2 = tb * tb; + t3 = t2 * tb; + exb = curve_coef[3] * t3 + curve_coef[2] * t2 + curve_coef[1] * tb + curve_coef[0]; + } + *upper = max(*upper, max(exa,exb)); + *lower = min(*lower, min(exa,exb)); + +} + /* Hair System Manager */ CurveSystemManager::CurveSystemManager() @@ -36,16 +82,16 @@ CurveSystemManager::CurveSystemManager() primitive = CURVE_LINE_SEGMENTS; line_method = CURVE_CORRECTED; interpolation = CURVE_CARDINAL; - triangle_method = CURVE_CAMERA; + triangle_method = CURVE_CAMERA_TRIANGLES; resolution = 3; segments = 1; + subdivisions = 3; normalmix = 1.0f; encasing_ratio = 1.01f; use_curves = true; use_smooth = true; - use_cache = true; use_parents = false; use_encasing = true; use_backfacing = false; @@ -75,31 +121,36 @@ void CurveSystemManager::device_update(Device *device, DeviceScene *dscene, Scen kcurve->curveflags = 0; - if(primitive == CURVE_SEGMENTS) - kcurve->curveflags |= CURVE_KN_INTERPOLATE; + if(use_curves) { + if(primitive == CURVE_SEGMENTS || primitive == CURVE_RIBBONS) + kcurve->curveflags |= CURVE_KN_INTERPOLATE; + if(primitive == CURVE_RIBBONS) + kcurve->curveflags |= CURVE_KN_RIBBONS; - if(line_method == CURVE_ACCURATE) - kcurve->curveflags |= CURVE_KN_ACCURATE; - if(line_method == CURVE_CORRECTED) - kcurve->curveflags |= CURVE_KN_INTERSECTCORRECTION; - if(line_method == CURVE_POSTCORRECTED) - kcurve->curveflags |= CURVE_KN_POSTINTERSECTCORRECTION; + if(line_method == CURVE_ACCURATE) + kcurve->curveflags |= CURVE_KN_ACCURATE; + if(line_method == CURVE_CORRECTED) + kcurve->curveflags |= CURVE_KN_INTERSECTCORRECTION; + if(line_method == CURVE_POSTCORRECTED) + kcurve->curveflags |= CURVE_KN_POSTINTERSECTCORRECTION; - if(use_tangent_normal) - kcurve->curveflags |= CURVE_KN_TANGENTGNORMAL; - if(use_tangent_normal_correction) - kcurve->curveflags |= CURVE_KN_NORMALCORRECTION; - if(use_tangent_normal_geometry) - kcurve->curveflags |= CURVE_KN_TRUETANGENTGNORMAL; - if(use_joined) - kcurve->curveflags |= CURVE_KN_CURVEDATA; - if(use_backfacing) - kcurve->curveflags |= CURVE_KN_BACKFACING; - if(use_encasing) - kcurve->curveflags |= CURVE_KN_ENCLOSEFILTER; + if(use_tangent_normal) + kcurve->curveflags |= CURVE_KN_TANGENTGNORMAL; + if(use_tangent_normal_correction) + kcurve->curveflags |= CURVE_KN_NORMALCORRECTION; + if(use_tangent_normal_geometry) + kcurve->curveflags |= CURVE_KN_TRUETANGENTGNORMAL; + if(use_joined) + kcurve->curveflags |= CURVE_KN_CURVEDATA; + if(use_backfacing) + kcurve->curveflags |= CURVE_KN_BACKFACING; + if(use_encasing) + kcurve->curveflags |= CURVE_KN_ENCLOSEFILTER; - kcurve->normalmix = normalmix; - kcurve->encasing_ratio = encasing_ratio; + kcurve->normalmix = normalmix; + kcurve->encasing_ratio = encasing_ratio; + kcurve->subdivisions = subdivisions; + } if(progress.get_cancel()) return; @@ -123,14 +174,14 @@ bool CurveSystemManager::modified(const CurveSystemManager& CurveSystemManager) encasing_ratio == CurveSystemManager.encasing_ratio && use_backfacing == CurveSystemManager.use_backfacing && normalmix == CurveSystemManager.normalmix && - use_cache == CurveSystemManager.use_cache && use_smooth == CurveSystemManager.use_smooth && triangle_method == CurveSystemManager.triangle_method && resolution == CurveSystemManager.resolution && use_curves == CurveSystemManager.use_curves && use_joined == CurveSystemManager.use_joined && segments == CurveSystemManager.segments && - use_parents == CurveSystemManager.use_parents); + use_parents == CurveSystemManager.use_parents && + subdivisions == CurveSystemManager.subdivisions); } bool CurveSystemManager::modified_mesh(const CurveSystemManager& CurveSystemManager) @@ -143,8 +194,7 @@ bool CurveSystemManager::modified_mesh(const CurveSystemManager& CurveSystemMana resolution == CurveSystemManager.resolution && use_curves == CurveSystemManager.use_curves && use_joined == CurveSystemManager.use_joined && - segments == CurveSystemManager.segments && - use_cache == CurveSystemManager.use_cache); + segments == CurveSystemManager.segments); } void CurveSystemManager::tag_update(Scene *scene) diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h index bb9ef6d99cf..3a12d33d0a7 100644 --- a/intern/cycles/render/curves.h +++ b/intern/cycles/render/curves.h @@ -29,6 +29,8 @@ class DeviceScene; class Progress; class Scene; +void curvebounds(float *lower, float *upper, float3 *p, int dim); + typedef enum curve_presets { CURVE_CUSTOM, CURVE_TANGENT_SHADING, @@ -39,13 +41,14 @@ typedef enum curve_presets { typedef enum curve_primitives { CURVE_TRIANGLES, CURVE_LINE_SEGMENTS, - CURVE_SEGMENTS + CURVE_SEGMENTS, + CURVE_RIBBONS } curve_primitives; typedef enum curve_triangles { - CURVE_CAMERA, - CURVE_RIBBONS, - CURVE_TESSELATED + CURVE_CAMERA_TRIANGLES, + CURVE_RIBBON_TRIANGLES, + CURVE_TESSELATED_TRIANGLES } curve_triangles; typedef enum curve_lines { @@ -98,13 +101,13 @@ public: int triangle_method; int resolution; int segments; + int subdivisions; float normalmix; float encasing_ratio; bool use_curves; bool use_smooth; - bool use_cache; bool use_parents; bool use_encasing; bool use_backfacing; diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index 14b219383d0..af27b46771c 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -708,7 +708,8 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight value2_in->value.x = 1.0f; weight_out = math_node->output("Value"); - disconnect(weight_in); + if(weight_in->link) + disconnect(weight_in); } /* connected to closure mix weight */ diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 230a12f9ff2..e6f8ab4a5d9 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -85,11 +85,21 @@ bool ImageManager::set_animation_frame_update(int frame) return false; } -bool ImageManager::is_float_image(const string& filename) +bool ImageManager::is_float_image(const string& filename, bool is_builtin) { - ImageInput *in = ImageInput::create(filename); bool is_float = false; + if(is_builtin) { + if(builtin_image_info_cb) { + int width, height, channels; + builtin_image_info_cb(filename, is_float, width, height, channels); + } + + return is_float; + } + + ImageInput *in = ImageInput::create(filename); + if(in) { ImageSpec spec; @@ -113,13 +123,13 @@ bool ImageManager::is_float_image(const string& filename) return is_float; } -int ImageManager::add_image(const string& filename, bool animated, bool& is_float) +int ImageManager::add_image(const string& filename, bool is_builtin, bool animated, bool& is_float) { Image *img; size_t slot; /* load image info and find out if we need a float texture */ - is_float = (pack_images)? false: is_float_image(filename); + is_float = (pack_images)? false: is_float_image(filename, is_builtin); if(is_float) { /* find existing image */ @@ -150,6 +160,7 @@ int ImageManager::add_image(const string& filename, bool animated, bool& is_floa /* add new image */ img = new Image(); img->filename = filename; + img->is_builtin = is_builtin; img->need_load = true; img->animated = animated; img->users = 1; @@ -184,6 +195,7 @@ int ImageManager::add_image(const string& filename, bool animated, bool& is_floa /* add new image */ img = new Image(); img->filename = filename; + img->is_builtin = is_builtin; img->need_load = true; img->animated = animated; img->users = 1; @@ -197,12 +209,12 @@ int ImageManager::add_image(const string& filename, bool animated, bool& is_floa return slot; } -void ImageManager::remove_image(const string& filename) +void ImageManager::remove_image(const string& filename, bool is_builtin) { size_t slot; for(slot = 0; slot < images.size(); slot++) { - if(images[slot] && images[slot]->filename == filename) { + if(images[slot] && images[slot]->filename == filename && images[slot]->is_builtin == is_builtin) { /* decrement user count */ images[slot]->users--; assert(images[slot]->users >= 0); @@ -220,7 +232,7 @@ void ImageManager::remove_image(const string& filename) if(slot == images.size()) { /* see if it's in a float texture slot */ for(slot = 0; slot < float_images.size(); slot++) { - if(float_images[slot] && float_images[slot]->filename == filename) { + if(float_images[slot] && float_images[slot]->filename == filename && float_images[slot]->is_builtin == is_builtin) { /* decrement user count */ float_images[slot]->users--; assert(float_images[slot]->users >= 0); @@ -242,27 +254,43 @@ bool ImageManager::file_load_image(Image *img, device_vector& tex_img) if(img->filename == "") return false; - /* load image from file through OIIO */ - ImageInput *in = ImageInput::create(img->filename); + ImageInput *in = NULL; + int width, height, components; - if(!in) - return false; + if(!img->is_builtin) { + /* load image from file through OIIO */ + in = ImageInput::create(img->filename); - ImageSpec spec; + if(!in) + return false; - if(!in->open(img->filename, spec)) { - delete in; - return false; + ImageSpec spec; + + if(!in->open(img->filename, spec)) { + delete in; + return false; + } + + width = spec.width; + height = spec.height; + components = spec.nchannels; + } + else { + /* load image using builtin images callbacks */ + if(!builtin_image_info_cb || !builtin_image_pixels_cb) + return false; + + bool is_float; + builtin_image_info_cb(img->filename, is_float, width, height, components); } /* we only handle certain number of components */ - int width = spec.width; - int height = spec.height; - int components = spec.nchannels; - if(!(components == 1 || components == 3 || components == 4)) { - in->close(); - delete in; + if(in) { + in->close(); + delete in; + } + return false; } @@ -270,14 +298,19 @@ bool ImageManager::file_load_image(Image *img, device_vector& tex_img) uchar *pixels = (uchar*)tex_img.resize(width, height); int scanlinesize = width*components*sizeof(uchar); - in->read_image(TypeDesc::UINT8, - (uchar*)pixels + (height-1)*scanlinesize, - AutoStride, - -scanlinesize, - AutoStride); + if(in) { + in->read_image(TypeDesc::UINT8, + (uchar*)pixels + (height-1)*scanlinesize, + AutoStride, + -scanlinesize, + AutoStride); - in->close(); - delete in; + in->close(); + delete in; + } + else { + builtin_image_pixels_cb(img->filename, pixels); + } if(components == 3) { for(int i = width*height-1; i >= 0; i--) { @@ -304,27 +337,42 @@ bool ImageManager::file_load_float_image(Image *img, device_vector& tex_ if(img->filename == "") return false; - /* load image from file through OIIO */ - ImageInput *in = ImageInput::create(img->filename); + ImageInput *in = NULL; + int width, height, components; - if(!in) - return false; + if(!img->is_builtin) { + /* load image from file through OIIO */ + in = ImageInput::create(img->filename); - ImageSpec spec; + if(!in) + return false; - if(!in->open(img->filename, spec)) { - delete in; - return false; + ImageSpec spec; + + if(!in->open(img->filename, spec)) { + delete in; + return false; + } + + /* we only handle certain number of components */ + width = spec.width; + height = spec.height; + components = spec.nchannels; + } + else { + /* load image using builtin images callbacks */ + if(!builtin_image_info_cb || !builtin_image_float_pixels_cb) + return false; + + bool is_float; + builtin_image_info_cb(img->filename, is_float, width, height, components); } - /* we only handle certain number of components */ - int width = spec.width; - int height = spec.height; - int components = spec.nchannels; - if(!(components == 1 || components == 3 || components == 4)) { - in->close(); - delete in; + if(in) { + in->close(); + delete in; + } return false; } @@ -332,14 +380,19 @@ bool ImageManager::file_load_float_image(Image *img, device_vector& tex_ float *pixels = (float*)tex_img.resize(width, height); int scanlinesize = width*components*sizeof(float); - in->read_image(TypeDesc::FLOAT, - (uchar*)pixels + (height-1)*scanlinesize, - AutoStride, - -scanlinesize, - AutoStride); + if(in) { + in->read_image(TypeDesc::FLOAT, + (uchar*)pixels + (height-1)*scanlinesize, + AutoStride, + -scanlinesize, + AutoStride); - in->close(); - delete in; + in->close(); + delete in; + } + else { + builtin_image_float_pixels_cb(img->filename, pixels); + } if(components == 3) { for(int i = width*height-1; i >= 0; i--) { diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 4d177174971..e39ac14b60f 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -51,9 +51,9 @@ public: ImageManager(); ~ImageManager(); - int add_image(const string& filename, bool animated, bool& is_float); - void remove_image(const string& filename); - bool is_float_image(const string& filename); + int add_image(const string& filename, bool is_builtin, bool animated, bool& is_float); + void remove_image(const string& filename, bool is_builtin); + bool is_float_image(const string& filename, bool is_builtin); void device_update(Device *device, DeviceScene *dscene, Progress& progress); void device_free(Device *device, DeviceScene *dscene); @@ -65,6 +65,9 @@ public: bool need_update; + boost::function builtin_image_info_cb; + boost::function builtin_image_pixels_cb; + boost::function builtin_image_float_pixels_cb; private: int tex_num_images; int tex_num_float_images; @@ -74,6 +77,7 @@ private: struct Image { string filename; + bool is_builtin; bool need_load; bool animated; diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 1b94d603a26..04fea1953e7 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -198,8 +198,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen bool have_emission = false; /* skip if we are not visible for BSDFs */ - if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT))) + if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT))) { + j++; continue; + } /* skip if we have no emission shaders */ foreach(uint sindex, mesh->used_shaders) { diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index d4619dcff55..57776e4cfa6 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -43,6 +43,7 @@ Mesh::Mesh() need_update = true; transform_applied = false; transform_negative_scaled = false; + transform_normal = transform_identity(); displacement_method = DISPLACE_BUMP; bounds = BoundBox::empty; @@ -94,6 +95,7 @@ void Mesh::clear() transform_applied = false; transform_negative_scaled = false; + transform_normal = transform_identity(); } void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_) @@ -151,7 +153,7 @@ void Mesh::add_face_normals() /* don't compute if already there */ if(attributes.find(ATTR_STD_FACE_NORMAL)) return; - + /* get attributes */ Attribute *attr_fN = attributes.add(ATTR_STD_FACE_NORMAL); float3 *fN = attr_fN->data_float3(); @@ -181,6 +183,14 @@ void Mesh::add_face_normals() fN[i] = -fN[i]; } } + + /* expected to be in local space */ + if(transform_applied) { + Transform ntfm = transform_inverse(transform_normal); + + for(size_t i = 0; i < triangles_size; i++) + fN[i] = normalize(transform_direction(&ntfm, fN[i])); + } } void Mesh::add_vertex_normals() @@ -188,7 +198,7 @@ void Mesh::add_vertex_normals() /* don't compute if already there */ if(attributes.find(ATTR_STD_VERTEX_NORMAL)) return; - + /* get attributes */ Attribute *attr_fN = attributes.find(ATTR_STD_FACE_NORMAL); Attribute *attr_vN = attributes.add(ATTR_STD_VERTEX_NORMAL); @@ -232,10 +242,18 @@ void Mesh::pack_normals(Scene *scene, float4 *normal, float4 *vnormal) size_t triangles_size = triangles.size(); uint *shader_ptr = (shader.size())? &shader[0]: NULL; + bool do_transform = transform_applied; + Transform ntfm = transform_normal; + for(size_t i = 0; i < triangles_size; i++) { - normal[i].x = fN[i].x; - normal[i].y = fN[i].y; - normal[i].z = fN[i].z; + float3 fNi = fN[i]; + + if(do_transform) + fNi = normalize(transform_direction(&ntfm, fNi)); + + normal[i].x = fNi.x; + normal[i].y = fNi.y; + normal[i].z = fNi.z; /* stuff shader id in here too */ if(shader_ptr[i] != last_shader || last_smooth != smooth[i]) { @@ -249,8 +267,14 @@ void Mesh::pack_normals(Scene *scene, float4 *normal, float4 *vnormal) size_t verts_size = verts.size(); - for(size_t i = 0; i < verts_size; i++) - vnormal[i] = make_float4(vN[i].x, vN[i].y, vN[i].z, 0.0f); + for(size_t i = 0; i < verts_size; i++) { + float3 vNi = vN[i]; + + if(do_transform) + vNi = normalize(transform_direction(&ntfm, vNi)); + + vnormal[i] = make_float4(vNi.x, vNi.y, vNi.z, 0.0f); + } } void Mesh::pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset) diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index b83752ad8df..dca1b00e1ff 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -90,6 +90,7 @@ public: BoundBox bounds; bool transform_applied; bool transform_negative_scaled; + Transform transform_normal; DisplacementMethod displacement_method; /* Update Flags */ diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 14ef3c68ad3..5444299b948 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -142,8 +142,9 @@ ImageTextureNode::ImageTextureNode() slot = -1; is_float = -1; filename = ""; + is_builtin = false; color_space = ustring("Color"); - projection = ustring("Flat");; + projection = ustring("Flat"); projection_blend = 0.0f; animated = false; @@ -155,7 +156,7 @@ ImageTextureNode::ImageTextureNode() ImageTextureNode::~ImageTextureNode() { if(image_manager) - image_manager->remove_image(filename); + image_manager->remove_image(filename, is_builtin); } ShaderNode *ImageTextureNode::clone() const @@ -176,7 +177,7 @@ void ImageTextureNode::compile(SVMCompiler& compiler) image_manager = compiler.image_manager; if(is_float == -1) { bool is_float_bool; - slot = image_manager->add_image(filename, animated, is_float_bool); + slot = image_manager->add_image(filename, is_builtin, animated, is_float_bool); is_float = (int)is_float_bool; } @@ -237,7 +238,7 @@ void ImageTextureNode::compile(OSLCompiler& compiler) tex_mapping.compile(compiler); if(is_float == -1) - is_float = (int)image_manager->is_float_image(filename); + is_float = (int)image_manager->is_float_image(filename, false); compiler.parameter("filename", filename.c_str()); if(is_float || color_space != "Color") @@ -271,6 +272,7 @@ EnvironmentTextureNode::EnvironmentTextureNode() slot = -1; is_float = -1; filename = ""; + is_builtin = false; color_space = ustring("Color"); projection = ustring("Equirectangular"); animated = false; @@ -283,7 +285,7 @@ EnvironmentTextureNode::EnvironmentTextureNode() EnvironmentTextureNode::~EnvironmentTextureNode() { if(image_manager) - image_manager->remove_image(filename); + image_manager->remove_image(filename, is_builtin); } ShaderNode *EnvironmentTextureNode::clone() const @@ -304,7 +306,7 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler) image_manager = compiler.image_manager; if(slot == -1) { bool is_float_bool; - slot = image_manager->add_image(filename, animated, is_float_bool); + slot = image_manager->add_image(filename, is_builtin, animated, is_float_bool); is_float = (int)is_float_bool; } @@ -354,7 +356,7 @@ void EnvironmentTextureNode::compile(OSLCompiler& compiler) tex_mapping.compile(compiler); if(is_float == -1) - is_float = (int)image_manager->is_float_image(filename); + is_float = (int)image_manager->is_float_image(filename, false); compiler.parameter("filename", filename.c_str()); compiler.parameter("projection", projection); @@ -3255,6 +3257,8 @@ void NormalMapNode::attributes(AttributeRequestSet *attributes) attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str())); attributes->add(ustring((string(attribute.c_str()) + ".tangent_sign").c_str())); } + + attributes->add(ATTR_STD_VERTEX_NORMAL); } ShaderNode::attributes(attributes); diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 564ceee5a5b..8b2d6a0e5c8 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -70,6 +70,7 @@ public: int slot; int is_float; string filename; + bool is_builtin; ustring color_space; ustring projection; float projection_blend; @@ -89,6 +90,7 @@ public: int slot; int is_float; string filename; + bool is_builtin; ustring color_space; ustring projection; bool animated; diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index a89f8afd251..8d8087266c1 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -91,38 +91,16 @@ void Object::apply_transform() for(size_t i = 0; i < mesh->curve_keys.size(); i++) mesh->curve_keys[i].co = transform_point(&tfm, mesh->curve_keys[i].co); - Attribute *attr_tangent = mesh->curve_attributes.find(ATTR_STD_CURVE_TANGENT); - Attribute *attr_fN = mesh->attributes.find(ATTR_STD_FACE_NORMAL); - Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL); - - Transform ntfm = transform_transpose(transform_inverse(tfm)); + /* store matrix to transform later. when accessing these as attributes we + * do not want the transform to be applied for consistency between static + * and dynamic BVH, so we do it on packing. */ + mesh->transform_normal = transform_transpose(transform_inverse(tfm)); /* we keep normals pointing in same direction on negative scale, notify * mesh about this in it (re)calculates normals */ if(transform_negative_scale(tfm)) mesh->transform_negative_scaled = true; - if(attr_fN) { - float3 *fN = attr_fN->data_float3(); - - for(size_t i = 0; i < mesh->triangles.size(); i++) - fN[i] = transform_direction(&ntfm, fN[i]); - } - - if(attr_vN) { - float3 *vN = attr_vN->data_float3(); - - for(size_t i = 0; i < mesh->verts.size(); i++) - vN[i] = transform_direction(&ntfm, vN[i]); - } - - if(attr_tangent) { - float3 *tangent = attr_tangent->data_float3(); - - for(size_t i = 0; i < mesh->curve_keys.size(); i++) - tangent[i] = transform_direction(&tfm, tangent[i]); - } - if(bounds.valid()) { mesh->compute_bounds(); compute_bounds(false, 0.0f); diff --git a/intern/cycles/util/util_cuda.cpp b/intern/cycles/util/util_cuda.cpp index 12cb0d3e254..6c9ee7c548f 100644 --- a/intern/cycles/util/util_cuda.cpp +++ b/intern/cycles/util/util_cuda.cpp @@ -376,21 +376,23 @@ bool cuLibraryInit() /* cuda 4.0 */ CUDA_LIBRARY_FIND(cuCtxSetCurrent); -#ifndef WITH_CUDA_BINARIES -#ifdef _WIN32 - return false; /* runtime build doesn't work at the moment */ -#else - if(cuCompilerPath() == "") - return false; + if(cuHavePrecompiledKernels()) + result = true; +#ifndef _WIN32 + else if(cuCompilerPath() != "") + result = true; #endif -#endif - - /* success */ - result = true; return result; } +bool cuHavePrecompiledKernels() +{ + string cubins_path = path_get("lib"); + + return path_exists(cubins_path); +} + string cuCompilerPath() { #ifdef _WIN32 diff --git a/intern/cycles/util/util_cuda.h b/intern/cycles/util/util_cuda.h index 9682f1cfe1d..69cf025de77 100644 --- a/intern/cycles/util/util_cuda.h +++ b/intern/cycles/util/util_cuda.h @@ -30,6 +30,7 @@ CCL_NAMESPACE_BEGIN * matrixMulDynlinkJIT in the CUDA SDK. */ bool cuLibraryInit(); +bool cuHavePrecompiledKernels(); string cuCompilerPath(); CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp index 8c4ec312256..43f15ba0ce6 100644 --- a/intern/cycles/util/util_task.cpp +++ b/intern/cycles/util/util_task.cpp @@ -152,7 +152,6 @@ void TaskPool::num_increase() thread_mutex TaskScheduler::mutex; int TaskScheduler::users = 0; vector TaskScheduler::threads; -vector TaskScheduler::thread_level; volatile bool TaskScheduler::do_exit = false; list TaskScheduler::queue; @@ -179,12 +178,9 @@ void TaskScheduler::init(int num_threads) /* launch threads that will be waiting for work */ threads.resize(num_threads); - thread_level.resize(num_threads); - for(size_t i = 0; i < threads.size(); i++) { + for(size_t i = 0; i < threads.size(); i++) threads[i] = new thread(function_bind(&TaskScheduler::thread_run, i)); - thread_level[i] = 0; - } } users++; @@ -208,7 +204,6 @@ void TaskScheduler::exit() } threads.clear(); - thread_level.clear(); } } diff --git a/intern/cycles/util/util_task.h b/intern/cycles/util/util_task.h index b795ca7524b..5bca3f255af 100644 --- a/intern/cycles/util/util_task.h +++ b/intern/cycles/util/util_task.h @@ -111,7 +111,6 @@ protected: static thread_mutex mutex; static int users; static vector threads; - static vector thread_level; static volatile bool do_exit; static list queue; diff --git a/intern/dualcon/intern/MemoryAllocator.h b/intern/dualcon/intern/MemoryAllocator.h index b704542d27b..e673d9498d2 100644 --- a/intern/dualcon/intern/MemoryAllocator.h +++ b/intern/dualcon/intern/MemoryAllocator.h @@ -43,6 +43,8 @@ class VirtualMemoryAllocator { public: +virtual ~VirtualMemoryAllocator() {} + virtual void *allocate( ) = 0; virtual void deallocate(void *obj) = 0; virtual void destroy( ) = 0; diff --git a/intern/ffmpeg/ffmpeg_compat.h b/intern/ffmpeg/ffmpeg_compat.h index 37cde2c2837..c07dc869291 100644 --- a/intern/ffmpeg/ffmpeg_compat.h +++ b/intern/ffmpeg/ffmpeg_compat.h @@ -33,6 +33,7 @@ #include #include #include +#include #if (LIBAVFORMAT_VERSION_MAJOR > 52) || ((LIBAVFORMAT_VERSION_MAJOR >= 52) && (LIBAVFORMAT_VERSION_MINOR >= 101)) #define FFMPEG_HAVE_PARSE_UTILS 1 @@ -75,10 +76,68 @@ #define FFMPEG_FFV1_ALPHA_SUPPORTED #endif +#if ((LIBAVUTIL_VERSION_MAJOR < 51) || (LIBAVUTIL_VERSION_MAJOR == 51) && (LIBAVUTIL_VERSION_MINOR < 22)) +static inline +int av_opt_set(void *obj, const char *name, const char *val, int search_flags) +{ + const AVOption *rv = NULL; + av_set_string3(obj, name, val, 1, &rv); + return rv != NULL; +} + +static inline +int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags) +{ + const AVOption *rv = NULL; + rv = av_set_int(obj, name, val); + return rv != NULL; +} + +static inline +int av_opt_set_double(void *obj, const char *name, double val, int search_flags) +{ + const AVOption *rv = NULL; + rv = av_set_double(obj, name, val); + return rv != NULL; +} + +#define AV_OPT_TYPE_INT FF_OPT_TYPE_INT +#define AV_OPT_TYPE_INT64 FF_OPT_TYPE_INT64 +#define AV_OPT_TYPE_STRING FF_OPT_TYPE_STRING +#define AV_OPT_TYPE_CONST FF_OPT_TYPE_CONST +#define AV_OPT_TYPE_DOUBLE FF_OPT_TYPE_DOUBLE +#define AV_OPT_TYPE_FLOAT FF_OPT_TYPE_FLOAT +#endif + #if ((LIBAVFORMAT_VERSION_MAJOR < 53) || ((LIBAVFORMAT_VERSION_MAJOR == 53) && (LIBAVFORMAT_VERSION_MINOR < 24)) || ((LIBAVFORMAT_VERSION_MAJOR == 53) && (LIBAVFORMAT_VERSION_MINOR < 24) && (LIBAVFORMAT_VERSION_MICRO < 2))) #define avformat_close_input(x) av_close_input_file(*(x)) #endif +#if ((LIBAVCODEC_VERSION_MAJOR < 53) || (LIBAVCODEC_VERSION_MAJOR == 53 && LIBAVCODEC_VERSION_MINOR < 35)) +static inline +int avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options) +{ + /* TODO: no options are taking into account */ + return avcodec_open(avctx, codec); +} +#endif + +#if ((LIBAVFORMAT_VERSION_MAJOR < 53) || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR < 21)) +static inline +AVStream *avformat_new_stream(AVFormatContext *s, AVCodec *c) +{ + /* TODO: no codec is taking into account */ + return av_new_stream(s, 0); +} + +static inline +int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) +{ + /* TODO: no options are taking into account */ + return av_find_stream_info(ic); +} +#endif + #if ((LIBAVFORMAT_VERSION_MAJOR > 53) || ((LIBAVFORMAT_VERSION_MAJOR == 53) && (LIBAVFORMAT_VERSION_MINOR > 32)) || ((LIBAVFORMAT_VERSION_MAJOR == 53) && (LIBAVFORMAT_VERSION_MINOR == 24) && (LIBAVFORMAT_VERSION_MICRO >= 100))) static inline void my_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp) diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index ab5feb287d8..ffdee6c1550 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -860,7 +860,7 @@ extern int GHOST_UseNativePixels(void); /** * If window was opened using native pixel size, it returns scaling factor. */ -extern float GHOST_GetNativePixelSize(void); +extern float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle); #ifdef __cplusplus diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index dfe01521a29..1b3509c1ac3 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -297,10 +297,8 @@ public: /** * Native pixel size support (MacBook 'retina'). - * \return The pixel size in float. */ virtual bool useNativePixel(void) = 0; - virtual float getNativePixelSize(void) = 0; /*************************************************************************************** * Event management functionality diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index 88f130aabe8..4cf0dbfb820 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -305,6 +305,10 @@ public: */ virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds, GHOST_TInt32 mouse_ungrab_xy[2]) { return GHOST_kSuccess; } + + virtual float getNativePixelSize(void) = 0; + + #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IWindow") #endif diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 868d787b5f9..35dff73f4af 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -183,6 +183,7 @@ typedef enum { GHOST_kEventDraggingDropDone, GHOST_kEventOpenMainFile, // Needed for Cocoa to open double-clicked .blend file at startup + GHOST_kEventNativeResolutionChange, // Needed for Cocoa when window moves to other display GHOST_kEventTimer, diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index ba0a6eba36f..be64acf8c94 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -885,9 +885,11 @@ int GHOST_UseNativePixels(void) return system->useNativePixel(); } -float GHOST_GetNativePixelSize(void) +float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle) { - GHOST_ISystem *system = GHOST_ISystem::getSystem(); - return system->getNativePixelSize(); + GHOST_IWindow *window = (GHOST_IWindow *) windowhandle; + if (window) + return window->getNativePixelSize(); + return 1.0f; } diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h index f0db1b3de8d..9292235a9c7 100644 --- a/intern/ghost/intern/GHOST_Debug.h +++ b/intern/ghost/intern/GHOST_Debug.h @@ -58,12 +58,23 @@ # define GHOST_PRINTF(x, ...) #endif // GHOST_DEBUG - -#ifdef GHOST_DEBUG +#ifdef WITH_ASSERT_ABORT +# include //for fprintf() +# include //for abort() +# define GHOST_ASSERT(x, info) \ + { \ + if (!(x)) { \ + fprintf(stderr, "GHOST_ASSERT failed: "); \ + fprintf(stderr, info); \ + fprintf(stderr, "\n"); \ + abort(); \ + } \ + } (void)0 +#elif defined(GHOST_DEBUG) # define GHOST_ASSERT(x, info) \ { \ if (!(x)) { \ - GHOST_PRINT("assertion failed: "); \ + GHOST_PRINT("GHOST_ASSERT failed: "); \ GHOST_PRINT(info); \ GHOST_PRINT("\n"); \ } \ diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp index 83df9971158..0bfc67a9126 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp @@ -52,11 +52,15 @@ GHOST_DisplayManagerWin32::GHOST_DisplayManagerWin32(void) GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplays(GHOST_TUns8& numDisplays) const { - // We do not support multiple monitors at the moment numDisplays = ::GetSystemMetrics(SM_CMONITORS); return numDisplays > 0 ? GHOST_kSuccess : GHOST_kFailure; } +static BOOL get_dd(DWORD d, DISPLAY_DEVICE* dd) +{ + dd->cb = sizeof(DISPLAY_DEVICE); + return ::EnumDisplayDevices(NULL, d, dd, 0); +} /* * When you call EnumDisplaySettings with iModeNum set to zero, the operating system @@ -67,10 +71,12 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplays(GHOST_TUns8& numDisplay */ GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const { - GHOST_ASSERT((display == kMainDisplay), "GHOST_DisplayManagerWin32::getNumDisplaySettings(): only main displlay is supported"); + DISPLAY_DEVICE display_device; + if (!get_dd(display, &display_device)) return GHOST_kFailure; + numSettings = 0; DEVMODE dm; - while (::EnumDisplaySettings(NULL, numSettings, &dm)) { + while (::EnumDisplaySettings(display_device.DeviceName, numSettings, &dm)) { numSettings++; } return GHOST_kSuccess; @@ -79,10 +85,12 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplaySettings(GHOST_TUns8 disp GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const { - GHOST_ASSERT((display == kMainDisplay), "GHOST_DisplayManagerWin32::getDisplaySetting(): only main display is supported"); + DISPLAY_DEVICE display_device; + if (!get_dd(display, &display_device)) return GHOST_kFailure; + GHOST_TSuccess success; DEVMODE dm; - if (::EnumDisplaySettings(NULL, index, &dm)) { + if (::EnumDisplaySettings(display_device.DeviceName, index, &dm)) { #ifdef GHOST_DEBUG printf("display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency); #endif // GHOST_DEBUG @@ -112,23 +120,23 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(GHOST_TUns8 display, GHOST_TSuccess GHOST_DisplayManagerWin32::getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const { - GHOST_ASSERT((display == kMainDisplay), "GHOST_DisplayManagerWin32::getCurrentDisplaySetting(): only main display is supported"); - return getDisplaySetting(kMainDisplay, ENUM_CURRENT_SETTINGS, setting); + return getDisplaySetting(display, ENUM_CURRENT_SETTINGS, setting); } GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting) { - GHOST_ASSERT((display == kMainDisplay), "GHOST_DisplayManagerWin32::setCurrentDisplaySetting(): only main display is supported"); + DISPLAY_DEVICE display_device; + if (!get_dd(display, &display_device)) return GHOST_kFailure; GHOST_DisplaySetting match; findMatch(display, setting, match); DEVMODE dm; int i = 0; - while (::EnumDisplaySettings(NULL, i++, &dm)) { - if ((dm.dmBitsPerPel == match.bpp) && - (dm.dmPelsWidth == match.xPixels) && - (dm.dmPelsHeight == match.yPixels) && + while (::EnumDisplaySettings(display_device.DeviceName, i++, &dm)) { + if ((dm.dmBitsPerPel == match.bpp ) && + (dm.dmPelsWidth == match.xPixels) && + (dm.dmPelsHeight == match.yPixels) && (dm.dmDisplayFrequency == match.frequency)) { break; diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index 41beeac6b51..080619bc0ac 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -46,7 +46,6 @@ GHOST_System::GHOST_System() : m_nativePixel(false), - m_nativePixelSize(1), m_displayManager(0), m_timerManager(0), m_windowManager(0), @@ -382,9 +381,3 @@ bool GHOST_System::useNativePixel(void) return 1; } -float GHOST_System::getNativePixelSize(void) -{ - if (m_nativePixel) - return m_nativePixelSize; - return 1.0f; -} diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index 5060f22c509..928bbe6a31b 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -175,9 +175,6 @@ public: virtual bool useNativePixel(void); bool m_nativePixel; - virtual float getNativePixelSize(void); - float m_nativePixelSize; - /*************************************************************************************** * Event management functionality ***************************************************************************************/ diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index ac3e22368bc..1665180b687 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -1038,6 +1038,10 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) ); break; case GHOST_kEventWindowUpdate: + if (m_nativePixel) { + window->setNativePixelSize(); + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventNativeResolutionChange, window) ); + } pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) ); break; case GHOST_kEventWindowMove: @@ -1054,6 +1058,13 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, //m_ignoreWindowSizedMessages = true; } break; + case GHOST_kEventNativeResolutionChange: + + if (m_nativePixel) { + window->setNativePixelSize(); + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventNativeResolutionChange, window) ); + } + default: return GHOST_kFailure; break; @@ -1592,7 +1603,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) } break; - /* these events only happen on swiping trackpads */ + /* these events only happen on swiping trackpads or tablets */ + /* warning: using tablet + trackpad at same time frustrates this static variable */ case NSEventTypeBeginGesture: m_hasMultiTouchTrackpad = 1; break; @@ -1626,9 +1638,17 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) double dy; #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 + int phase = [event phase]; + /* with 10.7 nice scrolling deltas are supported */ dx = [event scrollingDeltaX]; dy = [event scrollingDeltaY]; + + /* however, wacom tablet (intuos5) needs old deltas, it then has momentum and phase at zero */ + if (phase == 0 && momentum==NULL) { + dx = [event deltaX]; + dy = [event deltaY]; + } #else /* trying to pretend you have nice scrolls... */ diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 75d606a5d79..50d7b372dd6 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -783,8 +783,8 @@ GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType, void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO *minmax) { - minmax->ptMinTrackSize.x = 640; - minmax->ptMinTrackSize.y = 480; + minmax->ptMinTrackSize.x = 320; + minmax->ptMinTrackSize.y = 240; } #ifdef WITH_INPUT_NDOF diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index f5cb0d9323c..28a228b2777 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -69,8 +69,10 @@ #include /* for fprintf only */ #include /* for exit */ -static GHOST_TKey -convertXKey(KeySym key); +/* for debugging - so we can breakpoint X11 errors */ +// #define USE_X11_ERROR_HANDLERS + +static GHOST_TKey convertXKey(KeySym key); /* these are for copy and select copy */ static char *txt_cut_buffer = NULL; @@ -91,6 +93,11 @@ GHOST_SystemX11( abort(); /* was return before, but this would just mean it will crash later */ } +#ifdef USE_X11_ERROR_HANDLERS + (void) XSetErrorHandler(GHOST_X11_ApplicationErrorHandler); + (void) XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler); +#endif + #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING) /* note -- don't open connection to XIM server here, because the locale * has to be set before opening the connection but setlocale() has not @@ -146,6 +153,12 @@ GHOST_SystemX11( XkbSetDetectableAutoRepeat(m_display, true, NULL); } +#ifdef WITH_X11_XINPUT + /* initialize incase X11 fails to load */ + memset(&m_xtablet, 0, sizeof(m_xtablet)); + + initXInputDevices(); +#endif } GHOST_SystemX11:: @@ -157,6 +170,15 @@ GHOST_SystemX11:: } #endif +#ifdef WITH_X11_XINPUT + /* close tablet devices */ + if (m_xtablet.StylusDevice) + XCloseDevice(m_display, m_xtablet.StylusDevice); + + if (m_xtablet.EraserDevice) + XCloseDevice(m_display, m_xtablet.EraserDevice); +#endif /* WITH_X11_XINPUT */ + XCloseDisplay(m_display); } @@ -494,12 +516,52 @@ processEvents( #ifdef WITH_X11_XINPUT /* set currently using tablet mode (stylus or eraser) depending on device ID */ -static void setTabletMode(GHOST_WindowX11 *window, XID deviceid) +static void setTabletMode(GHOST_SystemX11 *system, GHOST_WindowX11 *window, XID deviceid) { - if (deviceid == window->GetXTablet().StylusID) - window->GetXTablet().CommonData.Active = GHOST_kTabletModeStylus; - else if (deviceid == window->GetXTablet().EraserID) - window->GetXTablet().CommonData.Active = GHOST_kTabletModeEraser; + if (deviceid == system->GetXTablet().StylusID) + window->GetTabletData()->Active = GHOST_kTabletModeStylus; + else if (deviceid == system->GetXTablet().EraserID) + window->GetTabletData()->Active = GHOST_kTabletModeEraser; +} +#endif /* WITH_X11_XINPUT */ + +#ifdef WITH_X11_XINPUT +static bool checkTabletProximity(Display *display, XDevice *device) +{ + /* we could have true/false/not-found return value, but for now false is OK */ + + /* see: state.c from xinput, to get more data out of the device */ + XDeviceState *state; + + if (device == NULL) { + return false; + } + + state = XQueryDeviceState(display, device); + + if (state) { + XInputClass *cls = state->data; + // printf("%d class%s :\n", state->num_classes, + // (state->num_classes > 1) ? "es" : ""); + for (int loop = 0; loop < state->num_classes; loop++) { + switch (cls->c_class) { + case ValuatorClass: + XValuatorState *val_state = (XValuatorState *)cls; + // printf("ValuatorClass Mode=%s Proximity=%s\n", + // val_state->mode & 1 ? "Absolute" : "Relative", + // val_state->mode & 2 ? "Out" : "In"); + + if ((val_state->mode & 2) == 0) { + XFreeDeviceState(state); + return true; + } + break; + } + cls = (XInputClass *) ((char *)cls + cls->length); + } + XFreeDeviceState(state); + } + return false; } #endif /* WITH_X11_XINPUT */ @@ -512,7 +574,23 @@ GHOST_SystemX11::processEvent(XEvent *xe) if (!window) { return; } - + +#ifdef WITH_X11_XINPUT + /* Proximity-Out Events are not reliable, if the tablet is active - check on each event + * this adds a little overhead but only while the tablet is in use. + * in the futire we could have a ghost call window->CheckTabletProximity() + * but for now enough parts of the code are checking 'Active' + * - campbell */ + if (window->GetTabletData()->Active != GHOST_kTabletModeNone) { + if (checkTabletProximity(xe->xany.display, m_xtablet.StylusDevice) == false && + checkTabletProximity(xe->xany.display, m_xtablet.EraserDevice) == false) + { + // printf("proximity disable\n"); + window->GetTabletData()->Active = GHOST_kTabletModeNone; + } + } +#endif /* WITH_X11_XINPUT */ + switch (xe->type) { case Expose: { @@ -537,7 +615,7 @@ GHOST_SystemX11::processEvent(XEvent *xe) XMotionEvent &xme = xe->xmotion; #ifdef WITH_X11_XINPUT - bool is_tablet = window->GetXTablet().CommonData.Active != GHOST_kTabletModeNone; + bool is_tablet = window->GetTabletData()->Active != GHOST_kTabletModeNone; #else bool is_tablet = false; #endif @@ -983,31 +1061,31 @@ GHOST_SystemX11::processEvent(XEvent *xe) default: { #ifdef WITH_X11_XINPUT - if (xe->type == window->GetXTablet().MotionEvent) { + if (xe->type == m_xtablet.MotionEvent) { XDeviceMotionEvent *data = (XDeviceMotionEvent *)xe; /* stroke might begin without leading ProxyIn event, * this happens when window is opened when stylus is already hovering * around tablet surface */ - setTabletMode(window, data->deviceid); + setTabletMode(this, window, data->deviceid); - window->GetXTablet().CommonData.Pressure = - data->axis_data[2] / ((float)window->GetXTablet().PressureLevels); + window->GetTabletData()->Pressure = + data->axis_data[2] / ((float)m_xtablet.PressureLevels); /* the (short) cast and the &0xffff is bizarre and unexplained anywhere, * but I got garbage data without it. Found it in the xidump.c source --matt */ - window->GetXTablet().CommonData.Xtilt = - (short)(data->axis_data[3] & 0xffff) / ((float)window->GetXTablet().XtiltLevels); - window->GetXTablet().CommonData.Ytilt = - (short)(data->axis_data[4] & 0xffff) / ((float)window->GetXTablet().YtiltLevels); + window->GetTabletData()->Xtilt = + (short)(data->axis_data[3] & 0xffff) / ((float)m_xtablet.XtiltLevels); + window->GetTabletData()->Ytilt = + (short)(data->axis_data[4] & 0xffff) / ((float)m_xtablet.YtiltLevels); } - else if (xe->type == window->GetXTablet().ProxInEvent) { + else if (xe->type == m_xtablet.ProxInEvent) { XProximityNotifyEvent *data = (XProximityNotifyEvent *)xe; - setTabletMode(window, data->deviceid); + setTabletMode(this, window, data->deviceid); } - else if (xe->type == window->GetXTablet().ProxOutEvent) { - window->GetXTablet().CommonData.Active = GHOST_kTabletModeNone; + else if (xe->type == m_xtablet.ProxOutEvent) { + window->GetTabletData()->Active = GHOST_kTabletModeNone; } #endif // WITH_X11_XINPUT break; @@ -1648,3 +1726,197 @@ GHOST_TSuccess GHOST_SystemX11::pushDragDropEvent(GHOST_TEventType eventType, ); } #endif + +#ifdef WITH_X11_XINPUT +/* + * Dummy function to get around IO Handler exiting if device invalid + * Basically it will not crash blender now if you have a X device that + * is configured but not plugged in. + */ +int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent) +{ + fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n", + theEvent->error_code, theEvent->request_code); + + /* No exit! - but keep lint happy */ + return 0; +} + +int GHOST_X11_ApplicationIOErrorHandler(Display *display) +{ + fprintf(stderr, "Ignoring Xlib error: error IO\n"); + + /* No exit! - but keep lint happy */ + return 0; +} + +/* These C functions are copied from Wine 1.1.13's wintab.c */ +#define BOOL int +#define TRUE 1 +#define FALSE 0 + +static bool match_token(const char *haystack, const char *needle) +{ + const char *p, *q; + for (p = haystack; *p; ) + { + while (*p && isspace(*p)) + p++; + if (!*p) + break; + + for (q = needle; *q && *p && tolower(*p) == tolower(*q); q++) + p++; + if (!*q && (isspace(*p) || !*p)) + return TRUE; + + while (*p && !isspace(*p)) + p++; + } + return FALSE; +} + + +/* Determining if an X device is a Tablet style device is an imperfect science. + * We rely on common conventions around device names as well as the type reported + * by Wacom tablets. This code will likely need to be expanded for alternate tablet types + * + * Wintab refers to any device that interacts with the tablet as a cursor, + * (stylus, eraser, tablet mouse, airbrush, etc) + * this is not to be confused with wacom x11 configuration "cursor" device. + * Wacoms x11 config "cursor" refers to its device slot (which we mirror with + * our gSysCursors) for puck like devices (tablet mice essentially). + */ +#if 0 // unused +static BOOL is_tablet_cursor(const char *name, const char *type) +{ + int i; + static const char *tablet_cursor_whitelist[] = { + "wacom", + "wizardpen", + "acecad", + "tablet", + "cursor", + "stylus", + "eraser", + "pad", + NULL + }; + + for (i = 0; tablet_cursor_whitelist[i] != NULL; i++) { + if (name && match_token(name, tablet_cursor_whitelist[i])) + return TRUE; + if (type && match_token(type, tablet_cursor_whitelist[i])) + return TRUE; + } + return FALSE; +} +#endif +static BOOL is_stylus(const char *name, const char *type) +{ + int i; + static const char *tablet_stylus_whitelist[] = { + "stylus", + "wizardpen", + "acecad", + NULL + }; + + for (i = 0; tablet_stylus_whitelist[i] != NULL; i++) { + if (name && match_token(name, tablet_stylus_whitelist[i])) + return TRUE; + if (type && match_token(type, tablet_stylus_whitelist[i])) + return TRUE; + } + + return FALSE; +} + +static BOOL is_eraser(const char *name, const char *type) +{ + if (name && match_token(name, "eraser")) + return TRUE; + if (type && match_token(type, "eraser")) + return TRUE; + return FALSE; +} +#undef BOOL +#undef TRUE +#undef FALSE +/* end code copied from wine */ + +void GHOST_SystemX11::initXInputDevices() +{ + static XErrorHandler old_handler = (XErrorHandler) 0; + static XIOErrorHandler old_handler_io = (XIOErrorHandler) 0; + + XExtensionVersion *version = XGetExtensionVersion(m_display, INAME); + + if (version && (version != (XExtensionVersion *)NoSuchExtension)) { + if (version->present) { + int device_count; + XDeviceInfo *device_info = XListInputDevices(m_display, &device_count); + m_xtablet.StylusDevice = NULL; + m_xtablet.EraserDevice = NULL; + + /* Install our error handler to override Xlib's termination behavior */ + old_handler = XSetErrorHandler(GHOST_X11_ApplicationErrorHandler); + old_handler_io = XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler); + + for (int i = 0; i < device_count; ++i) { + char *device_type = device_info[i].type ? XGetAtomName(m_display, device_info[i].type) : NULL; + +// printf("Tablet type:'%s', name:'%s', index:%d\n", device_type, device_info[i].name, i); + + + if (m_xtablet.StylusDevice == NULL && is_stylus(device_info[i].name, device_type)) { +// printf("\tfound stylus\n"); + m_xtablet.StylusID = device_info[i].id; + m_xtablet.StylusDevice = XOpenDevice(m_display, m_xtablet.StylusID); + + if (m_xtablet.StylusDevice != NULL) { + /* Find how many pressure levels tablet has */ + XAnyClassPtr ici = device_info[i].inputclassinfo; + for (int j = 0; j < m_xtablet.StylusDevice->num_classes; ++j) { + if (ici->c_class == ValuatorClass) { +// printf("\t\tfound ValuatorClass\n"); + XValuatorInfo *xvi = (XValuatorInfo *)ici; + m_xtablet.PressureLevels = xvi->axes[2].max_value; + + /* this is assuming that the tablet has the same tilt resolution in both + * positive and negative directions. It would be rather weird if it didn't.. */ + m_xtablet.XtiltLevels = xvi->axes[3].max_value; + m_xtablet.YtiltLevels = xvi->axes[4].max_value; + break; + } + + ici = (XAnyClassPtr)(((char *)ici) + ici->length); + } + } + else { + m_xtablet.StylusID = 0; + } + } + else if (m_xtablet.EraserDevice == NULL && is_eraser(device_info[i].name, device_type)) { +// printf("\tfound eraser\n"); + m_xtablet.EraserID = device_info[i].id; + m_xtablet.EraserDevice = XOpenDevice(m_display, m_xtablet.EraserID); + if (m_xtablet.EraserDevice == NULL) m_xtablet.EraserID = 0; + } + + if (device_type) { + XFree((void *)device_type); + } + } + + /* Restore handler */ + (void) XSetErrorHandler(old_handler); + (void) XSetIOErrorHandler(old_handler_io); + + XFreeDeviceList(device_info); + } + XFree(version); + } +} + +#endif /* WITH_X11_XINPUT */ diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index 02c0109085a..a5d5d9b7a99 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -39,11 +39,19 @@ #include "GHOST_System.h" #include "../GHOST_Types.h" +// For tablets +#ifdef WITH_X11_XINPUT +# include +#endif + #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING) # define GHOST_X11_RES_NAME "Blender" /* res_name */ # define GHOST_X11_RES_CLASS "Blender" /* res_class */ #endif +/* generic error handlers */ +int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent); +int GHOST_X11_ApplicationIOErrorHandler(Display *display); class GHOST_WindowX11; @@ -284,6 +292,27 @@ public: Atom m_incr; Atom m_utf8_string; +#ifdef WITH_X11_XINPUT + typedef struct GHOST_TabletX11 { + XDevice *StylusDevice; + XDevice *EraserDevice; + + XID StylusID, EraserID; + + int MotionEvent; + int ProxInEvent; + int ProxOutEvent; + + int PressureLevels; + int XtiltLevels, YtiltLevels; + } GHOST_TabletX11; + + GHOST_TabletX11 &GetXTablet() + { + return m_xtablet; + } +#endif // WITH_X11_XINPUT + private: Display *m_display; @@ -291,6 +320,11 @@ private: XIM m_xim; #endif +#ifdef WITH_X11_XINPUT + /* Tablet devices */ + GHOST_TabletX11 m_xtablet; +#endif + /// The vector of windows that need to be updated. std::vector m_dirty_windows; @@ -313,6 +347,10 @@ private: bool openX11_IM(); #endif +#ifdef WITH_X11_XINPUT + void initXInputDevices(); +#endif + GHOST_WindowX11 * findGhostWindow( Window xwind diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp index fd3ff4f85f0..ca12abe7324 100644 --- a/intern/ghost/intern/GHOST_Window.cpp +++ b/intern/ghost/intern/GHOST_Window.cpp @@ -61,6 +61,8 @@ GHOST_Window::GHOST_Window( m_cursorGrabAccumPos[0] = 0; m_cursorGrabAccumPos[1] = 0; + + m_nativePixelSize = 1.0f; m_fullScreen = state == GHOST_kWindowStateFullScreen; if (m_fullScreen) { @@ -194,3 +196,4 @@ bool GHOST_Window::getModifiedState() { return m_isUnsavedChanges; } + diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index fd870327fd4..f7c67bf7be6 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -257,6 +257,13 @@ public: { m_userData = userData; } + + virtual float getNativePixelSize(void) + { + if (m_nativePixelSize > 0.0f) + return m_nativePixelSize; + return 1.0f; + } protected: /** @@ -351,6 +358,9 @@ protected: GHOST_TUns32 m_fullScreenWidth; /** Full-screen height */ GHOST_TUns32 m_fullScreenHeight; + + /* OSX only, retina screens */ + float m_nativePixelSize; }; diff --git a/intern/ghost/intern/GHOST_WindowCarbon.cpp b/intern/ghost/intern/GHOST_WindowCarbon.cpp index 99d8854667e..36d45b4790c 100644 --- a/intern/ghost/intern/GHOST_WindowCarbon.cpp +++ b/intern/ghost/intern/GHOST_WindowCarbon.cpp @@ -182,7 +182,8 @@ GHOST_WindowCarbon::GHOST_WindowCarbon( (SInt32) this); // Store a pointer to the class in the refCon #endif //GHOST_PRINT("GHOST_WindowCarbon::GHOST_WindowCarbon(): creating full-screen OpenGL context\n"); - setDrawingContextType(GHOST_kDrawingContextTypeOpenGL);; installDrawingContext(GHOST_kDrawingContextTypeOpenGL); + setDrawingContextType(GHOST_kDrawingContextTypeOpenGL); + installDrawingContext(GHOST_kDrawingContextTypeOpenGL); updateDrawingContext(); activateDrawingContext(); diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h index 3e5c675d4a7..f1388c0b466 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.h +++ b/intern/ghost/intern/GHOST_WindowCocoa.h @@ -262,6 +262,11 @@ public: * Hides the progress bar icon */ virtual GHOST_TSuccess endProgressBar(); + + + virtual void setNativePixelSize(void); + + protected: /** * Tries to install a rendering context in this window. diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index e89dd1b41dc..ccd6cd93d4c 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -74,8 +74,10 @@ extern "C" { - (void)windowDidMove:(NSNotification *)notification; - (void)windowWillMove:(NSNotification *)notification; - (BOOL)windowShouldClose:(id)sender; +- (void)windowDidChangeBackingProperties:(NSNotification *)notification; @end + @implementation CocoaWindowDelegate : NSObject - (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa { @@ -128,6 +130,11 @@ extern "C" { }*/ } +- (void)windowDidChangeBackingProperties:(NSNotification *)notification +{ + systemCocoa->handleWindowEvent(GHOST_kEventNativeResolutionChange, associatedWindow); +} + - (BOOL)windowShouldClose:(id)sender; { //Let Blender close the window rather than closing immediately @@ -481,8 +488,8 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( [m_window setSystemAndWindowCocoa:systemCocoa windowCocoa:this]; //Forbid to resize the window below the blender defined minimum one - minSize.width = 640; - minSize.height = 480; + minSize.width = 320; + minSize.height = 240; [m_window setContentMinSize:minSize]; setTitle(title); @@ -593,7 +600,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( [m_openGLView setWantsBestResolutionOpenGLSurface:YES]; NSRect backingBounds = [m_openGLView convertRectToBacking:[m_openGLView bounds]]; - m_systemCocoa->m_nativePixelSize = (float)backingBounds.size.width / (float)rect.size.width; + m_nativePixelSize = (float)backingBounds.size.width / (float)rect.size.width; } } @@ -911,6 +918,19 @@ NSScreen* GHOST_WindowCocoa::getScreen() return [m_window screen]; } +/* called for event, when window leaves monitor to another */ +void GHOST_WindowCocoa::setNativePixelSize(void) +{ + /* make sure 10.6 keeps running */ + if ([m_openGLView respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) { + NSRect backingBounds = [m_openGLView convertRectToBacking:[m_openGLView bounds]]; + + GHOST_Rect rect; + getClientBounds(rect); + + m_nativePixelSize = (float)backingBounds.size.width / (float)rect.getWidth(); + } +} /** * \note Fullscreen switch is not actual fullscreen with display capture. @@ -1029,7 +1049,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) [tmpWindow registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSStringPboardType, NSTIFFPboardType, nil]]; //Forbid to resize the window below the blender defined minimum one - [tmpWindow setContentMinSize:NSMakeSize(640, 480)]; + [tmpWindow setContentMinSize:NSMakeSize(320, 240)]; //Assign the openGL view to the new window [tmpWindow setContentView:m_openGLView]; diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 3440e3ce15a..2e9ac94b9c7 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -186,11 +186,6 @@ GHOST_WindowX11( int natom; int glxVersionMajor, glxVersionMinor; /* As in GLX major.minor */ -#ifdef WITH_X11_XINPUT - /* initialize incase X11 fails to load */ - memset(&m_xtablet, 0, sizeof(m_xtablet)); -#endif - m_visual = NULL; if (!glXQueryVersion(m_display, &glxVersionMajor, &glxVersionMinor)) { @@ -363,8 +358,8 @@ GHOST_WindowX11( xsizehints->y = top; xsizehints->width = width; xsizehints->height = height; - xsizehints->min_width = 640; /* size hints, could be made apart of the ghost api */ - xsizehints->min_height = 480; /* limits are also arbitrary, but should not allow 1x1 window */ + xsizehints->min_width = 320; /* size hints, could be made apart of the ghost api */ + xsizehints->min_height = 240; /* limits are also arbitrary, but should not allow 1x1 window */ xsizehints->max_width = 65535; xsizehints->max_height = 65535; XSetWMNormalHints(m_display, m_window, xsizehints); @@ -461,6 +456,8 @@ GHOST_WindowX11( #ifdef WITH_X11_XINPUT initXInputDevices(); + + m_tabletData.Active = GHOST_kTabletModeNone; #endif /* now set up the rendering context. */ @@ -517,200 +514,30 @@ bool GHOST_WindowX11::createX11_XIC() #endif #ifdef WITH_X11_XINPUT -/* - * Dummy function to get around IO Handler exiting if device invalid - * Basically it will not crash blender now if you have a X device that - * is configured but not plugged in. - */ -static int ApplicationErrorHandler(Display *display, XErrorEvent *theEvent) -{ - fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n", - theEvent->error_code, theEvent->request_code); - - /* No exit! - but keep lint happy */ - return 0; -} - -/* These C functions are copied from Wine 1.1.13's wintab.c */ -#define BOOL int -#define TRUE 1 -#define FALSE 0 - -static bool match_token(const char *haystack, const char *needle) -{ - const char *p, *q; - for (p = haystack; *p; ) - { - while (*p && isspace(*p)) - p++; - if (!*p) - break; - - for (q = needle; *q && *p && tolower(*p) == tolower(*q); q++) - p++; - if (!*q && (isspace(*p) || !*p)) - return TRUE; - - while (*p && !isspace(*p)) - p++; - } - return FALSE; -} - - -/* Determining if an X device is a Tablet style device is an imperfect science. - * We rely on common conventions around device names as well as the type reported - * by Wacom tablets. This code will likely need to be expanded for alternate tablet types - * - * Wintab refers to any device that interacts with the tablet as a cursor, - * (stylus, eraser, tablet mouse, airbrush, etc) - * this is not to be confused with wacom x11 configuration "cursor" device. - * Wacoms x11 config "cursor" refers to its device slot (which we mirror with - * our gSysCursors) for puck like devices (tablet mice essentially). - */ -#if 0 // unused -static BOOL is_tablet_cursor(const char *name, const char *type) -{ - int i; - static const char *tablet_cursor_whitelist[] = { - "wacom", - "wizardpen", - "acecad", - "tablet", - "cursor", - "stylus", - "eraser", - "pad", - NULL - }; - - for (i = 0; tablet_cursor_whitelist[i] != NULL; i++) { - if (name && match_token(name, tablet_cursor_whitelist[i])) - return TRUE; - if (type && match_token(type, tablet_cursor_whitelist[i])) - return TRUE; - } - return FALSE; -} -#endif -static BOOL is_stylus(const char *name, const char *type) -{ - int i; - static const char *tablet_stylus_whitelist[] = { - "stylus", - "wizardpen", - "acecad", - NULL - }; - - for (i = 0; tablet_stylus_whitelist[i] != NULL; i++) { - if (name && match_token(name, tablet_stylus_whitelist[i])) - return TRUE; - if (type && match_token(type, tablet_stylus_whitelist[i])) - return TRUE; - } - - return FALSE; -} - -static BOOL is_eraser(const char *name, const char *type) -{ - if (name && match_token(name, "eraser")) - return TRUE; - if (type && match_token(type, "eraser")) - return TRUE; - return FALSE; -} -#undef BOOL -#undef TRUE -#undef FALSE -/* end code copied from wine */ - void GHOST_WindowX11::initXInputDevices() { - static XErrorHandler old_handler = (XErrorHandler) 0; XExtensionVersion *version = XGetExtensionVersion(m_display, INAME); if (version && (version != (XExtensionVersion *)NoSuchExtension)) { if (version->present) { - int device_count; - XDeviceInfo *device_info = XListInputDevices(m_display, &device_count); - m_xtablet.StylusDevice = NULL; - m_xtablet.EraserDevice = NULL; - m_xtablet.CommonData.Active = GHOST_kTabletModeNone; - - /* Install our error handler to override Xlib's termination behavior */ - old_handler = XSetErrorHandler(ApplicationErrorHandler); - - for (int i = 0; i < device_count; ++i) { - char *device_type = device_info[i].type ? XGetAtomName(m_display, device_info[i].type) : NULL; - -// printf("Tablet type:'%s', name:'%s', index:%d\n", device_type, device_info[i].name, i); - - - if (m_xtablet.StylusDevice == NULL && is_stylus(device_info[i].name, device_type)) { -// printf("\tfound stylus\n"); - m_xtablet.StylusID = device_info[i].id; - m_xtablet.StylusDevice = XOpenDevice(m_display, m_xtablet.StylusID); - - if (m_xtablet.StylusDevice != NULL) { - /* Find how many pressure levels tablet has */ - XAnyClassPtr ici = device_info[i].inputclassinfo; - for (int j = 0; j < m_xtablet.StylusDevice->num_classes; ++j) { - if (ici->c_class == ValuatorClass) { -// printf("\t\tfound ValuatorClass\n"); - XValuatorInfo *xvi = (XValuatorInfo *)ici; - m_xtablet.PressureLevels = xvi->axes[2].max_value; - - /* this is assuming that the tablet has the same tilt resolution in both - * positive and negative directions. It would be rather weird if it didn't.. */ - m_xtablet.XtiltLevels = xvi->axes[3].max_value; - m_xtablet.YtiltLevels = xvi->axes[4].max_value; - break; - } - - ici = (XAnyClassPtr)(((char *)ici) + ici->length); - } - } - else { - m_xtablet.StylusID = 0; - } - } - else if (m_xtablet.EraserDevice == NULL && is_eraser(device_info[i].name, device_type)) { -// printf("\tfound eraser\n"); - m_xtablet.EraserID = device_info[i].id; - m_xtablet.EraserDevice = XOpenDevice(m_display, m_xtablet.EraserID); - if (m_xtablet.EraserDevice == NULL) m_xtablet.EraserID = 0; - } - - if (device_type) { - XFree((void *)device_type); - } - } - - /* Restore handler */ - (void) XSetErrorHandler(old_handler); - - XFreeDeviceList(device_info); - - + GHOST_SystemX11::GHOST_TabletX11 &xtablet = m_system->GetXTablet(); XEventClass xevents[10], ev; int dcount = 0; - if (m_xtablet.StylusDevice) { - DeviceMotionNotify(m_xtablet.StylusDevice, m_xtablet.MotionEvent, ev); + if (xtablet.StylusDevice) { + DeviceMotionNotify(xtablet.StylusDevice, xtablet.MotionEvent, ev); if (ev) xevents[dcount++] = ev; - ProximityIn(m_xtablet.StylusDevice, m_xtablet.ProxInEvent, ev); + ProximityIn(xtablet.StylusDevice, xtablet.ProxInEvent, ev); if (ev) xevents[dcount++] = ev; - ProximityOut(m_xtablet.StylusDevice, m_xtablet.ProxOutEvent, ev); + ProximityOut(xtablet.StylusDevice, xtablet.ProxOutEvent, ev); if (ev) xevents[dcount++] = ev; } - if (m_xtablet.EraserDevice) { - DeviceMotionNotify(m_xtablet.EraserDevice, m_xtablet.MotionEvent, ev); + if (xtablet.EraserDevice) { + DeviceMotionNotify(xtablet.EraserDevice, xtablet.MotionEvent, ev); if (ev) xevents[dcount++] = ev; - ProximityIn(m_xtablet.EraserDevice, m_xtablet.ProxInEvent, ev); + ProximityIn(xtablet.EraserDevice, xtablet.ProxInEvent, ev); if (ev) xevents[dcount++] = ev; - ProximityOut(m_xtablet.EraserDevice, m_xtablet.ProxOutEvent, ev); + ProximityOut(xtablet.EraserDevice, xtablet.ProxOutEvent, ev); if (ev) xevents[dcount++] = ev; } @@ -1341,15 +1168,6 @@ GHOST_WindowX11:: XFreeCursor(m_display, m_custom_cursor); } -#ifdef WITH_X11_XINPUT - /* close tablet devices */ - if (m_xtablet.StylusDevice) - XCloseDevice(m_display, m_xtablet.StylusDevice); - - if (m_xtablet.EraserDevice) - XCloseDevice(m_display, m_xtablet.EraserDevice); -#endif /* WITH_X11_XINPUT */ - if (m_context != s_firstContext) { glXDestroyContext(m_display, m_context); } @@ -1392,6 +1210,15 @@ installDrawingContext( GHOST_TSuccess success; switch (type) { case GHOST_kDrawingContextTypeOpenGL: + { +#ifdef WITH_X11_XINPUT + /* use our own event handlers to avoid exiting blender, + * this would happen for eg: + * if you open blender, unplug a tablet, then open a new window. */ + XErrorHandler old_handler = XSetErrorHandler(GHOST_X11_ApplicationErrorHandler); + XIOErrorHandler old_handler_io = XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler); +#endif + m_context = glXCreateContext(m_display, m_visual, s_firstContext, True); if (m_context != NULL) { if (!s_firstContext) { @@ -1406,12 +1233,18 @@ installDrawingContext( success = GHOST_kFailure; } +#ifdef WITH_X11_XINPUT + /* Restore handler */ + (void) XSetErrorHandler(old_handler); + (void) XSetIOErrorHandler(old_handler_io); +#endif break; - + } case GHOST_kDrawingContextTypeNone: + { success = GHOST_kSuccess; break; - + } default: success = GHOST_kFailure; } diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index 5b2ffced29c..10d44987647 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -196,32 +196,9 @@ public: getXWindow( ); #ifdef WITH_X11_XINPUT - class XTablet + GHOST_TabletData *GetTabletData() { -public: - GHOST_TabletData CommonData; - - XDevice *StylusDevice; - XDevice *EraserDevice; - - XID StylusID, EraserID; - - int MotionEvent; - int ProxInEvent; - int ProxOutEvent; - - int PressureLevels; - int XtiltLevels, YtiltLevels; - }; - - XTablet& GetXTablet() - { - return m_xtablet; - } - - const GHOST_TabletData *GetTabletData() - { - return &m_xtablet.CommonData; + return &m_tabletData; } #else // WITH_X11_XINPUT const GHOST_TabletData *GetTabletData() @@ -387,8 +364,7 @@ private: #endif #ifdef WITH_X11_XINPUT - /* Tablet devices */ - XTablet m_xtablet; + GHOST_TabletData m_tabletData; #endif #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING) diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c index 11fa477c2a4..559d1138ffb 100644 --- a/intern/guardedalloc/intern/mallocn.c +++ b/intern/guardedalloc/intern/mallocn.c @@ -68,6 +68,17 @@ //#define DEBUG_MEMCOUNTER +/* Only for debugging: + * defining DEBUG_THREADS will enable check whether memory manager + * is locked with a mutex when allocation is called from non-main + * thread. + * + * This helps troubleshooting memory issues caused by the fact + * guarded allocator is not thread-safe, however this check will + * fail to check allocations from openmp threads. + */ +//#define DEBUG_THREADS + #ifdef DEBUG_MEMCOUNTER /* set this to the value that isn't being freed */ # define DEBUG_MEMCOUNTER_ERROR_VAL 0 @@ -122,6 +133,12 @@ typedef struct MemHead { #endif #endif +#ifdef DEBUG_THREADS +# include +# include +static pthread_t mainid; +#endif + typedef struct MemTail { int tag3, pad; } MemTail; @@ -206,6 +223,20 @@ static void print_error(const char *str, ...) static void mem_lock_thread(void) { +#ifdef DEBUG_THREADS + static int initialized = 0; + + if (initialized == 0) { + /* assume first allocation happens from main thread */ + mainid = pthread_self(); + initialized = 1; + } + + if (!pthread_equal(pthread_self(), mainid) && thread_lock_callback == NULL) { + assert(!"Memory function is called from non-main thread without lock"); + } +#endif + #ifdef DEBUG_OMP_MALLOC assert(omp_in_parallel() == 0); #endif diff --git a/intern/locale/boost_locale_wrapper.cpp b/intern/locale/boost_locale_wrapper.cpp index 80e75298d70..ebd2dd652c7 100644 --- a/intern/locale/boost_locale_wrapper.cpp +++ b/intern/locale/boost_locale_wrapper.cpp @@ -33,6 +33,7 @@ static std::string messages_path; static std::string default_domain; +static std::string locale_str; void bl_locale_init(const char *_messages_path, const char *_default_domain) { @@ -52,6 +53,7 @@ void bl_locale_init(const char *_messages_path, const char *_default_domain) void bl_locale_set(const char *locale) { boost::locale::generator gen; + std::locale _locale; // Specify location of dictionaries. gen.add_messages_path(messages_path); gen.add_messages_domain(default_domain); @@ -59,7 +61,8 @@ void bl_locale_set(const char *locale) try { if (locale && locale[0]) { - std::locale::global(gen(locale)); + _locale = gen(locale); + std::locale::global(_locale); } else { #ifdef __APPLE__ @@ -85,9 +88,11 @@ void bl_locale_set(const char *locale) if (locale_osx == "") fprintf(stderr, "Locale set: failed to read AppleLocale read from defaults\n"); - std::locale::global(gen(locale_osx.c_str())); + _locale = gen(locale_osx.c_str()); + std::locale::global(_locale); #else - std::locale::global(gen("")); + _locale = gen(""); + std::locale::global(_locale); #endif } // Note: boost always uses "C" LC_NUMERIC by default! @@ -95,6 +100,22 @@ void bl_locale_set(const char *locale) catch(std::exception const &e) { std::cout << "bl_locale_set(" << locale << "): " << e.what() << " \n"; } + + /* Generate the locale string (useful to know which locale we are actually using in case of "default" one). */ +#define LOCALE_INFO std::use_facet(_locale) + + locale_str = LOCALE_INFO.language(); + if (LOCALE_INFO.country() != "") { + locale_str += "_" + LOCALE_INFO.country(); + } + if (LOCALE_INFO.variant() != "") { + locale_str += "@" + LOCALE_INFO.variant(); + } +} + +const char *bl_locale_get(void) +{ + return locale_str.c_str(); } const char *bl_locale_pgettext(const char *msgctxt, const char *msgid) @@ -115,5 +136,4 @@ const char *bl_locale_pgettext(const char *msgctxt, const char *msgid) // std::cout << "bl_locale_pgettext(" << msgctxt << ", " << msgid << "): " << e.what() << " \n"; return msgid; } -} - +} \ No newline at end of file diff --git a/intern/locale/boost_locale_wrapper.h b/intern/locale/boost_locale_wrapper.h index e7956d216f1..4e3a1f848d2 100644 --- a/intern/locale/boost_locale_wrapper.h +++ b/intern/locale/boost_locale_wrapper.h @@ -40,7 +40,8 @@ extern "C" { void bl_locale_init(const char *messages_path, const char *default_domain); void bl_locale_set(const char *locale); -const char* bl_locale_pgettext(const char *msgctxt, const char *msgid); +const char *bl_locale_get(void); +const char *bl_locale_pgettext(const char *msgctxt, const char *msgid); #ifdef __cplusplus } diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg index fcade5b38c5..60c5ff92c55 100644 --- a/release/datafiles/blender_icons.svg +++ b/release/datafiles/blender_icons.svg @@ -14,18 +14,108 @@ height="640" id="svg2" sodipodi:version="0.32" - inkscape:version="0.48.3.1 r9886" + inkscape:version="0.48.2 r9819" version="1.0" sodipodi:docname="blender_icons.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape" style="display:inline;enable-background:new" - inkscape:export-filename="/home/wolter/Documenten/Blender/icons/D:\Documents\Blender\icons\BF icons v.2.5.08a.png" + inkscape:export-filename="blender_icons16.png" inkscape:export-xdpi="90" inkscape:export-ydpi="90"> Blender icons v. 2.5.08 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -65,11 +155,11 @@ @@ -14188,26 +14278,6 @@ offset="1" id="stop10073-42" /> - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +