Merged changes in the trunk up to revision 42021.

Conflicts resolved:
source/blender/blenkernel/intern/scene.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/interface/resources.c
source/blender/render/intern/source/pipeline.c
This commit is contained in:
Tamito Kajiyama 2011-11-20 21:02:12 +00:00
commit 2676f2d58f
497 changed files with 12939 additions and 5809 deletions

@ -171,6 +171,7 @@ option(WITH_MOD_DECIMATE "Enable Decimate Modifier" ON)
option(WITH_MOD_BOOLEAN "Enable Boolean Modifier" ON)
option(WITH_MOD_CLOTH_ELTOPO "Enable Experemental cloth solver" OFF)
mark_as_advanced(WITH_MOD_CLOTH_ELTOPO)
option(WITH_MOD_OCEANSIM "Enable Ocean Modifier" OFF)
# Image format support
option(WITH_IMAGE_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" ON)
@ -218,6 +219,7 @@ option(WITH_CYCLES "Enable cycles Render Engine" ON)
option(WITH_CYCLES_TEST "Build cycles test application" OFF)
option(WITH_CYCLES_CUDA_BINARIES "Build cycles CUDA binaries" OFF)
set(CYCLES_CUDA_BINARIES_ARCH sm_13 sm_20 sm_21 CACHE STRING "CUDA architectures to build binaries for")
mark_as_advanced(CYCLES_CUDA_BINARIES_ARCH)
# disable for now, but plan to support on all platforms eventually
option(WITH_MEM_JEMALLOC "Enable malloc replacement (http://www.canonware.com/jemalloc)" OFF)
@ -285,6 +287,10 @@ if(WITH_CODEC_QUICKTIME AND MINGW)
"line if youre a developer who wants to add support.")
endif()
if(NOT WITH_FFTW3 AND WITH_MOD_OCEANSIM)
message(FATAL_ERROR "WITH_MOD_OCEANSIM requires WITH_FFTW3 to be ON")
endif()
# may as well build python module without a UI
if(WITH_PYTHON_MODULE)
set(WITH_HEADLESS ON)
@ -1562,6 +1568,7 @@ if(FIRST_RUN)
info_cfg_option(WITH_MOD_BOOLEAN)
info_cfg_option(WITH_MOD_DECIMATE)
info_cfg_option(WITH_MOD_FLUID)
info_cfg_option(WITH_MOD_OCEANSIM)
info_cfg_text("")

@ -34,7 +34,10 @@ OS_NCASE:=$(shell uname -s | tr '[A-Z]' '[a-z]')
# Source and Build DIR's
BLENDER_DIR:=$(shell pwd -P)
BUILD_TYPE:=Release
BUILD_CMAKE_ARGS:=
ifndef BUILD_CMAKE_ARGS
BUILD_CMAKE_ARGS:=
endif
ifndef BUILD_DIR
BUILD_DIR:=$(shell dirname $(BLENDER_DIR))/build/$(OS_NCASE)
@ -123,6 +126,7 @@ help:
@echo " * bpy - build as a python module which can be loaded from python directly"
@echo ""
@echo " Note, passing the argument 'BUILD_DIR=path' when calling make will override the default build dir."
@echo " Note, passing the argument 'BUILD_CMAKE_ARGS=args' lets you add cmake arguments."
@echo ""
@echo ""
@echo "Project Files for IDE's"

@ -70,6 +70,7 @@ BlenderEnvironment = Blender.BlenderEnvironment
B = Blender
VERSION = btools.VERSION # This is used in creating the local config directories
VERSION_RELEASE_CYCLE = btools.VERSION_RELEASE_CYCLE
### globals ###
platform = sys.platform
@ -254,6 +255,7 @@ if 'blenderlite' in B.targets:
target_env_defs['WITH_BF_BINRELOC'] = False
target_env_defs['BF_BUILDINFO'] = False
target_env_defs['WITH_BF_FLUID'] = False
target_env_defs['WITH_BF_OCEANSIM'] = False
target_env_defs['WITH_BF_DECIMATE'] = False
target_env_defs['WITH_BF_BOOLEAN'] = False
target_env_defs['WITH_BF_PYTHON'] = False
@ -329,6 +331,11 @@ if 'blendernogame' in B.targets:
if env['WITH_BF_FLUID'] == 1:
env['CPPFLAGS'].append('-DWITH_MOD_FLUID')
# build with ocean sim?
if env['WITH_BF_OCEANSIM'] == 1:
env['WITH_BF_FFTW3'] = 1 # ocean needs fftw3 so enable it
env['CPPFLAGS'].append('-DWITH_MOD_OCEANSIM')
if btools.ENDIAN == "big":
env['CPPFLAGS'].append('-D__BIG_ENDIAN__')
@ -518,6 +525,10 @@ if env['OURPLATFORM']!='darwin':
if '__pycache__' in dn: # py3.2 cache dir
dn.remove('__pycache__')
# only for testing builds
if VERSION_RELEASE_CYCLE == "release" and "addons_contrib" in dn:
dn.remove('addons_contrib')
dir = os.path.join(env['BF_INSTALLDIR'], VERSION)
dir += os.sep + os.path.basename(scriptpath) + dp[len(scriptpath):]

@ -109,6 +109,9 @@ BF_BOOST_INC = '${BF_BOOST}/include'
BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a'
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
# Ocean Simulation
WITH_BF_OCEANSIM = True
# Compilation and optimization
BF_DEBUG = False
REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++

@ -86,6 +86,11 @@ WITH_BF_JACK = True
# Motion Tracking
WITH_BF_LIBMV = False
# Ocean Simulation
WITH_BF_FFTW3 = True
WITH_BF_STATICFFTW3 = True
WITH_BF_OCEANSIM = True
# Compilation and optimization
BF_DEBUG = False
REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++

@ -86,6 +86,11 @@ WITH_BF_JACK = True
# Motion Tracking
WITH_BF_LIBMV = False
# Ocean Simulation
WITH_BF_FFTW3 = True
WITH_BF_STATICFFTW3 = True
WITH_BF_OCEANSIM = True
# Compilation and optimization
BF_DEBUG = False
REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++

@ -109,6 +109,9 @@ BF_BOOST_INC = '${BF_BOOST}/include'
BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a'
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
# Ocean Simulation
WITH_BF_OCEANSIM = True
# Compilation and optimization
BF_DEBUG = False
REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++

@ -139,9 +139,9 @@ IF(PYTHONLIBSUNIX_FOUND)
# not used
# SET(PYTHON_BINARY ${PYTHON_EXECUTABLE} CACHE STRING "")
MARK_AS_ADVANCED(
PYTHON_INCLUDE_DIR
PYTHON_LIBRARY
)
ENDIF()
MARK_AS_ADVANCED(
PYTHON_INCLUDE_DIR
PYTHON_LIBRARY
)

@ -22,6 +22,12 @@
# <pep8 compliant>
import sys
if not sys.version.startswith("3"):
print("\nPython3.x needed, found %s.\nAborting!\n" %
sys.version.partition(" ")[0])
sys.exit(1)
from cmake_consistency_check_config import IGNORE, UTF8_CHECK, SOURCE_DIR
import os

@ -89,7 +89,7 @@ def create_qtc_project_main():
f = open(os.path.join(PROJECT_DIR, "%s.files" % FILE_NAME), 'w')
f.write("\n".join(files_rel))
f = open(os.path.join(PROJECT_DIR, "%s.includes" % FILE_NAME), 'w')
f = open(os.path.join(PROJECT_DIR, "%s.includes" % FILE_NAME), 'w', encoding='utf-8')
f.write("\n".join(sorted(includes)))
qtc_prj = os.path.join(PROJECT_DIR, "%s.creator" % FILE_NAME)
@ -104,7 +104,7 @@ def create_qtc_project_main():
defines_final += cmake_compiler_defines()
f.write("\n".join(defines_final))
print("Blender project file written to: %s" % qtc_prj)
print("Blender project file written to: %r" % qtc_prj)
# --- end
@ -133,7 +133,7 @@ def create_qtc_project_python():
f = open(qtc_cfg, 'w')
f.write("// ADD PREDEFINED MACROS HERE!\n")
print("Python project file written to: %s" % qtc_prj)
print("Python project file written to: %r" % qtc_prj)
def main():

@ -34,6 +34,7 @@ set(WITH_MOD_BOOLEAN OFF CACHE FORCE BOOL)
set(WITH_MOD_DECIMATE OFF CACHE FORCE BOOL)
set(WITH_MOD_FLUID OFF CACHE FORCE BOOL)
set(WITH_MOD_SMOKE OFF CACHE FORCE BOOL)
set(WITH_MOD_OCEANSIM OFF CACHE FORCE BOOL)
set(WITH_AUDASPACE OFF CACHE FORCE BOOL)
set(WITH_OPENAL OFF CACHE FORCE BOOL)
set(WITH_OPENCOLLADA OFF CACHE FORCE BOOL)

@ -44,7 +44,14 @@ __all__ = (
"project_name_get"
)
import sys
if not sys.version.startswith("3"):
print("\nPython3.x needed, found %s.\nAborting!\n" %
sys.version.partition(" ")[0])
sys.exit(1)
import os
from os.path import join, dirname, normpath, abspath, splitext, exists
@ -142,10 +149,11 @@ def cmake_advanced_info():
from xml.dom.minidom import parse
tree = parse(join(CMAKE_DIR, ".cproject"))
'''
f = open(".cproject_pretty", 'w')
f.write(tree.toprettyxml(indent=" ", newl=""))
'''
# to check on nicer xml
# f = open(".cproject_pretty", 'w')
# f.write(tree.toprettyxml(indent=" ", newl=""))
ELEMENT_NODE = tree.ELEMENT_NODE
cproject, = tree.getElementsByTagName("cproject")
@ -186,7 +194,7 @@ def cmake_advanced_info():
def cmake_cache_var(var):
cache_file = open(join(CMAKE_DIR, "CMakeCache.txt"))
cache_file = open(join(CMAKE_DIR, "CMakeCache.txt"), encoding='utf-8')
lines = [l_strip for l in cache_file for l_strip in (l.strip(),) if l_strip if not l_strip.startswith("//") if not l_strip.startswith("#")]
cache_file.close()
@ -224,7 +232,9 @@ def project_name_get(path, fallback="Blender", prefix="Blender_"):
import subprocess
info = subprocess.Popen(["svn", "info", path],
stdout=subprocess.PIPE).communicate()[0].decode()
stdout=subprocess.PIPE).communicate()[0]
# string version, we only want the URL
info = info.decode(encoding="utf-8", errors="ignore")
for l in info.split("\n"):
l = l.strip()

@ -25,6 +25,14 @@ __all__ = (
"SOURCE_DIR",
)
import sys
if not sys.version.startswith("3"):
print("\nPython3.x needed, found %s.\nAborting!\n" %
sys.version.partition(" ")[0])
sys.exit(1)
import os
from os.path import join, dirname, normpath, abspath
@ -73,7 +81,7 @@ def do_ignore(filepath, ignore_prefix_list):
def makefile_log():
import subprocess
import time
# Check blender is not 2.5x until it supports playback again
print("running make with --dry-run ...")
process = subprocess.Popen(["make", "--always-make", "--dry-run", "--keep-going", "VERBOSE=1"],
stdout=subprocess.PIPE,
@ -85,7 +93,7 @@ def makefile_log():
out = process.stdout.read()
process.stdout.close()
print("done!", len(out), "bytes")
return out.decode("ascii").split("\n")
return out.decode("utf-8", errors="ignore").split("\n")
def build_info(use_c=True, use_cxx=True, ignore_prefix_list=None):

@ -18,20 +18,20 @@ MACOSX_ARCHITECTURE = 'i386' # valid archs: ppc, i386, ppc64, x86_64
cmd = 'uname -p'
MAC_PROC=commands.getoutput(cmd)
MAC_PROC=commands.getoutput(cmd)
cmd = 'uname -r'
cmd_res=commands.getoutput(cmd)
cmd_res=commands.getoutput(cmd)
if cmd_res[:1]=='7':
MAC_CUR_VER='10.3'
MAC_CUR_VER='10.3'
elif cmd_res[:1]=='8':
MAC_CUR_VER='10.4'
MAC_CUR_VER='10.4'
elif cmd_res[:1]=='9':
MAC_CUR_VER='10.5'
MAC_CUR_VER='10.5'
elif cmd_res[:2]=='10':
MAC_CUR_VER='10.6'
MAC_CUR_VER='10.6'
elif cmd_res[:2]=='11':
MAC_CUR_VER='10.7'
MAC_CUR_VER='10.7'
cmd = 'xcodebuild -version'
cmd_xcode=commands.getoutput(cmd)
XCODE_CUR_VER=cmd_xcode
@ -40,7 +40,7 @@ cmd_sdk=commands.getoutput(cmd)
MACOSX_SDK_CHECK=cmd_sdk
if MACOSX_ARCHITECTURE == 'x86_64' or MACOSX_ARCHITECTURE == 'ppc64':
USE_QTKIT=True # Carbon quicktime is not available for 64bit
USE_QTKIT=True # Carbon quicktime is not available for 64bit
# Default target OSX settings per architecture
@ -48,41 +48,41 @@ if MACOSX_ARCHITECTURE == 'x86_64' or MACOSX_ARCHITECTURE == 'ppc64':
if MACOSX_ARCHITECTURE == 'ppc' and MAC_CUR_VER == '10.4':
# all releases are now made for 10.5 !
# MAC_MIN_VERS = '10.3'
# MACOSX_SDK='/Developer/SDKs/MacOSX10.3.9.sdk'
# LCGDIR = '#../lib/darwin-6.1-powerpc'
# CC = 'gcc-3.3'
# CXX = 'g++-3.3'
MAC_MIN_VERS = '10.4'
MACOSX_DEPLOYMENT_TARGET = '10.4'
MACOSX_SDK='/Developer/SDKs/MacOSX10.4u.sdk'
LCGDIR = '#../lib/darwin-8.0.0-powerpc'
CC = 'gcc-4.0'
CXX = 'g++-4.0'
# MAC_MIN_VERS = '10.3'
# MACOSX_SDK='/Developer/SDKs/MacOSX10.3.9.sdk'
# LCGDIR = '#../lib/darwin-6.1-powerpc'
# CC = 'gcc-3.3'
# CXX = 'g++-3.3'
MAC_MIN_VERS = '10.4'
MACOSX_DEPLOYMENT_TARGET = '10.4'
MACOSX_SDK='/Developer/SDKs/MacOSX10.4u.sdk'
LCGDIR = '#../lib/darwin-8.0.0-powerpc'
CC = 'gcc-4.0'
CXX = 'g++-4.0'
elif MACOSX_ARCHITECTURE == 'i386' and MAC_CUR_VER == '10.4':
MAC_MIN_VERS = '10.4'
MACOSX_DEPLOYMENT_TARGET = '10.4'
MACOSX_SDK='/Developer/SDKs/MacOSX10.4u.sdk'
LCGDIR = '#../lib/darwin-8.x.i386'
CC = 'gcc-4.0'
CXX = 'g++-4.0'
MAC_MIN_VERS = '10.4'
MACOSX_DEPLOYMENT_TARGET = '10.4'
MACOSX_SDK='/Developer/SDKs/MacOSX10.4u.sdk'
LCGDIR = '#../lib/darwin-8.x.i386'
CC = 'gcc-4.0'
CXX = 'g++-4.0'
else :
if 'Mac OS X 10.5' in MACOSX_SDK_CHECK:
# OSX 10.5/6 with Xcode 3.x
MAC_MIN_VERS = '10.5'
MACOSX_DEPLOYMENT_TARGET = '10.5'
MACOSX_SDK='/Developer/SDKs/MacOSX10.5.sdk'
LCGDIR = '#../lib/darwin-9.x.universal'
CC = 'gcc-4.2'
CXX = 'g++-4.2'
else:
# OSX 10.6/7 with Xcode 4.x
MAC_MIN_VERS = '10.6'
MACOSX_DEPLOYMENT_TARGET = '10.6'
MACOSX_SDK='/Developer/SDKs/MacOSX10.6.sdk'
LCGDIR = '#../lib/darwin-9.x.universal'
CC = 'gcc-4.2'
CXX = 'g++-4.2'
if 'Mac OS X 10.5' in MACOSX_SDK_CHECK:
# OSX 10.5/6 with Xcode 3.x
MAC_MIN_VERS = '10.5'
MACOSX_DEPLOYMENT_TARGET = '10.5'
MACOSX_SDK='/Developer/SDKs/MacOSX10.5.sdk'
LCGDIR = '#../lib/darwin-9.x.universal'
CC = 'gcc-4.2'
CXX = 'g++-4.2'
else:
# OSX 10.6/7 with Xcode 4.x
MAC_MIN_VERS = '10.6'
MACOSX_DEPLOYMENT_TARGET = '10.6'
MACOSX_SDK='/Developer/SDKs/MacOSX10.6.sdk'
LCGDIR = '#../lib/darwin-9.x.universal'
CC = 'gcc-4.2'
CXX = 'g++-4.2'
LIBDIR = '${LCGDIR}'
@ -109,32 +109,32 @@ BF_PYTHON_VERSION = '3.2'
WITH_OSX_STATICPYTHON = True
if WITH_OSX_STATICPYTHON:
# python 3.2 uses precompiled libraries in bf svn /lib by default
# python 3.2 uses precompiled libraries in bf svn /lib by default
BF_PYTHON = LIBDIR + '/python'
BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}'
# BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}'
BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}'
BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/python${BF_PYTHON_VERSION}'
# BF_PYTHON_LINKFLAGS = ['-u', '_PyMac_Error', '-framework', 'System']
BF_PYTHON = LIBDIR + '/python'
BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}'
# BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}'
BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}'
BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/python${BF_PYTHON_VERSION}'
# BF_PYTHON_LINKFLAGS = ['-u', '_PyMac_Error', '-framework', 'System']
else:
# python 3.2 uses Python-framework additionally installed in /Library/Frameworks
BF_PYTHON = '/Library/Frameworks/Python.framework/Versions/'
BF_PYTHON_INC = '${BF_PYTHON}${BF_PYTHON_VERSION}/include/python${BF_PYTHON_VERSION}m'
BF_PYTHON_BINARY = '${BF_PYTHON}${BF_PYTHON_VERSION}/bin/python${BF_PYTHON_VERSION}'
#BF_PYTHON_LIB = ''
BF_PYTHON_LIBPATH = '${BF_PYTHON}${BF_PYTHON_VERSION}/lib/python${BF_PYTHON_VERSION}/config-3.2m'
# python 3.2 uses Python-framework additionally installed in /Library/Frameworks
BF_PYTHON = '/Library/Frameworks/Python.framework/Versions/'
BF_PYTHON_INC = '${BF_PYTHON}${BF_PYTHON_VERSION}/include/python${BF_PYTHON_VERSION}m'
BF_PYTHON_BINARY = '${BF_PYTHON}${BF_PYTHON_VERSION}/bin/python${BF_PYTHON_VERSION}'
#BF_PYTHON_LIB = ''
BF_PYTHON_LIBPATH = '${BF_PYTHON}${BF_PYTHON_VERSION}/lib/python${BF_PYTHON_VERSION}/config-3.2m'
WITH_BF_OPENAL = True
#different lib must be used following version of gcc
# for gcc 3.3
#BF_OPENAL = LIBDIR + '/openal'
# for gcc 3.4 and ulterior
if MAC_PROC == 'powerpc':
BF_OPENAL = '#../lib/darwin-8.0.0-powerpc/openal'
BF_OPENAL = '#../lib/darwin-8.0.0-powerpc/openal'
else :
BF_OPENAL = LIBDIR + '/openal'
BF_OPENAL = LIBDIR + '/openal'
WITH_BF_STATICOPENAL = False
BF_OPENAL_INC = '${BF_OPENAL}/include' # only headers from libdir needed for proper use of framework !!!!
@ -217,6 +217,7 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE = True
WITH_BF_PLAYER = True
WITH_BF_OCEANSIM = True
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'
@ -232,7 +233,7 @@ BF_FFTW3_LIBPATH = '${BF_FFTW3}/lib'
#WITH_BF_NSPR = True
#BF_NSPR = $(LIBDIR)/nspr
#BF_NSPR_INC = -I$(BF_NSPR)/include -I$(BF_NSPR)/include/nspr
#BF_NSPR_LIB =
#BF_NSPR_LIB =
# Uncomment the following line to use Mozilla inplace of netscape
#CPPFLAGS += -DMOZ_NOT_NET
@ -283,7 +284,7 @@ BF_PCRE_LIBPATH = '${BF_PCRE}/lib'
#BF_EXPAT_LIBPATH = '/usr/lib'
#Cycles
WITH_BF_CYCLES = True
WITH_BF_CYCLES = True
WITH_BF_OIIO = True
BF_OIIO = LIBDIR + '/openimageio'
@ -317,9 +318,9 @@ WITH_BF_3DMOUSE = True
BF_QUIET = '1' # suppress verbose output
if MACOSX_ARCHITECTURE == 'x86_64' or MACOSX_ARCHITECTURE == 'ppc64':
ARCH_FLAGS = ['-m64']
ARCH_FLAGS = ['-m64']
else:
ARCH_FLAGS = ['-m32']
ARCH_FLAGS = ['-m32']
CFLAGS = []
CXXFLAGS = []
@ -328,53 +329,53 @@ CCFLAGS = ['-pipe','-funsigned-char']
CPPFLAGS = list(ARCH_FLAGS)
if WITH_GHOST_COCOA:
PLATFORM_LINKFLAGS = ['-fexceptions','-framework','CoreServices','-framework','Foundation','-framework','IOKit','-framework','AppKit','-framework','Cocoa','-framework','Carbon','-framework','AudioUnit','-framework','AudioToolbox','-framework','CoreAudio','-framework','OpenAL']+ARCH_FLAGS
PLATFORM_LINKFLAGS = ['-fexceptions','-framework','CoreServices','-framework','Foundation','-framework','IOKit','-framework','AppKit','-framework','Cocoa','-framework','Carbon','-framework','AudioUnit','-framework','AudioToolbox','-framework','CoreAudio','-framework','OpenAL']+ARCH_FLAGS
else:
PLATFORM_LINKFLAGS = ['-fexceptions','-framework','CoreServices','-framework','Foundation','-framework','IOKit','-framework','AppKit','-framework','Carbon','-framework','AGL','-framework','AudioUnit','-framework','AudioToolbox','-framework','CoreAudio','-framework','OpenAL']+ARCH_FLAGS
PLATFORM_LINKFLAGS = ['-fexceptions','-framework','CoreServices','-framework','Foundation','-framework','IOKit','-framework','AppKit','-framework','Carbon','-framework','AGL','-framework','AudioUnit','-framework','AudioToolbox','-framework','CoreAudio','-framework','OpenAL']+ARCH_FLAGS
if WITH_BF_QUICKTIME:
if USE_QTKIT:
PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','QTKit']
else:
PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','QuickTime']
if USE_QTKIT:
PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','QTKit']
else:
PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','QuickTime']
if not WITH_OSX_STATICPYTHON:
PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','Python']
PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','Python']
#note to build succesfully on 10.3.9 SDK you need to patch 10.3.9 by adding the SystemStubs.a lib from 10.4
#for 10.7.sdk, SystemStubs needs to be excluded (lib doesn't exist anymore)
if MACOSX_DEPLOYMENT_TARGET == '10.7':
LLIBS = ['stdc++']
LLIBS = ['stdc++']
else:
LLIBS = ['stdc++', 'SystemStubs']
LLIBS = ['stdc++', 'SystemStubs']
# some flags shuffling for different OS versions
if MAC_MIN_VERS == '10.3':
CCFLAGS = ['-fuse-cxa-atexit'] + CCFLAGS
PLATFORM_LINKFLAGS = ['-fuse-cxa-atexit'] + PLATFORM_LINKFLAGS
LLIBS.append('crt3.o')
if USE_SDK:
SDK_FLAGS=['-isysroot', MACOSX_SDK,'-mmacosx-version-min='+MAC_MIN_VERS,'-arch',MACOSX_ARCHITECTURE]
PLATFORM_LINKFLAGS = ['-mmacosx-version-min='+MAC_MIN_VERS,'-Wl','-isysroot',MACOSX_SDK,'-arch',MACOSX_ARCHITECTURE]+PLATFORM_LINKFLAGS
CCFLAGS=SDK_FLAGS+CCFLAGS
CXXFLAGS=SDK_FLAGS+CXXFLAGS
CCFLAGS = ['-fuse-cxa-atexit'] + CCFLAGS
PLATFORM_LINKFLAGS = ['-fuse-cxa-atexit'] + PLATFORM_LINKFLAGS
LLIBS.append('crt3.o')
#Intel Macs are CoreDuo and Up
if USE_SDK:
SDK_FLAGS=['-isysroot', MACOSX_SDK,'-mmacosx-version-min='+MAC_MIN_VERS,'-arch',MACOSX_ARCHITECTURE]
PLATFORM_LINKFLAGS = ['-mmacosx-version-min='+MAC_MIN_VERS,'-Wl','-isysroot',MACOSX_SDK,'-arch',MACOSX_ARCHITECTURE]+PLATFORM_LINKFLAGS
CCFLAGS=SDK_FLAGS+CCFLAGS
CXXFLAGS=SDK_FLAGS+CXXFLAGS
#Intel Macs are CoreDuo and Up
if MACOSX_ARCHITECTURE == 'i386' or MACOSX_ARCHITECTURE == 'x86_64':
REL_CFLAGS = []
REL_CXXFLAGS = []
REL_CCFLAGS = ['-DNDEBUG', '-O2','-ftree-vectorize','-msse','-msse2','-msse3','-mfpmath=sse']
REL_CFLAGS = []
REL_CXXFLAGS = []
REL_CCFLAGS = ['-DNDEBUG', '-O2','-ftree-vectorize','-msse','-msse2','-msse3','-mfpmath=sse']
else:
CCFLAGS += ['-fno-strict-aliasing']
REL_CFLAGS = []
REL_CXXFLAGS = []
REL_CCFLAGS = ['-DNDEBUG', '-O2']
CCFLAGS += ['-fno-strict-aliasing']
REL_CFLAGS = []
REL_CXXFLAGS = []
REL_CCFLAGS = ['-DNDEBUG', '-O2']
# Intel 64bit Macs are Core2Duo and up
if MACOSX_ARCHITECTURE == 'x86_64':
REL_CCFLAGS += ['-march=core2','-mssse3','-with-tune=core2','-enable-threads']
REL_CCFLAGS += ['-march=core2','-mssse3','-with-tune=core2','-enable-threads']
CC_WARN = ['-Wall']
C_WARN = ['-Wno-char-subscripts', '-Wpointer-arith', '-Wcast-align', '-Wdeclaration-after-statement', '-Wno-unknown-pragmas', '-Wstrict-prototypes']

@ -84,6 +84,7 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE = False
WITH_BF_PLAYER = True
WITH_BF_OCEANSIM = True
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'
@ -174,8 +175,8 @@ CCFLAGS = ['-pipe','-fPIC','-funsigned-char','-fno-strict-aliasing','-D_LARGEFIL
CPPFLAGS = []
CXXFLAGS = []
if WITH_BF_FFMPEG:
# libavutil needs UINT64_C()
CXXFLAGS += ['-D__STDC_CONSTANT_MACROS', ]
# libavutil needs UINT64_C()
CXXFLAGS += ['-D__STDC_CONSTANT_MACROS', ]
REL_CFLAGS = []
REL_CXXFLAGS = []
REL_CCFLAGS = ['-DNDEBUG', '-O2']

@ -84,6 +84,7 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE = False
WITH_BF_PLAYER = True
WITH_BF_OCEANSIM = True
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'
@ -174,8 +175,8 @@ CCFLAGS = ['-pipe','-fPIC','-funsigned-char','-fno-strict-aliasing','-D_LARGEFIL
CPPFLAGS = []
CXXFLAGS = []
if WITH_BF_FFMPEG:
# libavutil needs UINT64_C()
CXXFLAGS += ['-D__STDC_CONSTANT_MACROS', ]
# libavutil needs UINT64_C()
CXXFLAGS += ['-D__STDC_CONSTANT_MACROS', ]
REL_CFLAGS = []
REL_CXXFLAGS = []
REL_CCFLAGS = ['-DNDEBUG', '-O2']

@ -84,6 +84,7 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE = False
WITH_BF_PLAYER = True
WITH_BF_OCEANSIM = True
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'
@ -174,8 +175,8 @@ CXXFLAGS = []
CPPFLAGS = []
if WITH_BF_FFMPEG:
# libavutil needs UINT64_C()
CXXFLAGS += ['-D__STDC_CONSTANT_MACROS', ]
# libavutil needs UINT64_C()
CXXFLAGS += ['-D__STDC_CONSTANT_MACROS', ]
REL_CFLAGS = []
REL_CXXFLAGS = []
REL_CCFLAGS = ['-DNDEBUG', '-O2']

@ -94,6 +94,7 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE = True
WITH_BF_PLAYER = True
WITH_BF_OCEANSIM = True
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'
@ -196,7 +197,8 @@ BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib'
BF_JEMALLOC_LIB = 'jemalloc'
BF_JEMALLOC_LIB_STATIC = '${BF_JEMALLOC_LIBPATH}/libjemalloc.a'
WITH_BF_OIIO = True
WITH_BF_OIIO = True
WITH_BF_STATICOIIO = False
BF_OIIO = LIBDIR + '/oiio'
if not os.path.exists(LCGDIR + '/oiio'):
WITH_BF_OIIO = False
@ -206,6 +208,7 @@ BF_OIIO_LIB = 'OpenImageIO'
BF_OIIO_LIBPATH = BF_OIIO + '/lib'
WITH_BF_BOOST = True
WITH_BF_STATICBOOST = False
BF_BOOST = LIBDIR + '/boost'
if not os.path.exists(LCGDIR + '/boost'):
WITH_BF_BOOST = False
@ -224,6 +227,7 @@ BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-pthread']
#SpaceNavigator and friends
WITH_BF_3DMOUSE = True
WITH_BF_STATIC3DMOUSE = False
BF_3DMOUSE = '/usr'
BF_3DMOUSE_INC = '${BF_3DMOUSE}/include'
BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib'
@ -243,8 +247,8 @@ CPPFLAGS = []
# g++ 4.6, only needed for bullet
CXXFLAGS += ['-fpermissive']
if WITH_BF_FFMPEG:
# libavutil needs UINT64_C()
CXXFLAGS += ['-D__STDC_CONSTANT_MACROS', ]
# libavutil needs UINT64_C()
CXXFLAGS += ['-D__STDC_CONSTANT_MACROS', ]
REL_CFLAGS = []
REL_CXXFLAGS = []
REL_CCFLAGS = ['-DNDEBUG', '-O2']

@ -90,6 +90,7 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE = True
WITH_BF_PLAYER = False
WITH_BF_OCEANSIM = True
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'

@ -94,7 +94,7 @@ BF_OPENJPEG_LIB = ''
BF_OPENJPEG_INC = '${BF_OPENJPEG}'
BF_OPENJPEG_LIBPATH='${BF_OPENJPEG}/lib'
WITH_BF_FFTW3 = False
WITH_BF_FFTW3 = True
BF_FFTW3 = LIBDIR + '/gcc/fftw3'
BF_FFTW3_INC = '${BF_FFTW3}/include'
BF_FFTW3_LIB = 'fftw3'
@ -102,6 +102,7 @@ BF_FFTW3_LIBPATH = '${BF_FFTW3}/lib'
WITH_BF_GAMEENGINE = True
WITH_BF_PLAYER = True
WITH_BF_OCEANSIM = True
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'

@ -96,6 +96,7 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE = True
WITH_BF_PLAYER = True
WITH_BF_OCEANSIM = True
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'

@ -100,6 +100,7 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib'
WITH_BF_GAMEENGINE = True
WITH_BF_PLAYER = True
WITH_BF_OCEANSIM = True
WITH_BF_BULLET = True
BF_BULLET = '#extern/bullet2/src'

@ -34,6 +34,7 @@ import bcolors
bc = bcolors.bcolors()
import btools
VERSION = btools.VERSION
VERSION_RELEASE_CYCLE = btools.VERSION_RELEASE_CYCLE
Split = SCons.Util.Split
Action = SCons.Action.Action
@ -257,9 +258,9 @@ def setup_syslibs(lenv):
if lenv['WITH_BF_OGG']:
syslibs += Split(lenv['BF_OGG_LIB'])
if lenv['WITH_BF_JACK']:
syslibs += Split(lenv['BF_JACK_LIB'])
syslibs += Split(lenv['BF_JACK_LIB'])
if lenv['WITH_BF_SNDFILE'] and not lenv['WITH_BF_STATICSNDFILE']:
syslibs += Split(lenv['BF_SNDFILE_LIB'])
syslibs += Split(lenv['BF_SNDFILE_LIB'])
if lenv['WITH_BF_FFTW3'] and not lenv['WITH_BF_STATICFFTW3']:
syslibs += Split(lenv['BF_FFTW3_LIB'])
if lenv['WITH_BF_SDL']:
@ -584,6 +585,10 @@ def AppIt(target=None, source=None, env=None):
cmd = 'cp -R %s/release/scripts %s/%s.app/Contents/MacOS/%s/'%(bldroot,installdir,binary,VERSION)
commands.getoutput(cmd)
if VERSION_RELEASE_CYCLE == "release":
cmd = 'rm -rf %s/%s.app/Contents/MacOS/%s/scripts/addons_contrib'%(installdir,binary,VERSION)
commands.getoutput(cmd)
if env['WITH_BF_CYCLES']:
croot = '%s/intern/cycles' % (bldroot)
cinstalldir = '%s/%s.app/Contents/MacOS/%s/scripts/addons/cycles' % (installdir,binary,VERSION)
@ -759,17 +764,17 @@ class BlenderEnvironment(SConsEnvironment):
lenv.Append(CPPPATH=includes)
lenv.Append(CPPDEFINES=defines)
if lenv['BF_DEBUG'] or (libname in quickdebug):
lenv.Append(CFLAGS = lenv['BF_DEBUG_CFLAGS'])
lenv.Append(CCFLAGS = lenv['BF_DEBUG_CCFLAGS'])
lenv.Append(CXXFLAGS = lenv['BF_DEBUG_CXXFLAGS'])
lenv.Append(CFLAGS = lenv['BF_DEBUG_CFLAGS'])
lenv.Append(CCFLAGS = lenv['BF_DEBUG_CCFLAGS'])
lenv.Append(CXXFLAGS = lenv['BF_DEBUG_CXXFLAGS'])
else:
lenv.Append(CFLAGS = lenv['REL_CFLAGS'])
lenv.Append(CCFLAGS = lenv['REL_CCFLAGS'])
lenv.Append(CXXFLAGS = lenv['REL_CXXFLAGS'])
lenv.Append(CFLAGS = lenv['REL_CFLAGS'])
lenv.Append(CCFLAGS = lenv['REL_CCFLAGS'])
lenv.Append(CXXFLAGS = lenv['REL_CXXFLAGS'])
if lenv['BF_PROFILE']:
lenv.Append(CFLAGS = lenv['BF_PROFILE_CFLAGS'])
lenv.Append(CCFLAGS = lenv['BF_PROFILE_CCFLAGS'])
lenv.Append(CXXFLAGS = lenv['BF_PROFILE_CXXFLAGS'])
lenv.Append(CFLAGS = lenv['BF_PROFILE_CFLAGS'])
lenv.Append(CCFLAGS = lenv['BF_PROFILE_CCFLAGS'])
lenv.Append(CXXFLAGS = lenv['BF_PROFILE_CXXFLAGS'])
if compileflags:
lenv.Replace(CFLAGS = compileflags)
if cc_compileflags:
@ -829,7 +834,7 @@ class BlenderEnvironment(SConsEnvironment):
if lenv['WITH_BF_PYTHON']:
lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
if lenv['CXX'].endswith('CC'):
lenv.Replace(LINK = '$CXX')
lenv.Replace(LINK = '$CXX')
if lenv['OURPLATFORM']=='darwin':
if lenv['WITH_BF_PYTHON']:
lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
@ -841,8 +846,8 @@ class BlenderEnvironment(SConsEnvironment):
lenv.Append(LIBPATH=libpath)
lenv.Append(LIBS=libs)
if lenv['WITH_BF_QUICKTIME']:
lenv.Append(LIBS = lenv['BF_QUICKTIME_LIB'])
lenv.Append(LIBPATH = lenv['BF_QUICKTIME_LIBPATH'])
lenv.Append(LIBS = lenv['BF_QUICKTIME_LIB'])
lenv.Append(LIBPATH = lenv['BF_QUICKTIME_LIBPATH'])
prog = lenv.Program(target=builddir+'bin/'+progname, source=sources)
if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc') and lenv['BF_BSC']:
f = lenv.File(progname + '.bsc', builddir)

@ -52,7 +52,7 @@ def get_version():
else:
ver_display = "%s%s" % (ver_base, ver_char) # assume release
return ver_base, ver_display
return ver_base, ver_display, ver_cycle
raise Exception("%s: missing version string" % fname)
@ -80,7 +80,7 @@ def checkEndian():
# This is used in creating the local config directories
VERSION, VERSION_DISPLAY = get_version()
VERSION, VERSION_DISPLAY, VERSION_RELEASE_CYCLE = get_version()
REVISION = get_revision()
ENDIAN = checkEndian()
@ -152,6 +152,7 @@ def validate_arguments(args, bc):
'WITH_BF_FLUID',
'WITH_BF_DECIMATE',
'WITH_BF_BOOLEAN',
'WITH_BF_OCEANSIM',
'WITH_BF_CXX_GUARDEDALLOC',
'WITH_BF_JEMALLOC', 'WITH_BF_STATICJEMALLOC', 'BF_JEMALLOC', 'BF_JEMALLOC_INC', 'BF_JEMALLOC_LIBPATH', 'BF_JEMALLOC_LIB', 'BF_JEMALLOC_LIB_STATIC',
'BUILDBOT_BRANCH',
@ -259,6 +260,7 @@ def read_opts(env, cfg, args):
(BoolVariable('WITH_BF_FLUID', 'Build with Fluid simulation (Elbeem)', True)),
(BoolVariable('WITH_BF_DECIMATE', 'Build with decimate modifier', True)),
(BoolVariable('WITH_BF_BOOLEAN', 'Build with boolean modifier', True)),
(BoolVariable('WITH_BF_OCEANSIM', 'Build with ocean simulation', False)),
('BF_PROFILE_FLAGS', 'Profiling compiler flags', ''),
(BoolVariable('WITH_BF_OPENAL', 'Use OpenAL if true', False)),
('BF_OPENAL', 'Base path for OpenAL', ''),

@ -52,9 +52,9 @@ else:
cmd = [blender_bin, "--help"]
print(" executing:", " ".join(cmd))
blender_help = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0].decode()
blender_help = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0].decode(encoding="utf-8")
blender_version = subprocess.Popen([blender_bin, "--version"], stdout=subprocess.PIPE).communicate()[0].decode().strip()
blender_version = subprocess.Popen([blender_bin, "--version"], stdout=subprocess.PIPE).communicate()[0].decode(encoding="utf-8").strip()
blender_version = blender_version.split("Build")[0]
date_string = datetime.date.fromtimestamp(time.time()).strftime("%B %d, %Y")

@ -1,45 +0,0 @@
# Testing the BGL module
import Blender
from Blender.BGL import *
from Blender import Draw
R = G = B = 0
A = 1
instructions = "Hold mouse buttons to change the background color."
quitting = " Press ESC or q to quit."
def show_win():
glClearColor(R,G,B,A) # define color used to clear buffers
glClear(GL_COLOR_BUFFER_BIT) # use it to clear the color buffer
glColor3f(1,1,1) # change default color
glRasterPos2i(50,100) # move cursor to x = 50, y = 100
Draw.Text("Testing BGL + Draw") # draw this text there
glRasterPos2i(350,20) # move cursor again
Draw.Text(instructions + quitting) # draw another msg
glBegin(GL_LINE_LOOP) # begin a vertex-data list
glVertex2i(46,92)
glVertex2i(120,92)
glVertex2i(120,115)
glVertex2i(46,115)
glEnd() # close this list
glColor3f(0.35,0.18,0.92) # change default color again
glBegin(GL_POLYGON) # another list, for a polygon
glVertex2i(315, 292)
glVertex2i(412, 200)
glVertex2i(264, 256)
glEnd()
Draw.Redraw(1) # make changes visible.
def ev(evt, val): # this is a callback for Draw.Register()
global R,G,B,A # it handles input events
if evt == Draw.ESCKEY or evt == Draw.QKEY:
Draw.Exit() # this quits the script
elif evt == Draw.LEFTMOUSE: R = 1 - R
elif evt == Draw.MIDDLEMOUSE: G = 1 - G
elif evt == Draw.RIGHTMOUSE: B = 1 - B
else:
Draw.Register(show_win, ev, None)
Draw.Register(show_win, ev, None) # start the main loop

@ -147,7 +147,7 @@ Armature Bones in Blender have three distinct data structures that contain them.
.. note::
In the following examples ``bpy.context.object`` is assumed to be an armature object.
In the following examples ``bpy.context.object`` is assumed to be an armature object.
Edit Bones
@ -163,11 +163,11 @@ This is only possible in edit mode.
This will be empty outside of editmode.
>>> mybones = bpy.context.selected_editable_bones
>>> mybones = bpy.context.selected_editable_bones
Returns an editbone only in edit mode.
>>> bpy.context.active_bone
>>> bpy.context.active_bone
Bones (Object Mode)
@ -179,15 +179,15 @@ Example using :class:`bpy.types.Bone` in object or pose mode:
Returns a bone (not an editbone) outside of edit mode
>>> bpy.context.active_bone
>>> bpy.context.active_bone
This works, as with blender the setting can be edited in any mode
>>> bpy.context.object.data.bones["Bone"].use_deform = True
>>> bpy.context.object.data.bones["Bone"].use_deform = True
Accessible but read-only
>>> tail = myobj.data.bones["Bone"].tail
>>> tail = myobj.data.bones["Bone"].tail
Pose Bones
@ -199,20 +199,20 @@ Examples using :class:`bpy.types.PoseBone` in object or pose mode:
.. code-block:: python
# Gets the name of the first constraint (if it exists)
bpy.context.object.pose.bones["Bone"].constraints[0].name
# Gets the name of the first constraint (if it exists)
bpy.context.object.pose.bones["Bone"].constraints[0].name
# Gets the last selected pose bone (pose mode only)
bpy.context.active_pose_bone
# Gets the last selected pose bone (pose mode only)
bpy.context.active_pose_bone
.. note::
Notice the pose is accessed from the object rather than the object data, this is why blender can have 2 or more objects sharing the same armature in different poses.
Notice the pose is accessed from the object rather than the object data, this is why blender can have 2 or more objects sharing the same armature in different poses.
.. note::
Strictly speaking PoseBone's are not bones, they are just the state of the armature, stored in the :class:`bpy.types.Object` rather than the :class:`bpy.types.Armature`, the real bones are however accessible from the pose bones - :class:`bpy.types.PoseBone.bone`
Strictly speaking PoseBone's are not bones, they are just the state of the armature, stored in the :class:`bpy.types.Object` rather than the :class:`bpy.types.Armature`, the real bones are however accessible from the pose bones - :class:`bpy.types.PoseBone.bone`
Armature Mode Switching
@ -223,6 +223,86 @@ While writing scripts that deal with armatures you may find you have to switch b
This is mainly an issue with editmode since pose data can be manipulated without having to be in pose mode, however for operator access you may still need to enter pose mode.
Data Names
==========
Naming Limitations
------------------
A common mistake is to assume newly created data is given the requested name.
This can cause bugs when you add some data (normally imported) and then reference it later by name.
.. code-block:: python
bpy.data.meshes.new(name=meshid)
# normally some code, function calls...
bpy.data.meshes[meshid]
Or with name assignment...
.. code-block:: python
obj.name = objname
# normally some code, function calls...
obj = bpy.data.meshes[objname]
Data names may not match the assigned values if they exceed the maximum length, are already used or an empty string.
Its better practice not to reference objects by names at all, once created you can store the data in a list, dictionary, on a class etc, there is rarely a reason to have to keep searching for the same data by name.
If you do need to use name references, its best to use a dictionary to maintain a mapping between the names of the imported assets and the newly created data, this way you don't run this risk of referencing existing data from the blend file, or worse modifying it.
.. code-block:: python
# typically declared in the main body of the function.
mesh_name_mapping = {}
mesh = bpy.data.meshes.new(name=meshid)
mesh_name_mapping[meshid] = mesh
# normally some code, or function calls...
# use own dictionary rather then bpy.data
mesh = mesh_name_mapping[meshid]
Library Collisions
------------------
Blender keeps data names unique - :class:`bpy.types.ID.name` so you can't name two objects, meshes, scenes etc the same thing by accident.
However when linking in library data from another blend file naming collisions can occur, so its best to avoid referencing data by name at all.
This can be tricky at times and not even blender handles this correctly in some case (when selecting the modifier object for eg you can't select between multiple objects with the same name), but its still good to try avoid problems in this area.
If you need to select between local and library data, there is a feature in ``bpy.data`` members to allow for this.
.. code-block:: python
# typical name lookup, could be local or library.
obj = bpy.data.objects["my_obj"]
# library object name look up using a pair
# where the second argument is the library path matching bpy.types.Library.filepath
obj = bpy.data.objects["my_obj", "//my_lib.blend"]
# local object name look up using a pair
# where the second argument excludes library data from being returned.
obj = bpy.data.objects["my_obj", None]
# both the examples above also works for 'get'
obj = bpy.data.objects.get(("my_obj", None))
Relative File Paths
===================
@ -230,12 +310,12 @@ Blenders relative file paths are not compatible with standard python modules suc
Built in python functions don't understand blenders ``//`` prefix which denotes the blend file path.
A common case where you would run into this problem is when exporting a material with assosiated image paths.
A common case where you would run into this problem is when exporting a material with associated image paths.
>>> bpy.path.abspath(image.filepath)
When using blender data from linked libraries there is an unfortunate complication since the path will be relative to the library rather then the open blend file. When the data block may be from an external blend file pass the library argument from the `bpy.types.ID`.
When using blender data from linked libraries there is an unfortunate complication since the path will be relative to the library rather then the open blend file. When the data block may be from an external blend file pass the library argument from the :class:`bpy.types.ID`.
>>> bpy.path.abspath(image.filepath, library=image.library)
@ -289,7 +369,7 @@ Unicode encoding/decoding is a big topic with comprehensive python documentation
* To print paths or to include them in the user interface use ``repr(path)`` first or ``"%r" % path`` with string formatting.
* **Possibly** - use bytes instead of python strings, when reading some input its less trouble to read it as binary data though you will still need to deciede how to treat any strings you want to use with Blender, some importers do this.
* **Possibly** - use bytes instead of python strings, when reading some input its less trouble to read it as binary data though you will still need to decide how to treat any strings you want to use with Blender, some importers do this.
Strange errors using 'threading' module
@ -458,3 +538,14 @@ Removing Data
**Any** data that you remove shouldn't be modified or accessed afterwards, this includes f-curves, drivers, render layers, timeline markers, modifiers, constraints along with objects, scenes, groups, bones.. etc.
This is a problem in the API at the moment that we should eventually solve.
sys.exit
========
Some python modules will call sys.exit() themselves when an error occurs, while not common behavior this is something to watch out for because it may seem as if blender is crashing since sys.exit() will quit blender immediately.
For example, the ``optparse`` module will print an error and exit if the arguments are invalid.
An ugly way of troubleshooting this is to set ``sys.exit = None`` and see what line of python code is quitting, you could of course replace ``sys.exit``/ with your own function but manipulating python in this way is bad practice.

@ -597,6 +597,7 @@ def pycontext2sphinx(BASEPATH):
"active_base": ("ObjectBase", False),
"active_bone": ("Bone", False),
"active_object": ("Object", False),
"active_operator": ("Operator", False),
"active_pose_bone": ("PoseBone", False),
"armature": ("Armature", False),
"bone": ("Bone", False),
@ -605,6 +606,7 @@ def pycontext2sphinx(BASEPATH):
"cloth": ("ClothModifier", False),
"collision": ("CollisionModifier", False),
"curve": ("Curve", False),
"dynamic_paint": ("DynamicPaintModifier", False),
"edit_bone": ("EditBone", False),
"edit_image": ("Image", False),
"edit_object": ("Object", False),
@ -643,6 +645,7 @@ def pycontext2sphinx(BASEPATH):
"speaker": ("Speaker", False),
"texture": ("Texture", False),
"texture_slot": ("MaterialTextureSlot", False),
"texture_user": ("ID", False),
"vertex_paint_object": ("Object", False),
"visible_bases": ("ObjectBase", True),
"visible_bones": ("Object", True),
@ -663,7 +666,7 @@ def pycontext2sphinx(BASEPATH):
char_array = c_char_p_p.from_address(attr)
i = 0
while char_array[i] is not None:
member = ctypes.string_at(char_array[i]).decode()
member = ctypes.string_at(char_array[i]).decode(encoding="ascii")
fw(".. data:: %s\n\n" % member)
member_type, is_seq = type_map[member]
fw(" :type: %s :class:`bpy.types.%s`\n\n" % ("sequence of " if is_seq else "", member_type))

@ -52,8 +52,10 @@ set(SRC
libmv/image/array_nd.cc
libmv/tracking/pyramid_region_tracker.cc
libmv/tracking/sad.cc
libmv/tracking/esm_region_tracker.cc
libmv/tracking/trklt_region_tracker.cc
libmv/tracking/klt_region_tracker.cc
libmv/tracking/lmicklt_region_tracker.cc
libmv/tracking/retrack_region_tracker.cc
libmv/multiview/projection.cc
libmv/multiview/conditioning.cc
@ -99,8 +101,10 @@ set(SRC
libmv/tracking/retrack_region_tracker.h
libmv/tracking/sad.h
libmv/tracking/pyramid_region_tracker.h
libmv/tracking/esm_region_tracker.h
libmv/tracking/trklt_region_tracker.h
libmv/tracking/klt_region_tracker.h
libmv/tracking/lmicklt_region_tracker.h
libmv/base/id_generator.h
libmv/base/vector.h
libmv/base/scoped_ptr.h

@ -33,8 +33,10 @@
#include "glog/logging.h"
#include "Math/v3d_optimization.h"
#include "libmv/tracking/esm_region_tracker.h"
#include "libmv/tracking/klt_region_tracker.h"
#include "libmv/tracking/trklt_region_tracker.h"
#include "libmv/tracking/lmicklt_region_tracker.h"
#include "libmv/tracking/pyramid_region_tracker.h"
#include "libmv/tracking/sad.h"
@ -47,6 +49,7 @@
#include "libmv/simple_pipeline/camera_intrinsics.h"
#include <stdlib.h>
#include <assert.h>
#ifdef DUMP_FAILURE
# include <png.h>
@ -56,13 +59,6 @@
# define snprintf _snprintf
#endif
#define DEFAULT_WINDOW_HALFSIZE 5
typedef struct libmv_RegionTracker {
libmv::TrkltRegionTracker *trklt_region_tracker;
libmv::RegionTracker *region_tracker;
} libmv_RegionTracker;
typedef struct libmv_Reconstruction {
libmv::EuclideanReconstruction reconstruction;
@ -110,22 +106,18 @@ void libmv_setLoggingVerbosity(int verbosity)
/* ************ RegionTracker ************ */
libmv_RegionTracker *libmv_regionTrackerNew(int max_iterations, int pyramid_level)
libmv_RegionTracker *libmv_regionTrackerNew(int max_iterations, int pyramid_level, int half_window_size)
{
libmv::TrkltRegionTracker *trklt_region_tracker = new libmv::TrkltRegionTracker;
libmv::EsmRegionTracker *klt_region_tracker = new libmv::EsmRegionTracker;
trklt_region_tracker->half_window_size = DEFAULT_WINDOW_HALFSIZE;
trklt_region_tracker->max_iterations = max_iterations;
trklt_region_tracker->min_determinant = 1e-4;
klt_region_tracker->half_window_size = half_window_size;
klt_region_tracker->max_iterations = max_iterations;
klt_region_tracker->min_determinant = 1e-4;
libmv::PyramidRegionTracker *region_tracker =
new libmv::PyramidRegionTracker(trklt_region_tracker, pyramid_level);
new libmv::PyramidRegionTracker(klt_region_tracker, pyramid_level);
libmv_RegionTracker *configured_region_tracker = new libmv_RegionTracker;
configured_region_tracker->trklt_region_tracker = trklt_region_tracker;
configured_region_tracker->region_tracker = region_tracker;
return configured_region_tracker;
return (libmv_RegionTracker *)region_tracker;
}
static void floatBufToImage(const float *buf, int width, int height, libmv::FloatImage *image)
@ -267,18 +259,11 @@ static void saveBytesImage(char *prefix, unsigned char *data, int width, int hei
#endif
int libmv_regionTrackerTrack(libmv_RegionTracker *libmv_tracker, const float *ima1, const float *ima2,
int width, int height, int half_window_size,
double x1, double y1, double *x2, double *y2)
int width, int height, double x1, double y1, double *x2, double *y2)
{
libmv::RegionTracker *region_tracker;
libmv::TrkltRegionTracker *trklt_region_tracker;
libmv::RegionTracker *region_tracker = (libmv::RegionTracker *)libmv_tracker;
libmv::FloatImage old_patch, new_patch;
trklt_region_tracker = libmv_tracker->trklt_region_tracker;
region_tracker = libmv_tracker->region_tracker;
trklt_region_tracker->half_window_size = half_window_size;
floatBufToImage(ima1, width, height, &old_patch);
floatBufToImage(ima2, width, height, &new_patch);
@ -301,8 +286,9 @@ int libmv_regionTrackerTrack(libmv_RegionTracker *libmv_tracker, const float *im
void libmv_regionTrackerDestroy(libmv_RegionTracker *libmv_tracker)
{
delete libmv_tracker->region_tracker;
delete libmv_tracker;
libmv::RegionTracker *region_tracker= (libmv::RegionTracker *)libmv_tracker;
delete region_tracker;
}
/* ************ Tracks ************ */
@ -353,8 +339,24 @@ void libmv_tracksDestroy(libmv_Tracks *libmv_tracks)
/* ************ Reconstruction solver ************ */
int libmv_refineParametersAreValid(int parameters) {
return (parameters == (LIBMV_REFINE_FOCAL_LENGTH)) ||
(parameters == (LIBMV_REFINE_FOCAL_LENGTH |
LIBMV_REFINE_PRINCIPAL_POINT)) ||
(parameters == (LIBMV_REFINE_FOCAL_LENGTH |
LIBMV_REFINE_PRINCIPAL_POINT |
LIBMV_REFINE_RADIAL_DISTORTION_K1 |
LIBMV_REFINE_RADIAL_DISTORTION_K2)) ||
(parameters == (LIBMV_REFINE_FOCAL_LENGTH |
LIBMV_REFINE_RADIAL_DISTORTION_K1 |
LIBMV_REFINE_RADIAL_DISTORTION_K2)) ||
(parameters == (LIBMV_REFINE_FOCAL_LENGTH |
LIBMV_REFINE_RADIAL_DISTORTION_K1));
}
libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyframe1, int keyframe2,
double focal_length, double principal_x, double principal_y, double k1, double k2, double k3)
int refine_intrinsics, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3)
{
/* Invert the camera intrinsics. */
libmv::vector<libmv::Marker> markers = ((libmv::Tracks*)tracks)->AllMarkers();
@ -366,25 +368,43 @@ libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyfra
intrinsics->SetPrincipalPoint(principal_x, principal_y);
intrinsics->SetRadialDistortion(k1, k2, k3);
if(focal_length) {
/* do a lens undistortion if focal length is non-zero only */
for (int i = 0; i < markers.size(); ++i) {
intrinsics->InvertIntrinsics(markers[i].x,
markers[i].y,
&(markers[i].x),
&(markers[i].y));
}
for (int i = 0; i < markers.size(); ++i) {
intrinsics->InvertIntrinsics(markers[i].x,
markers[i].y,
&(markers[i].x),
&(markers[i].y));
}
libmv::Tracks normalized_tracks(markers);
// printf("frames to init from: %d, %d\n", keyframe1, keyframe2);
libmv::vector<libmv::Marker> keyframe_markers =
normalized_tracks.MarkersForTracksInBothImages(keyframe1, keyframe2);
// printf("number of markers for init: %d\n", keyframe_markers.size());
libmv::EuclideanReconstructTwoFrames(keyframe_markers, reconstruction);
libmv::EuclideanBundle(normalized_tracks, reconstruction);
libmv::EuclideanCompleteReconstruction(normalized_tracks, reconstruction);
if (refine_intrinsics) {
/* only a few combinations are supported but trust the caller */
int libmv_refine_flags = 0;
if (refine_intrinsics & LIBMV_REFINE_FOCAL_LENGTH) {
libmv_refine_flags |= libmv::BUNDLE_FOCAL_LENGTH;
}
if (refine_intrinsics & LIBMV_REFINE_PRINCIPAL_POINT) {
libmv_refine_flags |= libmv::BUNDLE_PRINCIPAL_POINT;
}
if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K1) {
libmv_refine_flags |= libmv::BUNDLE_RADIAL_K1;
}
if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K2) {
libmv_refine_flags |= libmv::BUNDLE_RADIAL_K2;
}
libmv::EuclideanBundleCommonIntrinsics(*(libmv::Tracks *)tracks, libmv_refine_flags, reconstruction, intrinsics);
}
libmv_reconstruction->tracks = *(libmv::Tracks *)tracks;
libmv_reconstruction->error = libmv::EuclideanReprojectionError(*(libmv::Tracks *)tracks, *reconstruction, *intrinsics);
@ -608,6 +628,10 @@ void libmv_destroyFeatures(struct libmv_Features *libmv_features)
/* ************ camera intrinsics ************ */
struct libmv_CameraIntrinsics *libmv_ReconstructionExtractIntrinsics(struct libmv_Reconstruction *libmv_Reconstruction) {
return (struct libmv_CameraIntrinsics *)&libmv_Reconstruction->intrinsics;
}
struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNew(double focal_length, double principal_x, double principal_y,
double k1, double k2, double k3, int width, int height)
{
@ -654,6 +678,16 @@ void libmv_CameraIntrinsicsUpdate(struct libmv_CameraIntrinsics *libmvIntrinsics
intrinsics->SetImageSize(width, height);
}
void libmv_CameraIntrinsicsExtract(struct libmv_CameraIntrinsics *libmvIntrinsics, double *focal_length,
double *principal_x, double *principal_y, double *k1, double *k2, double *k3, int *width, int *height) {
libmv::CameraIntrinsics *intrinsics= (libmv::CameraIntrinsics *) libmvIntrinsics;
*focal_length = intrinsics->focal_length();
*principal_x = intrinsics->principal_point_x();
*principal_y = intrinsics->principal_point_y();
*k1 = intrinsics->k1();
*k2 = intrinsics->k2();
}
void libmv_CameraIntrinsicsUndistortByte(struct libmv_CameraIntrinsics *libmvIntrinsics,
unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels)
{

@ -43,10 +43,9 @@ void libmv_startDebugLogging(void);
void libmv_setLoggingVerbosity(int verbosity);
/* RegionTracker */
struct libmv_RegionTracker *libmv_regionTrackerNew(int max_iterations, int pyramid_level);
struct libmv_RegionTracker *libmv_regionTrackerNew(int max_iterations, int pyramid_level, int half_window_size);
int libmv_regionTrackerTrack(struct libmv_RegionTracker *libmv_tracker, const float *ima1, const float *ima2,
int width, int height, int half_window_size,
double x1, double y1, double *x2, double *y2);
int width, int height, double x1, double y1, double *x2, double *y2);
void libmv_regionTrackerDestroy(struct libmv_RegionTracker *libmv_tracker);
/* SAD Tracker */
@ -61,8 +60,14 @@ void libmv_tracksInsert(struct libmv_Tracks *libmv_tracks, int image, int track,
void libmv_tracksDestroy(struct libmv_Tracks *libmv_tracks);
/* Reconstruction solver */
#define LIBMV_REFINE_FOCAL_LENGTH (1<<0)
#define LIBMV_REFINE_PRINCIPAL_POINT (1<<1)
#define LIBMV_REFINE_RADIAL_DISTORTION_K1 (1<<2)
#define LIBMV_REFINE_RADIAL_DISTORTION_K2 (1<<4)
int libmv_refineParametersAreValid(int parameters);
struct libmv_Reconstruction *libmv_solveReconstruction(struct libmv_Tracks *tracks, int keyframe1, int keyframe2,
double focal_length, double principal_x, double principal_y, double k1, double k2, double k3);
int refine_intrinsics, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3);
int libmv_reporojectionPointForTrack(struct libmv_Reconstruction *libmv_reconstruction, int track, double pos[3]);
double libmv_reporojectionErrorForTrack(struct libmv_Reconstruction *libmv_reconstruction, int track);
double libmv_reporojectionErrorForImage(struct libmv_Reconstruction *libmv_reconstruction, int image);
@ -80,18 +85,21 @@ void libmv_getFeature(struct libmv_Features *libmv_features, int number, double
void libmv_destroyFeatures(struct libmv_Features *libmv_features);
/* camera intrinsics */
struct libmv_CameraIntrinsics *libmv_ReconstructionExtractIntrinsics(struct libmv_Reconstruction *libmv_Reconstruction);
struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNew(double focal_length, double principal_x, double principal_y,
double k1, double k2, double k3, int width, int height);
struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsCopy(struct libmv_CameraIntrinsics *libmvIntrinsics);
struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsCopy(struct libmv_CameraIntrinsics *libmvIntrinsics);
void libmv_CameraIntrinsicsDestroy(struct libmv_CameraIntrinsics *libmvIntrinsics);
void libmv_CameraIntrinsicsUpdate(struct libmv_CameraIntrinsics *libmvIntrinsics, double focal_length,
double principal_x, double principal_y, double k1, double k2, double k3, int width, int height);
void libmv_CameraIntrinsicsExtract(struct libmv_CameraIntrinsics *libmvIntrinsics, double *focal_length,
double *principal_x, double *principal_y, double *k1, double *k2, double *k3, int *width, int *height);
void libmv_CameraIntrinsicsUndistortByte(struct libmv_CameraIntrinsics *libmvIntrinsics,
unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels);

@ -27,6 +27,8 @@
#include "libmv/multiview/fundamental.h"
#include "libmv/multiview/projection.h"
#include "libmv/numeric/numeric.h"
#include "libmv/simple_pipeline/camera_intrinsics.h"
#include "libmv/simple_pipeline/bundle.h"
#include "libmv/simple_pipeline/reconstruction.h"
#include "libmv/simple_pipeline/tracks.h"
#include "third_party/ssba/Geometry/v3d_cameramatrix.h"
@ -38,6 +40,18 @@ namespace libmv {
void EuclideanBundle(const Tracks &tracks,
EuclideanReconstruction *reconstruction) {
CameraIntrinsics intrinsics;
EuclideanBundleCommonIntrinsics(tracks,
BUNDLE_NO_INTRINSICS,
reconstruction,
&intrinsics);
}
void EuclideanBundleCommonIntrinsics(const Tracks &tracks,
int bundle_intrinsics,
EuclideanReconstruction *reconstruction,
CameraIntrinsics *intrinsics) {
LG << "Original intrinsics: " << *intrinsics;
vector<Marker> markers = tracks.AllMarkers();
// "index" in this context is the index that V3D's optimizer will see. The
@ -69,18 +83,20 @@ void EuclideanBundle(const Tracks &tracks,
}
}
// Make a V3D identity matrix, needed in a few places for K, since this
// assumes a calibrated setup.
V3D::Matrix3x3d identity3x3;
identity3x3[0][0] = 1.0;
identity3x3[0][1] = 0.0;
identity3x3[0][2] = 0.0;
identity3x3[1][0] = 0.0;
identity3x3[1][1] = 1.0;
identity3x3[1][2] = 0.0;
identity3x3[2][0] = 0.0;
identity3x3[2][1] = 0.0;
identity3x3[2][2] = 1.0;
// Convert libmv's K matrix to V3d's K matrix.
V3D::Matrix3x3d v3d_K;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
v3d_K[i][j] = intrinsics->K()(i, j);
}
}
// Convert libmv's distortion to v3d distortion.
V3D::StdDistortionFunction v3d_distortion;
v3d_distortion.k1 = intrinsics->k1();
v3d_distortion.k2 = intrinsics->k2();
v3d_distortion.p1 = intrinsics->p1();
v3d_distortion.p2 = intrinsics->p2();
// Convert libmv's cameras to V3D's cameras.
std::vector<V3D::CameraMatrix> v3d_cameras(index_to_camera.size());
@ -98,7 +114,7 @@ void EuclideanBundle(const Tracks &tracks,
}
t[i] = t_libmv(i);
}
v3d_cameras[k].setIntrinsic(identity3x3);
v3d_cameras[k].setIntrinsic(v3d_K);
v3d_cameras[k].setRotation(R);
v3d_cameras[k].setTranslation(t);
}
@ -134,27 +150,81 @@ void EuclideanBundle(const Tracks &tracks,
}
LG << "Number of residuals: " << num_residuals;
// This is calibrated reconstruction, so use zero distortion.
V3D::StdDistortionFunction v3d_distortion;
v3d_distortion.k1 = 0;
v3d_distortion.k2 = 0;
v3d_distortion.p1 = 0;
v3d_distortion.p2 = 0;
// Convert from libmv's specification for which intrinsics to bundle to V3D's.
int v3d_bundle_intrinsics;
if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) {
LG << "Bundling only camera positions.";
v3d_bundle_intrinsics = V3D::FULL_BUNDLE_METRIC;
} else if (bundle_intrinsics == BUNDLE_FOCAL_LENGTH) {
LG << "Bundling f.";
v3d_bundle_intrinsics = V3D::FULL_BUNDLE_FOCAL_LENGTH;
} else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
BUNDLE_PRINCIPAL_POINT)) {
LG << "Bundling f, px, py.";
v3d_bundle_intrinsics = V3D::FULL_BUNDLE_FOCAL_LENGTH_PP;
} else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
BUNDLE_PRINCIPAL_POINT |
BUNDLE_RADIAL)) {
LG << "Bundling f, px, py, k1, k2.";
v3d_bundle_intrinsics = V3D::FULL_BUNDLE_RADIAL;
} else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
BUNDLE_PRINCIPAL_POINT |
BUNDLE_RADIAL |
BUNDLE_TANGENTIAL)) {
LG << "Bundling f, px, py, k1, k2, p1, p2.";
v3d_bundle_intrinsics = V3D::FULL_BUNDLE_RADIAL_TANGENTIAL;
} else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
BUNDLE_RADIAL |
BUNDLE_TANGENTIAL)) {
LG << "Bundling f, px, py, k1, k2, p1, p2.";
v3d_bundle_intrinsics = V3D::FULL_BUNDLE_RADIAL_TANGENTIAL;
} else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
BUNDLE_RADIAL)) {
LG << "Bundling f, k1, k2.";
v3d_bundle_intrinsics = V3D::FULL_BUNDLE_FOCAL_AND_RADIAL;
} else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
BUNDLE_RADIAL_K1)) {
LG << "Bundling f, k1.";
v3d_bundle_intrinsics = V3D::FULL_BUNDLE_FOCAL_AND_RADIAL_K1;
} else {
LOG(FATAL) << "Unsupported bundle combination.";
}
// Ignore any outliers; assume supervised tracking.
double v3d_inlier_threshold = 500000.0;
// Finally, run the bundle adjustment.
double const inlierThreshold = 500000.0;
V3D::CommonInternalsMetricBundleOptimizer opt(V3D::FULL_BUNDLE_METRIC,
inlierThreshold,
identity3x3,
V3D::CommonInternalsMetricBundleOptimizer opt(v3d_bundle_intrinsics,
v3d_inlier_threshold,
v3d_K,
v3d_distortion,
v3d_cameras,
v3d_points,
v3d_measurements,
v3d_camera_for_measurement,
v3d_point_for_measurement);
opt.maxIterations = 50;
opt.maxIterations = 500;
opt.minimize();
LG << "Bundle status: " << opt.status;
if (opt.status == V3D::LEVENBERG_OPTIMIZER_TIMEOUT) {
LG << "Bundle status: Timed out.";
} else if (opt.status == V3D::LEVENBERG_OPTIMIZER_SMALL_UPDATE) {
LG << "Bundle status: Small update.";
} else if (opt.status == V3D::LEVENBERG_OPTIMIZER_CONVERGED) {
LG << "Bundle status: Converged.";
}
// Convert V3D's K matrix back to libmv's K matrix.
Mat3 K;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
K(i, j) = v3d_K[i][j];
}
}
intrinsics->SetK(K);
// Convert V3D's distortion back to libmv's distortion.
intrinsics->SetRadialDistortion(v3d_distortion.k1, v3d_distortion.k2, 0.0);
intrinsics->SetTangentialDistortion(v3d_distortion.p1, v3d_distortion.p2);
// Convert V3D's cameras back to libmv's cameras.
for (int k = 0; k < num_cameras; k++) {
@ -173,6 +243,7 @@ void EuclideanBundle(const Tracks &tracks,
index_to_point[k]->X(i) = v3d_points[k][i];
}
}
LG << "Final intrinsics: " << *intrinsics;
}
void ProjectiveBundle(const Tracks & /*tracks*/,

@ -23,6 +23,7 @@
namespace libmv {
class CameraIntrinsics;
class EuclideanReconstruction;
class ProjectiveReconstruction;
class Tracks;
@ -47,6 +48,46 @@ class Tracks;
void EuclideanBundle(const Tracks &tracks,
EuclideanReconstruction *reconstruction);
/*!
Refine camera poses and 3D coordinates using bundle adjustment.
This routine adjusts all cameras positions, points, and the camera
intrinsics (assumed common across all images) in \a *reconstruction. This
assumes a full observation for reconstructed tracks; this implies that if
there is a reconstructed 3D point (a bundle) for a track, then all markers
for that track will be included in the minimization. \a tracks should
contain markers used in the initial reconstruction.
The cameras, bundles, and intrinsics are refined in-place.
The only supported combinations of bundle parameters are:
BUNDLE_NO_INTRINSICS
BUNDLE_FOCAL_LENGTH
BUNDLE_FOCAL_LENGTH | BUNDLE_PRINCIPAL_POINT
BUNDLE_FOCAL_LENGTH | BUNDLE_PRINCIPAL_POINT | BUNDLE_RADIAL
BUNDLE_FOCAL_LENGTH | BUNDLE_PRINCIPAL_POINT | BUNDLE_RADIAL | BUNDLE_TANGENTIAL
\note This assumes an outlier-free set of markers.
\sa EuclideanResect, EuclideanIntersect, EuclideanReconstructTwoFrames
*/
enum BundleIntrinsics {
BUNDLE_NO_INTRINSICS = 0,
BUNDLE_FOCAL_LENGTH = 1,
BUNDLE_PRINCIPAL_POINT = 2,
BUNDLE_RADIAL_K1 = 4,
BUNDLE_RADIAL_K2 = 8,
BUNDLE_RADIAL = 12,
BUNDLE_TANGENTIAL_P1 = 16,
BUNDLE_TANGENTIAL_P2 = 32,
BUNDLE_TANGENTIAL = 48,
};
void EuclideanBundleCommonIntrinsics(const Tracks &tracks,
int bundle_intrinsics,
EuclideanReconstruction *reconstruction,
CameraIntrinsics *intrinsics);
/*!
Refine camera poses and 3D coordinates using bundle adjustment.

@ -24,7 +24,7 @@
namespace libmv {
struct Offset {
signed char ix, iy;
short ix, iy;
unsigned char fx,fy;
};
@ -201,20 +201,14 @@ void CameraIntrinsics::ComputeLookupGrid(Grid* grid, int width, int height, doub
warp_y = warp_y*aspy + 0.5 * overscan * h;
int ix = int(warp_x), iy = int(warp_y);
int fx = round((warp_x-ix)*256), fy = round((warp_y-iy)*256);
if(fx == 256) { fx=0; ix++; }
if(fy == 256) { fy=0; iy++; }
// Use nearest border pixel
if( ix < 0 ) { ix = 0, fx = 0; }
if( iy < 0 ) { iy = 0, fy = 0; }
if( ix >= width-2 ) ix = width-2;
if( iy >= height-2 ) iy = height-2;
if ( ix-x > -128 && ix-x < 128 && iy-y > -128 && iy-y < 128 ) {
Offset offset = { ix-x, iy-y, fx, fy };
grid->offset[y*width+x] = offset;
} else {
Offset offset = { 0, 0, 0, 0 };
grid->offset[y*width+x] = offset;
}
Offset offset = { ix-x, iy-y, fx, fy };
grid->offset[y*width+x] = offset;
}
}
}
@ -348,4 +342,26 @@ void CameraIntrinsics::Undistort(const unsigned char* src, unsigned char* dst, i
//else assert("channels must be between 1 and 4");
}
std::ostream& operator <<(std::ostream &os,
const CameraIntrinsics &intrinsics) {
if (intrinsics.focal_length_x() == intrinsics.focal_length_x()) {
os << "f=" << intrinsics.focal_length();
} else {
os << "fx=" << intrinsics.focal_length_x()
<< " fy=" << intrinsics.focal_length_y();
}
os << " cx=" << intrinsics.principal_point_x()
<< " cy=" << intrinsics.principal_point_y()
<< " w=" << intrinsics.image_width()
<< " h=" << intrinsics.image_height();
if (intrinsics.k1() != 0.0) { os << " k1=" << intrinsics.k1(); }
if (intrinsics.k2() != 0.0) { os << " k2=" << intrinsics.k2(); }
if (intrinsics.k3() != 0.0) { os << " k3=" << intrinsics.k3(); }
if (intrinsics.p1() != 0.0) { os << " p1=" << intrinsics.p1(); }
if (intrinsics.p2() != 0.0) { os << " p2=" << intrinsics.p2(); }
return os;
}
} // namespace libmv

@ -21,11 +21,15 @@
#ifndef LIBMV_SIMPLE_PIPELINE_CAMERA_INTRINSICS_H_
#define LIBMV_SIMPLE_PIPELINE_CAMERA_INTRINSICS_H_
#include <iostream>
#include <string>
#include <Eigen/Core>
typedef Eigen::Matrix<double, 3, 3> Mat3;
namespace libmv {
typedef Eigen::Matrix<double, 3, 3> Mat3;
struct Grid;
class CameraIntrinsics {
@ -35,7 +39,6 @@ class CameraIntrinsics {
~CameraIntrinsics();
const Mat3 &K() const { return K_; }
// FIXME(MatthiasF): these should be CamelCase methods
double focal_length() const { return K_(0, 0); }
double focal_length_x() const { return K_(0, 0); }
double focal_length_y() const { return K_(1, 1); }
@ -55,8 +58,10 @@ class CameraIntrinsics {
/// Set both x and y focal length in pixels.
void SetFocalLength(double focal_x, double focal_y);
/// Set principal point in pixels.
void SetPrincipalPoint(double cx, double cy);
/// Set the image size in pixels.
void SetImageSize(int width, int height);
void SetRadialDistortion(double k1, double k2, double k3 = 0);
@ -92,6 +97,7 @@ class CameraIntrinsics {
*/
void Distort(const float* src, float* dst,
int width, int height, double overscan, int channels);
/*!
Distort an image using the current camera instrinsics
@ -102,6 +108,7 @@ class CameraIntrinsics {
*/
void Distort(const unsigned char* src, unsigned char* dst,
int width, int height, double overscan, int channels);
/*!
Undistort an image using the current camera instrinsics
@ -112,6 +119,7 @@ class CameraIntrinsics {
*/
void Undistort(const float* src, float* dst,
int width, int height, double overscan, int channels);
/*!
Undistort an image using the current camera instrinsics
@ -147,6 +155,10 @@ class CameraIntrinsics {
struct Grid *undistort_;
};
/// A human-readable representation of the camera intrinsic parameters.
std::ostream& operator <<(std::ostream &os,
const CameraIntrinsics &intrinsics);
} // namespace libmv
#endif // LIBMV_SIMPLE_PIPELINE_CAMERA_INTRINSICS_H_

@ -67,6 +67,7 @@ void GetImagesInMarkers(const vector<Marker> &markers,
bool EuclideanReconstructTwoFrames(const vector<Marker> &markers,
EuclideanReconstruction *reconstruction) {
if (markers.size() < 16) {
LG << "Not enough markers to initialize from two frames: " << markers.size();
return false;
}
@ -105,6 +106,7 @@ bool EuclideanReconstructTwoFrames(const vector<Marker> &markers,
K, x1.col(0),
K, x2.col(0),
&R, &t)) {
LG << "Failed to compute R and t from E and K.";
return false;
}

@ -262,7 +262,6 @@ double InternalReprojectionError(const Tracks &image_tracks,
ex,
ey,
sqrt(ex*ex + ey*ey));
//LG << line;
total_error += sqrt(ex*ex + ey*ey);
}
LG << "Skipped " << num_skipped << " markers.";

@ -0,0 +1,290 @@
// Copyright (c) 2007, 2008, 2009, 2011 libmv authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#define _USE_MATH_DEFINES
#include "libmv/tracking/esm_region_tracker.h"
#include "libmv/logging/logging.h"
#include "libmv/image/image.h"
#include "libmv/image/convolve.h"
#include "libmv/image/sample.h"
#include "libmv/numeric/numeric.h"
namespace libmv {
// TODO(keir): Reduce duplication between here and the other region trackers.
bool RegionIsInBounds(const FloatImage &image1,
double x, double y,
int half_window_size) {
// Check the minimum coordinates.
int min_x = floor(x) - half_window_size - 1;
int min_y = floor(y) - half_window_size - 1;
if (min_x < 0.0 ||
min_y < 0.0) {
return false;
}
// Check the maximum coordinates.
int max_x = ceil(x) + half_window_size + 1;
int max_y = ceil(y) + half_window_size + 1;
if (max_x > image1.cols() ||
max_y > image1.rows()) {
return false;
}
// Ok, we're good.
return true;
}
// Sample a region centered at x,y in image with size extending by half_width
// from x,y. Channels specifies the number of channels to sample from.
void SamplePattern(const FloatImage &image,
double x, double y,
int half_width,
int channels,
FloatImage *sampled) {
sampled->Resize(2 * half_width + 1, 2 * half_width + 1, channels);
for (int r = -half_width; r <= half_width; ++r) {
for (int c = -half_width; c <= half_width; ++c) {
for (int i = 0; i < channels; ++i) {
(*sampled)(r + half_width, c + half_width, i) =
SampleLinear(image, y + r, x + c, i);
}
}
}
}
// Estimate "reasonable" error by computing autocorrelation for a small shift.
// TODO(keir): Add a facility for
double EstimateReasonableError(const FloatImage &image,
double x, double y,
int half_width) {
double error = 0.0;
for (int r = -half_width; r <= half_width; ++r) {
for (int c = -half_width; c <= half_width; ++c) {
double s = SampleLinear(image, y + r, x + c, 0);
double e1 = SampleLinear(image, y + r + 0.5, x + c, 0) - s;
double e2 = SampleLinear(image, y + r, x + c + 0.5, 0) - s;
error += e1*e1 + e2*e2;
}
}
// XXX hack
return error / 2.0 * 16.0;
}
// This is implemented from "Lukas and Kanade 20 years on: Part 1. Page 42,
// figure 14: the Levenberg-Marquardt-Inverse Compositional Algorithm".
bool EsmRegionTracker::Track(const FloatImage &image1,
const FloatImage &image2,
double x1, double y1,
double *x2, double *y2) const {
if (!RegionIsInBounds(image1, x1, y1, half_window_size)) {
LG << "Fell out of image1's window with x1=" << x1 << ", y1=" << y1
<< ", hw=" << half_window_size << ".";
return false;
}
int width = 2 * half_window_size + 1;
// TODO(keir): Avoid recomputing gradients for e.g. the pyramid tracker.
Array3Df image_and_gradient1;
Array3Df image_and_gradient2;
BlurredImageAndDerivativesChannels(image1, sigma, &image_and_gradient1);
BlurredImageAndDerivativesChannels(image2, sigma, &image_and_gradient2);
// Step -1: Resample the template (image1) since it is not pixel aligned.
//
// Take a sample of the gradient of the pattern area of image1 at the
// subpixel position x1, x2. This is reused for each iteration, so
// precomputing it saves time.
Array3Df image_and_gradient1_sampled;
SamplePattern(image_and_gradient1, x1, y1, half_window_size, 3,
&image_and_gradient1_sampled);
// Step 0: Initialize delta = 0.01.
//
// Ignored for my "normal" LM loop.
double reasonable_error =
EstimateReasonableError(image1, x1, y1, half_window_size);
// Step 1: Warp I with W(x, p) to compute I(W(x; p).
//
// Use two images for accepting / rejecting updates.
// XXX is this necessary?
int current_image = 0, new_image = 1;
Array3Df image_and_gradient2_sampled[2];
SamplePattern(image_and_gradient2, *x2, *y2, half_window_size, 3,
&image_and_gradient2_sampled[current_image]);
// Step 2: Compute the squared error I - J.
double error = 0;
for (int r = 0; r < width; ++r) {
for (int c = 0; c < width; ++c) {
double e = image_and_gradient1_sampled(r, c, 0) -
image_and_gradient2_sampled[current_image](r, c, 0);
error += e*e;
}
}
// Step 3: Evaluate the gradient of the template.
//
// This is done above when sampling the template (step -1).
// Step 4: Evaluate the jacobian dw/dp at (x; 0).
//
// The jacobian between dx,dy and the warp is constant 2x2 identity, so it
// doesn't have to get computed. The Gauss-Newton Hessian matrix computation
// below would normally have to include a multiply by the jacobian.
// Step 5: Compute the steepest descent images of the template.
//
// Since the jacobian of the position w.r.t. the sampled template position is
// the identity, the steepest descent images are the same as the gradient.
// Step 6: Compute the Gauss-Newton Hessian for the template (image1).
//
// This could get rolled into the previous loop, but split it for now for
// clarity.
Mat2 H_image1 = Mat2::Zero();
for (int r = 0; r < width; ++r) {
for (int c = 0; c < width; ++c) {
Vec2 g(image_and_gradient1_sampled(r, c, 1),
image_and_gradient1_sampled(r, c, 2));
H_image1 += g * g.transpose();
}
}
double tau = 1e-4, eps1, eps2, eps3;
eps1 = eps2 = eps3 = 1e-15;
double mu = tau * std::max(H_image1(0, 0), H_image1(1, 1));
double nu = M_E;
int i;
for (i = 0; i < max_iterations; ++i) {
// Check that the entire image patch is within the bounds of the images.
if (!RegionIsInBounds(image2, *x2, *y2, half_window_size)) {
LG << "Fell out of image2's window with x2=" << *x2 << ", y2=" << *y2
<< ", hw=" << half_window_size << ".";
return false;
}
Mat2 H = Mat2::Zero();
for (int r = 0; r < width; ++r) {
for (int c = 0; c < width; ++c) {
Vec2 g1(image_and_gradient1_sampled(r, c, 1),
image_and_gradient1_sampled(r, c, 2));
Vec2 g2(image_and_gradient2_sampled[current_image](r, c, 1),
image_and_gradient2_sampled[current_image](r, c, 2));
Vec2 g = g1 + g2; // Should be / 2.0, but do that outside the loop.
H += g * g.transpose();
}
}
H /= 4.0;
// Step 7: Compute z
Vec2 z = Vec2::Zero();
for (int r = 0; r < width; ++r) {
for (int c = 0; c < width; ++c) {
double e = image_and_gradient2_sampled[current_image](r, c, 0) -
image_and_gradient1_sampled(r, c, 0);
z(0) += image_and_gradient1_sampled(r, c, 1) * e;
z(1) += image_and_gradient1_sampled(r, c, 2) * e;
z(0) += image_and_gradient2_sampled[current_image](r, c, 1) * e;
z(1) += image_and_gradient2_sampled[current_image](r, c, 2) * e;
}
}
z /= 2.0;
// Step 8: Compute Hlm and (dx,dy)
Mat2 diag = H.diagonal().asDiagonal();
diag *= mu;
Mat2 Hlm = H + diag;
Vec2 d = Hlm.lu().solve(z);
// TODO(keir): Use the usual LM termination and update criterion instead of
// this hacky version from the LK 20 years on paper.
LG << "x=" << *x2 << ", y=" << *y2 << ", dx=" << d[0] << ", dy=" << d[1]
<< ", mu=" << mu << ", nu=" << nu;
// Step 9: Update the warp; W(x; p) <-- W(x;p) compose W(x, dp)^-1
double new_x2 = *x2 - d[0];
double new_y2 = *y2 - d[1];
// Step 9.1: Sample the image at the new position.
SamplePattern(image_and_gradient2, new_x2, new_y2, half_window_size, 3,
&image_and_gradient2_sampled[new_image]);
// Step 9.2: Compute the new error.
// TODO(keir): Eliminate duplication with above code.
double new_error = 0;
for (int r = 0; r < width; ++r) {
for (int c = 0; c < width; ++c) {
double e = image_and_gradient1_sampled(r, c, 0) -
image_and_gradient2_sampled[new_image](r, c, 0);
new_error += e*e;
}
}
//LG << "Old error: " << error << ", new error: " << new_error;
double rho = (error - new_error) / (d.transpose() * (mu * d + z));
// Step 10: Accept or reject step.
if (rho <= 0) {
// This was a bad step, so don't update.
mu *= nu;
// The standard Levenberg-Marquardt update multiplies nu by 2, but
// instead chose e. I chose a constant greater than 2 since in typical
// tracking examples, I saw that once updates started failing they should
// ramp towards steepest descent faster. This has no basis in theory, but
// appears to lead to faster tracking overall.
nu *= M_E;
LG << "Error increased, so reject update.";
} else {
// The step was good, so update.
*x2 = new_x2;
*y2 = new_y2;
std::swap(new_image, current_image);
error = new_error;
mu *= std::max(1/3., 1 - pow(2*rho - 1, 3));
nu = M_E; // See above for why to use e.
}
// If the step was accepted, then check for termination.
if (d.squaredNorm() < min_update_squared_distance) {
if (new_error > reasonable_error) {
LG << "Update size shrank but reasonable error ("
<< reasonable_error << ") not achieved; failing.";
return true; // XXX
}
LG << "Successful track in " << (i + 1) << " iterations.";
return true;
}
}
// Getting here means we hit max iterations, so tracking failed.
LG << "Too many iterations; max is set to " << max_iterations << ".";
return false;
}
} // namespace libmv

@ -0,0 +1,61 @@
// Copyright (c) 2007, 2008, 2009, 2011 libmv authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#ifndef LIBMV_REGION_TRACKING_LMICKLT_REGION_TRACKER_H_
#define LIBMV_REGION_TRACKING_LMICKLT_REGION_TRACKER_H_
#include "libmv/image/image.h"
#include "libmv/tracking/region_tracker.h"
namespace libmv {
/*!
A translation-only Efficient Second-order Minimization ("ESM") tracker
Based on the paper "Real-time image-based trackiing of planes using
Efficient Second-order Minimization"
*/
struct EsmRegionTracker : public RegionTracker {
EsmRegionTracker()
: half_window_size(4),
max_iterations(16),
min_determinant(1e-6),
min_update_squared_distance(1e-4),
sigma(0.9) {}
virtual ~EsmRegionTracker() {}
// Tracker interface.
virtual bool Track(const FloatImage &image1,
const FloatImage &image2,
double x1, double y1,
double *x2, double *y2) const;
// No point in creating getters or setters.
int half_window_size;
int max_iterations;
double min_determinant;
double min_update_squared_distance;
double sigma;
};
} // namespace libmv
#endif // LIBMV_REGION_TRACKING_LMICKLT_REGION_TRACKER_H_

@ -63,24 +63,26 @@ static void ComputeTrackingEquation(const Array3Df &image_and_gradient1,
}
}
// Solve the tracking equation
//
// [gxx gxy] [dx] = [ex]
// [gxy gyy] [dy] = [ey]
//
// for dx and dy. Borrowed from Stan Birchfield's KLT implementation.
static bool SolveTrackingEquation(float gxx, float gxy, float gyy,
float ex, float ey,
float min_determinant,
float *dx, float *dy) {
float det = gxx * gyy - gxy * gxy;
if (det < min_determinant) {
*dx = 0;
*dy = 0;
bool RegionIsInBounds(const FloatImage &image1,
double x, double y,
int half_window_size) {
// Check the minimum coordinates.
int min_x = floor(x) - half_window_size - 1;
int min_y = floor(y) - half_window_size - 1;
if (min_x < 0.0 ||
min_y < 0.0) {
return false;
}
*dx = (gyy * ex - gxy * ey) / det;
*dy = (gxx * ey - gxy * ex) / det;
// Check the maximum coordinates.
int max_x = ceil(x) + half_window_size + 1;
int max_y = ceil(y) + half_window_size + 1;
if (max_x > image1.cols() ||
max_y > image1.rows()) {
return false;
}
// Ok, we're good.
return true;
}
@ -88,6 +90,12 @@ bool KltRegionTracker::Track(const FloatImage &image1,
const FloatImage &image2,
double x1, double y1,
double *x2, double *y2) const {
if (!RegionIsInBounds(image1, x1, y1, half_window_size)) {
LG << "Fell out of image1's window with x1=" << x1 << ", y1=" << y1
<< ", hw=" << half_window_size << ".";
return false;
}
Array3Df image_and_gradient1;
Array3Df image_and_gradient2;
BlurredImageAndDerivativesChannels(image1, sigma, &image_and_gradient1);
@ -96,6 +104,13 @@ bool KltRegionTracker::Track(const FloatImage &image1,
int i;
float dx = 0, dy = 0;
for (i = 0; i < max_iterations; ++i) {
// Check that the entire image patch is within the bounds of the images.
if (!RegionIsInBounds(image2, *x2, *y2, half_window_size)) {
LG << "Fell out of image2's window with x2=" << *x2 << ", y2=" << *y2
<< ", hw=" << half_window_size << ".";
return false;
}
// Compute gradient matrix and error vector.
float gxx, gxy, gyy, ex, ey;
ComputeTrackingEquation(image_and_gradient1,
@ -105,19 +120,32 @@ bool KltRegionTracker::Track(const FloatImage &image1,
half_window_size,
&gxx, &gxy, &gyy, &ex, &ey);
// Solve the linear system for the best update to x2 and y2.
if (!SolveTrackingEquation(gxx, gxy, gyy, ex, ey, min_determinant,
&dx, &dy)) {
// The determinant, which indicates the trackiness of the point, is too
// small, so fail out.
LG << "Determinant too small; failing tracking.";
return false;
}
// Solve the tracking equation
//
// [gxx gxy] [dx] = [ex]
// [gxy gyy] [dy] = [ey]
//
// for dx and dy. Borrowed from Stan Birchfield's KLT implementation.
float determinant = gxx * gyy - gxy * gxy;
dx = (gyy * ex - gxy * ey) / determinant;
dy = (gxx * ey - gxy * ex) / determinant;
// Update the position with the solved displacement.
*x2 += dx;
*y2 += dy;
// Check for the quality of the solution, but not until having already
// updated the position with our best estimate. The reason to do the update
// anyway is that the user already knows the position is bad, so we may as
// well try our best.
if (determinant < min_determinant) {
// The determinant, which indicates the trackiness of the point, is too
// small, so fail out.
LG << "Determinant " << determinant << " is too small; failing tracking.";
return false;
}
LG << "x=" << *x2 << ", y=" << *y2 << ", dx=" << dx << ", dy=" << dy << ", det=" << determinant;
// If the update is small, then we probably found the target.
if (dx * dx + dy * dy < min_update_squared_distance) {
LG << "Successful track in " << i << " iterations.";
@ -125,7 +153,7 @@ bool KltRegionTracker::Track(const FloatImage &image1,
}
}
// Getting here means we hit max iterations, so tracking failed.
LG << "Too many iterations.";
LG << "Too many iterations; max is set to " << max_iterations << ".";
return false;
}

@ -0,0 +1,265 @@
// Copyright (c) 2007, 2008, 2009, 2011 libmv authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#include "libmv/tracking/lmicklt_region_tracker.h"
#include "libmv/logging/logging.h"
#include "libmv/image/image.h"
#include "libmv/image/convolve.h"
#include "libmv/image/sample.h"
#include "libmv/numeric/numeric.h"
namespace libmv {
// TODO(keir): Reduce duplication between here and the other region trackers.
bool RegionIsInBounds(const FloatImage &image1,
double x, double y,
int half_window_size) {
// Check the minimum coordinates.
int min_x = floor(x) - half_window_size - 1;
int min_y = floor(y) - half_window_size - 1;
if (min_x < 0.0 ||
min_y < 0.0) {
return false;
}
// Check the maximum coordinates.
int max_x = ceil(x) + half_window_size + 1;
int max_y = ceil(y) + half_window_size + 1;
if (max_x > image1.cols() ||
max_y > image1.rows()) {
return false;
}
// Ok, we're good.
return true;
}
// Sample a region centered at x,y in image with size extending by half_width
// from x,y. Channels specifies the number of channels to sample from.
void SamplePattern(const FloatImage &image,
double x, double y,
int half_width,
int channels,
FloatImage *sampled) {
sampled->Resize(2 * half_width + 1, 2 * half_width + 1, channels);
for (int r = -half_width; r <= half_width; ++r) {
for (int c = -half_width; c <= half_width; ++c) {
for (int i = 0; i < channels; ++i) {
(*sampled)(r + half_width, c + half_width, i) =
SampleLinear(image, y + r, x + c, i);
}
}
}
}
// Estimate "reasonable" error by computing autocorrelation for a small shift.
double EstimateReasonableError(const FloatImage &image,
double x, double y,
int half_width) {
double error = 0.0;
for (int r = -half_width; r <= half_width; ++r) {
for (int c = -half_width; c <= half_width; ++c) {
double s = SampleLinear(image, y + r, x + c, 0);
double e1 = SampleLinear(image, y + r + 0.5, x + c, 0) - s;
double e2 = SampleLinear(image, y + r, x + c + 0.5, 0) - s;
error += e1*e1 + e2*e2;
}
}
return error / 2.0 * 8.0;
}
// This is implemented from "Lukas and Kanade 20 years on: Part 1. Page 42,
// figure 14: the Levenberg-Marquardt-Inverse Compositional Algorithm".
bool LmickltRegionTracker::Track(const FloatImage &image1,
const FloatImage &image2,
double x1, double y1,
double *x2, double *y2) const {
if (!RegionIsInBounds(image1, x1, y1, half_window_size)) {
LG << "Fell out of image1's window with x1=" << x1 << ", y1=" << y1
<< ", hw=" << half_window_size << ".";
return false;
}
int width = 2 * half_window_size + 1;
// TODO(keir): Avoid recomputing gradients for e.g. the pyramid tracker.
Array3Df image_and_gradient1;
Array3Df image_and_gradient2;
BlurredImageAndDerivativesChannels(image1, sigma, &image_and_gradient1);
// TODO(keir): Avoid computing the derivative of image2.
BlurredImageAndDerivativesChannels(image2, sigma, &image_and_gradient2);
// Step -1: Resample the template (image1) since it is not pixel aligned.
//
// Take a sample of the gradient of the pattern area of image1 at the
// subpixel position x1, x2. This is reused for each iteration, so
// precomputing it saves time.
Array3Df image_and_gradient1_sampled;
SamplePattern(image_and_gradient1, x1, y1, half_window_size, 3,
&image_and_gradient1_sampled);
// Step 0: Initialize delta = 0.01.
//
// Ignored for my "normal" LM loop.
double reasonable_error =
EstimateReasonableError(image1, x1, y1, half_window_size);
// Step 1: Warp I with W(x, p) to compute I(W(x; p).
//
// Use two images for accepting / rejecting updates.
int current_image = 0, new_image = 1;
Array3Df image2_sampled[2];
SamplePattern(image_and_gradient2, *x2, *y2, half_window_size, 1,
&image2_sampled[current_image]);
// Step 2: Compute the squared error I - J.
double error = 0;
for (int r = 0; r < width; ++r) {
for (int c = 0; c < width; ++c) {
double e = image_and_gradient1_sampled(r, c, 0) -
image2_sampled[current_image](r, c, 0);
error += e*e;
}
}
// Step 3: Evaluate the gradient of the template.
//
// This is done above when sampling the template (step -1).
// Step 4: Evaluate the jacobian dw/dp at (x; 0).
//
// The jacobian between dx,dy and the warp is constant 2x2 identity, so it
// doesn't have to get computed. The Gauss-Newton Hessian matrix computation
// below would normally have to include a multiply by the jacobian.
// Step 5: Compute the steepest descent images of the template.
//
// Since the jacobian of the position w.r.t. the sampled template position is
// the identity, the steepest descent images are the same as the gradient.
// Step 6: Compute the Gauss-Newton Hessian for the template (image1).
//
// This could get rolled into the previous loop, but split it for now for
// clarity.
Mat2 H = Mat2::Zero();
for (int r = 0; r < width; ++r) {
for (int c = 0; c < width; ++c) {
Vec2 g(image_and_gradient1_sampled(r, c, 1),
image_and_gradient1_sampled(r, c, 2));
H += g * g.transpose();
}
}
double tau = 1e-3, eps1, eps2, eps3;
eps1 = eps2 = eps3 = 1e-15;
double mu = tau * std::max(H(0, 0), H(1, 1));
double nu = 2.0;
int i;
for (i = 0; i < max_iterations; ++i) {
// Check that the entire image patch is within the bounds of the images.
if (!RegionIsInBounds(image2, *x2, *y2, half_window_size)) {
LG << "Fell out of image2's window with x2=" << *x2 << ", y2=" << *y2
<< ", hw=" << half_window_size << ".";
return false;
}
// Step 7: Compute z
Vec2 z = Vec2::Zero();
for (int r = 0; r < width; ++r) {
for (int c = 0; c < width; ++c) {
double e = image2_sampled[current_image](r, c, 0) -
image_and_gradient1_sampled(r, c, 0);
z(0) += image_and_gradient1_sampled(r, c, 1) * e;
z(1) += image_and_gradient1_sampled(r, c, 2) * e;
}
}
// Step 8: Compute Hlm and (dx,dy)
Mat2 diag = H.diagonal().asDiagonal();
diag *= mu;
Mat2 Hlm = H + diag;
Vec2 d = Hlm.lu().solve(z);
// TODO(keir): Use the usual LM termination and update criterion instead of
// this hacky version from the LK 20 years on paper.
LG << "x=" << *x2 << ", y=" << *y2 << ", dx=" << d[0] << ", dy=" << d[1]
<< ", mu=" << mu << ", nu=" << nu;
// Step 9: Update the warp; W(x; p) <-- W(x;p) compose W(x, dp)^-1
double new_x2 = *x2 - d[0];
double new_y2 = *y2 - d[1];
// Step 9.1: Sample the image at the new position.
SamplePattern(image_and_gradient2, new_x2, new_y2, half_window_size, 1,
&image2_sampled[new_image]);
// Step 9.2: Compute the new error.
// TODO(keir): Eliminate duplication with above code.
double new_error = 0;
for (int r = 0; r < width; ++r) {
for (int c = 0; c < width; ++c) {
double e = image_and_gradient1_sampled(r, c, 0) -
image2_sampled[new_image](r, c, 0);
new_error += e*e;
}
}
LG << "Old error: " << error << ", new error: " << new_error;
// If the step was accepted, then check for termination.
if (d.squaredNorm() < min_update_squared_distance) {
if (new_error > reasonable_error) {
LG << "Update size shrank but reasonable error ("
<< reasonable_error << ") not achieved; failing.";
return false;
}
LG << "Successful track in " << i << " iterations.";
return true;
}
double rho = (error - new_error) / (d.transpose() * (mu * d + z));
// Step 10: Accept or reject step.
if (rho <= 0) {
// This was a bad step, so don't update.
mu *= nu;
nu *= 2;
LG << "Error increased, so reject update.";
} else {
// The step was good, so update.
*x2 = new_x2;
*y2 = new_y2;
std::swap(new_image, current_image);
error = new_error;
mu *= std::max(1/3., 1 - pow(2*rho - 1, 3));
nu = 2;
}
}
// Getting here means we hit max iterations, so tracking failed.
LG << "Too many iterations; max is set to " << max_iterations << ".";
return false;
}
} // namespace libmv

@ -0,0 +1,62 @@
// Copyright (c) 2007, 2008, 2009, 2011 libmv authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
#ifndef LIBMV_REGION_TRACKING_LMICKLT_REGION_TRACKER_H_
#define LIBMV_REGION_TRACKING_LMICKLT_REGION_TRACKER_H_
#include "libmv/image/image.h"
#include "libmv/tracking/region_tracker.h"
namespace libmv {
/*!
Levenberg-Marquardt inverse compositional region tracking
This tracker implements the Levenberg-Marquardt inverse compositional
region tracking algorithm as described in the paper "Lucas and Kanade 20
years on: A unifying framework."
*/
struct LmickltRegionTracker : public RegionTracker {
LmickltRegionTracker()
: half_window_size(4),
max_iterations(16),
min_determinant(1e-6),
min_update_squared_distance(1e-6),
sigma(0.9) {}
virtual ~LmickltRegionTracker() {}
// Tracker interface.
virtual bool Track(const FloatImage &image1,
const FloatImage &image2,
double x1, double y1,
double *x2, double *y2) const;
// No point in creating getters or setters.
int half_window_size;
int max_iterations;
double min_determinant;
double min_update_squared_distance;
double sigma;
};
} // namespace libmv
#endif // LIBMV_REGION_TRACKING_LMICKLT_REGION_TRACKER_H_

@ -63,15 +63,32 @@ bool PyramidRegionTracker::Track(const FloatImage &image1,
*x2 *= 2;
*y2 *= 2;
// Track the point on this level with the base tracker.
bool succeeded = tracker_->Track(pyramid1[i], pyramid2[i], xx, yy, x2, y2);
// Save the previous best guess for this level, since tracking within this
// level might fail.
double x2_new = *x2;
double y2_new = *y2;
if (i == 0 && !succeeded) {
// Only fail on the highest-resolution level, because a failure on a
// coarse level does not mean failure at a lower level (consider
// out-of-bounds conditions).
LG << "Finest level of pyramid tracking failed; failing.";
return false;
// Track the point on this level with the base tracker.
LG << "Tracking on level " << i;
bool succeeded = tracker_->Track(pyramid1[i], pyramid2[i], xx, yy,
&x2_new, &y2_new);
if (!succeeded) {
if (i == 0) {
// Only fail on the highest-resolution level, because a failure on a
// coarse level does not mean failure at a lower level (consider
// out-of-bounds conditions).
LG << "Finest level of pyramid tracking failed; failing.";
return false;
}
LG << "Failed to track at level " << i << "; restoring guess.";
} else {
// Only save the update if the track for this level succeeded. This is a
// bit of a hack; the jury remains out on whether this is better than
// re-using the previous failed-attempt.
*x2 = x2_new;
*y2 = y2_new;
}
}
return true;

@ -28,6 +28,8 @@
namespace libmv {
// TODO(keir): Switch this to use the smarter LM loop like in ESM.
// Computes U and e from the Ud = e equation (number 14) from the paper.
static void ComputeTrackingEquation(const Array3Df &image_and_gradient1,
const Array3Df &image_and_gradient2,
@ -79,10 +81,39 @@ static void ComputeTrackingEquation(const Array3Df &image_and_gradient1,
*e = (A + lambda*Mat2f::Identity())*Di*(V - W) + 0.5*(S - R);
}
bool RegionIsInBounds(const FloatImage &image1,
double x, double y,
int half_window_size) {
// Check the minimum coordinates.
int min_x = floor(x) - half_window_size - 1;
int min_y = floor(y) - half_window_size - 1;
if (min_x < 0.0 ||
min_y < 0.0) {
return false;
}
// Check the maximum coordinates.
int max_x = ceil(x) + half_window_size + 1;
int max_y = ceil(y) + half_window_size + 1;
if (max_x > image1.cols() ||
max_y > image1.rows()) {
return false;
}
// Ok, we're good.
return true;
}
bool TrkltRegionTracker::Track(const FloatImage &image1,
const FloatImage &image2,
double x1, double y1,
double *x2, double *y2) const {
if (!RegionIsInBounds(image1, x1, y1, half_window_size)) {
LG << "Fell out of image1's window with x1=" << x1 << ", y1=" << y1
<< ", hw=" << half_window_size << ".";
return false;
}
Array3Df image_and_gradient1;
Array3Df image_and_gradient2;
BlurredImageAndDerivativesChannels(image1, sigma, &image_and_gradient1);
@ -91,6 +122,13 @@ bool TrkltRegionTracker::Track(const FloatImage &image1,
int i;
Vec2f d = Vec2f::Zero();
for (i = 0; i < max_iterations; ++i) {
// Check that the entire image patch is within the bounds of the images.
if (!RegionIsInBounds(image2, *x2, *y2, half_window_size)) {
LG << "Fell out of image2's window with x2=" << *x2 << ", y2=" << *y2
<< ", hw=" << half_window_size << ".";
return false;
}
// Compute gradient matrix and error vector.
Mat2f U;
Vec2f e;
@ -120,6 +158,8 @@ bool TrkltRegionTracker::Track(const FloatImage &image1,
LG << "Determinant " << determinant << " is too small; failing tracking.";
return false;
}
LG << "x=" << *x2 << ", y=" << *y2 << ", dx=" << d[0] << ", dy=" << d[1] << ", det=" << determinant;
// If the update is small, then we probably found the target.
if (d.squaredNorm() < min_update_squared_distance) {

@ -131,7 +131,7 @@
#define PACKAGE_VERSION "0.3.1"
/* How to access the PC from a struct ucontext */
#if defined(_M_X64) || defined(__amd64__)
#if defined(_M_X64) || defined(__amd64__) || defined(__x86_64__)
#define PC_FROM_UCONTEXT uc_mcontext.gregs[REG_RIP]
#else
#define PC_FROM_UCONTEXT uc_mcontext.gregs[REG_EIP]

@ -158,6 +158,31 @@ namespace V3D
switch (_mode)
{
case FULL_BUNDLE_FOCAL_AND_RADIAL_K1:
{
// Focal length.
Ck[0][0] = xd[0];
Ck[1][0] = xd[1];
// For radial, k1 only.
Matrix2x2d dxd_dk1k2 = _distortion.derivativeWrtRadialParameters(xu);
Matrix2x2d d_dk1k2 = dp_dxd * dxd_dk1k2;
Ck[0][1] = d_dk1k2[0][0];
Ck[1][1] = d_dk1k2[1][0];
break;
}
case FULL_BUNDLE_FOCAL_AND_RADIAL:
{
// Focal length.
Ck[0][0] = xd[0];
Ck[1][0] = xd[1];
// Radial k1 and k2.
Matrix2x2d dxd_dk1k2 = _distortion.derivativeWrtRadialParameters(xu);
Matrix2x2d d_dk1k2 = dp_dxd * dxd_dk1k2;
copyMatrixSlice(d_dk1k2, 0, 0, 2, 2, Ck, 0, 1);
break;
}
case FULL_BUNDLE_RADIAL_TANGENTIAL:
{
Matrix2x2d dxd_dp1p2 = _distortion.derivativeWrtTangentialParameters(xu);
@ -194,6 +219,21 @@ namespace V3D
{
switch (_mode)
{
case FULL_BUNDLE_FOCAL_AND_RADIAL_K1:
{
_K[0][0] += deltaC[0];
_K[1][1] = _cachedAspectRatio * _K[0][0];
_distortion.k1 += deltaC[1];
break;
}
case FULL_BUNDLE_FOCAL_AND_RADIAL:
{
_K[0][0] += deltaC[0];
_K[1][1] = _cachedAspectRatio * _K[0][0];
_distortion.k1 += deltaC[1];
_distortion.k2 += deltaC[2];
break;
}
case FULL_BUNDLE_RADIAL_TANGENTIAL:
{
_distortion.p1 += deltaC[5];

@ -166,7 +166,9 @@ namespace V3D
FULL_BUNDLE_FOCAL_LENGTH = 1, // f
FULL_BUNDLE_FOCAL_LENGTH_PP = 2, // f, cx, cy
FULL_BUNDLE_RADIAL = 3, // f, cx, cy, k1, k2
FULL_BUNDLE_RADIAL_TANGENTIAL = 4 // f, cx, cy, k1, k2, p1, p2
FULL_BUNDLE_RADIAL_TANGENTIAL = 4, // f, cx, cy, k1, k2, p1, p2
FULL_BUNDLE_FOCAL_AND_RADIAL_K1 = 5, // f, k1
FULL_BUNDLE_FOCAL_AND_RADIAL = 6, // f, k1, k2
};
struct CommonInternalsMetricBundleOptimizer : public MetricBundleOptimizerBase
@ -175,11 +177,13 @@ namespace V3D
{
switch (mode)
{
case FULL_BUNDLE_METRIC: return 0;
case FULL_BUNDLE_FOCAL_LENGTH: return 1;
case FULL_BUNDLE_FOCAL_LENGTH_PP: return 3;
case FULL_BUNDLE_RADIAL: return 5;
case FULL_BUNDLE_RADIAL_TANGENTIAL: return 7;
case FULL_BUNDLE_METRIC: return 0;
case FULL_BUNDLE_FOCAL_LENGTH: return 1;
case FULL_BUNDLE_FOCAL_LENGTH_PP: return 3;
case FULL_BUNDLE_RADIAL: return 5;
case FULL_BUNDLE_RADIAL_TANGENTIAL: return 7;
case FULL_BUNDLE_FOCAL_AND_RADIAL_K1: return 2;
case FULL_BUNDLE_FOCAL_AND_RADIAL: return 3;
}
return 0;
}
@ -266,11 +270,13 @@ namespace V3D
{
switch (mode)
{
case FULL_BUNDLE_METRIC: return 0;
case FULL_BUNDLE_FOCAL_LENGTH: return 1;
case FULL_BUNDLE_FOCAL_LENGTH_PP: return 3;
case FULL_BUNDLE_RADIAL: return 5;
case FULL_BUNDLE_RADIAL_TANGENTIAL: return 7;
case FULL_BUNDLE_METRIC: return 0;
case FULL_BUNDLE_FOCAL_LENGTH: return 1;
case FULL_BUNDLE_FOCAL_LENGTH_PP: return 3;
case FULL_BUNDLE_RADIAL: return 5;
case FULL_BUNDLE_RADIAL_TANGENTIAL: return 7;
case FULL_BUNDLE_FOCAL_AND_RADIAL_K1: return 2;
case FULL_BUNDLE_FOCAL_AND_RADIAL: return 3;
}
return 0;
}

0
extern/libmv/third_party/ssba/README.libmv vendored Executable file → Normal file

@ -155,6 +155,9 @@ void AUD_LinearResampleReader::read(int& length, bool& eos, sample_t* buffer)
m_cache_ok = true;
}
if(length == 0)
return;
for(int channel = 0; channel < m_channels; channel++)
{
for(int i = 0; i < length; i++)

@ -9,31 +9,18 @@ include(cmake/external_libs.cmake)
# Build Flags
if(WITH_RAYOPTIMIZATION AND SUPPORT_SSE_BUILD)
set(GCC_OPTIM_FLAGS "-ffast-math -msse -msse2 -msse3")
endif()
set(WITH_CYCLES_OPTIMIZED_KERNEL ON)
if(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_OPTIM_FLAGS}")
set(RTTI_DISABLE_FLAGS "-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID")
endif()
if(WIN32)
if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Ox /Ot /arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /EHsc /fp:fast")
set(RTTI_DISABLE_FLAGS "/GR- -DBOOST_NO_RTTI -DBOOST_NO_TYPEID")
if(WIN32 AND MSVC)
set(CYCLES_OPTIMIZED_KERNEL_FLAGS "/Ox /Ot /arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /EHsc /fp:fast")
elseif(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_OPTIM_FLAGS}")
set(RTTI_DISABLE_FLAGS "-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID")
set(CYCLES_OPTIMIZED_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -DGOGOGO")
endif()
endif()
if(UNIX AND NOT APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_OPTIM_FLAGS}")
set(RTTI_DISABLE_FLAGS "-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID")
endif()
# not needed yet, is for open shading language
set(RTTI_DISABLE_FLAGS "")
# for OSL, not needed yet
# set(RTTI_DISABLE_FLAGS "-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID")
# set(RTTI_DISABLE_FLAGS "/GR- -DBOOST_NO_RTTI -DBOOST_NO_TYPEID")
# Definitions and Includes
@ -42,6 +29,10 @@ add_definitions(${BOOST_DEFINITIONS} ${OPENIMAGEIO_DEFINITIONS})
add_definitions(-DCCL_NAMESPACE_BEGIN=namespace\ ccl\ {)
add_definitions(-DCCL_NAMESPACE_END=})
if(WITH_CYCLES_OPTIMIZED_KERNEL)
add_definitions(-DWITH_OPTIMIZED_KERNEL)
endif()
if(WITH_CYCLES_NETWORK)
add_definitions(-DWITH_NETWORK)
endif()
@ -70,6 +61,7 @@ include_directories(
# Subdirectories
if(WITH_CYCLES_BLENDER)
add_definitions(-DBLENDER_PLUGIN)
add_subdirectory(blender)
endif(WITH_CYCLES_BLENDER)

@ -6,15 +6,14 @@ cycles = env.Clone()
cycles.Depends('../../source/blender/makesrna/intern/RNA_blender_cpp.h', 'makesrna')
sources = cycles.Glob('bvh/*.cpp') + cycles.Glob('device/*.cpp') + cycles.Glob('kernel/*.cpp') + cycles.Glob('render/*.cpp') + cycles.Glob('subd/*.cpp') + cycles.Glob('util/*.cpp') + cycles.Glob('util/*.c') + cycles.Glob('blender/*.cpp')
sources = cycles.Glob('bvh/*.cpp') + cycles.Glob('device/*.cpp') + cycles.Glob('kernel/*.cpp') + cycles.Glob('render/*.cpp') + cycles.Glob('subd/*.cpp') + cycles.Glob('util/*.cpp') + cycles.Glob('blender/*.cpp')
sources.remove(path.join('util', 'util_view.cpp'))
sources.remove(path.join('render', 'film_response.cpp'))
sources.remove(path.join('kernel', 'kernel_optimized.cpp'))
incs = []
defs = []
ccflags = []
cxxflags = []
defs.append('CCL_NAMESPACE_BEGIN=namespace ccl {')
defs.append('CCL_NAMESPACE_END=}')
@ -23,14 +22,6 @@ defs.append('WITH_OPENCL')
defs.append('WITH_MULTI')
defs.append('WITH_CUDA')
if env['OURPLATFORM'] in ('win32-mingw'):
if env['WITH_BF_RAYOPTIMIZATION']:
cxxflags.append('-ffast-math -msse -msse2 -msse3'.split())
ccflags.append('-ffast-math -msse -msse2 -msse3'.split())
# not needed yet, is for open shading language
# cxxflags.append('-fno-rtti'.split())
# defs.append('BOOST_NO_RTTI BOOST_NO_TYPEID'.split())
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())
@ -39,5 +30,20 @@ incs.append(cycles['BF_OIIO_INC'])
incs.append(cycles['BF_BOOST_INC'])
incs.append(cycles['BF_PYTHON_INC'])
cycles.BlenderLib('bf_intern_cycles', sources, incs, defs, libtype=['intern'], priority=[0], compileflags=[None], cc_compileflags=ccflags, cxx_compileflags=cxxflags)
# optimized kernel
if env['WITH_BF_RAYOPTIMIZATION']:
optim_cxxflags = []
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
optim_cxxflags.append('/Ox /Ot /arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /EHsc /fp:fast'.split())
else:
optim_cxxflags.append('-ffast-math -msse -msse2 -msse3'.split())
optim_defs = defs + ['WITH_OPTIMIZED_KERNEL']
optim_sources = [path.join('kernel', 'kernel_optimized.cpp')]
cycles_optim = cycles.Clone()
cycles_optim.BlenderLib('bf_intern_cycles_optimized', optim_sources, incs, optim_defs, libtype=['intern'], priority=[0], compileflags=[None], cxx_compileflags=optim_cxxflags)
cycles.BlenderLib('bf_intern_cycles', sources, incs, defs, libtype=['intern'], priority=[0], compileflags=[None])

@ -6,15 +6,18 @@ set(INC
../kernel/svm
../util
../subd
../../../intern/guardedalloc
../../../source/blender/makesdna
../../../source/blender/makesrna
../../../source/blender/blenloader
${CMAKE_BINARY_DIR}/source/blender/makesrna/intern
)
set(INC_SYS
${BLENDER_INCLUDE_DIRS}
${PYTHON_INCLUDE_DIRS}
${GLEW_INCLUDE_PATH}
)
set(SRC
blender_camera.cpp
blender_mesh.cpp

@ -16,17 +16,20 @@
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# <pep8 compliant>
bl_info = {
"name": "Cycles Render Engine",
"author": "",
"version": (0,0),
"blender": (2, 5, 6),
"api": 34462,
"version": (0, 0),
"blender": (2, 6, 0),
"api": 41670,
"location": "Info header, render engine menu",
"description": "Cycles Render Engine integration.",
"warning": "",
"wiki_url": "",
"wiki_url": "http://wiki.blender.org/index.php/Dev:2.6/Source/Render/Cycles",
"tracker_url": "",
"support": 'OFFICIAL',
"category": "Render"}
import bpy
@ -37,6 +40,7 @@ from cycles import xml
from cycles import engine
from cycles import presets
class CyclesRender(bpy.types.RenderEngine):
bl_idname = 'CYCLES'
bl_label = "Cycles"
@ -45,7 +49,7 @@ class CyclesRender(bpy.types.RenderEngine):
def __init__(self):
engine.init()
self.session = None
def __del__(self):
engine.free(self)
@ -63,7 +67,7 @@ class CyclesRender(bpy.types.RenderEngine):
#
# def preview_render(self):
# pass
# viewport render
def view_update(self, context):
if not self.session:
@ -74,6 +78,7 @@ class CyclesRender(bpy.types.RenderEngine):
def view_draw(self, context):
engine.draw(self, context.region, context.space_data, context.region_data)
def register():
properties.register()
ui.register()
@ -81,10 +86,10 @@ def register():
presets.register()
bpy.utils.register_module(__name__)
def unregister():
xml.unregister()
ui.unregister()
properties.unregister()
presets.unregister()
bpy.utils.unregister_module(__name__)

@ -16,8 +16,11 @@
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# <pep8 compliant>
import bpy
def init():
import bcycles
import os.path
@ -27,7 +30,8 @@ def init():
bcycles.init(path, user_path)
def create(engine, data, scene, region = 0, v3d = 0, rv3d = 0):
def create(engine, data, scene, region=0, v3d=0, rv3d=0):
import bcycles
data = data.as_pointer()
@ -41,20 +45,29 @@ def create(engine, data, scene, region = 0, v3d = 0, rv3d = 0):
engine.session = bcycles.create(engine.as_pointer(), data, scene, region, v3d, rv3d)
def free(engine):
if "session" in dir(engine):
if hasattr(engine, "session"):
if engine.session:
import bcycles
bcycles.free(engine.session)
del engine.session
def render(engine):
import bcycles
bcycles.render(engine.session)
if "session" in dir(engine):
bcycles.render(engine.session)
def update(engine, data, scene):
import bcycles
bcycles.sync(engine.session)
if scene.render.use_border:
engine.report({'ERROR'}, "Border rendering not supported yet")
free(engine)
else:
bcycles.sync(engine.session)
def draw(engine, region, v3d, rv3d):
import bcycles
@ -64,11 +77,12 @@ def draw(engine, region, v3d, rv3d):
# draw render image
bcycles.draw(engine.session, v3d, rv3d)
def available_devices():
import bcycles
return bcycles.available_devices()
def with_osl():
import bcycles
return bcycles.with_osl()

@ -16,8 +16,11 @@
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# <pep8 compliant>
from cycles import engine
def get_gpu_device():
available_devices = engine.available_devices()
cuda = 'cuda' in available_devices
@ -28,32 +31,36 @@ def get_gpu_device():
gpu_string = "CUDA GPU"
else:
gpu_string = "OpenCL GPU"
return gpu_string
devices = (
("CPU", "CPU", "Processor"),
("GPU", get_gpu_device(), "Graphics card"))
("CPU", "CPU", "Processor"),
("GPU", get_gpu_device(), "Graphics card"),
)
gpu_type = (
("CUDA", "CUDA", "NVidia only"),
("OPENCL", "OpenCL (incomplete)", ""))
("CUDA", "CUDA", "NVidia only"),
("OPENCL", "OpenCL (incomplete)", ""),
)
shading_systems = (
("GPU_COMPATIBLE", "GPU Compatible", "Restricted shading system compatible with GPU rendering"),
("OSL", "Open Shading Language", "Open Shading Language shading system that only runs on the CPU"))
("GPU_COMPATIBLE", "GPU Compatible", "Restricted shading system compatible with GPU rendering"),
("OSL", "Open Shading Language", "Open Shading Language shading system that only runs on the CPU"),
)
displacement_methods = (
("BUMP", "Bump", "Bump mapping to simulate the appearance of displacement"),
("TRUE", "True", "Use true displacement only, requires fine subdivision"),
("BOTH", "Both", "Combination of displacement and bump mapping"))
("BUMP", "Bump", "Bump mapping to simulate the appearance of displacement"),
("TRUE", "True", "Use true displacement only, requires fine subdivision"),
("BOTH", "Both", "Combination of displacement and bump mapping"),
)
bvh_types = (
("DYNAMIC_BVH", "Dynamic BVH", "Objects can be individually updated, at the cost of slower render time"),
("STATIC_BVH", "Static BVH", "Any object modification requires a complete BVH rebuild, but renders faster"))
("DYNAMIC_BVH", "Dynamic BVH", "Objects can be individually updated, at the cost of slower render time"),
("STATIC_BVH", "Static BVH", "Any object modification requires a complete BVH rebuild, but renders faster"),
)
filter_types = (
("BOX", "Box", "Box filter"),
("GAUSSIAN", "Gaussian", "Gaussian filter"))
("BOX", "Box", "Box filter"),
("GAUSSIAN", "Gaussian", "Gaussian filter"),
)

@ -16,9 +16,12 @@
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# <pep8 compliant>
from bl_operators.presets import AddPresetBase
from bpy.types import Operator
class AddPresetIntegrator(AddPresetBase, Operator):
'''Add an Integrator Preset'''
bl_idname = "render.cycles_integrator_preset_add"
@ -41,13 +44,14 @@ class AddPresetIntegrator(AddPresetBase, Operator):
]
preset_subdir = "cycles/integrator"
def register():
pass
def unregister():
pass
if __name__ == "__main__":
register()

@ -16,6 +16,8 @@
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# <pep8 compliant>
import bpy
from bpy.props import *
@ -23,6 +25,7 @@ import math
from cycles import enums
class CyclesRenderSettings(bpy.types.PropertyGroup):
@classmethod
def register(cls):
@ -30,7 +33,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
cls.device = EnumProperty(name="Device", description="Device to use for rendering",
items=enums.devices, default="CPU")
cls.gpu_type = EnumProperty(name="GPU Type", description="Processing system to use on the GPU",
items=enums.gpu_type, default="CUDA")
@ -101,6 +104,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
def unregister(cls):
del bpy.types.Scene.cycles
class CyclesCameraSettings(bpy.types.PropertyGroup):
@classmethod
def register(cls):
@ -108,26 +112,28 @@ class CyclesCameraSettings(bpy.types.PropertyGroup):
cls.aperture_size = FloatProperty(name="Aperture Size", description="Radius of the aperture for depth of field",
default=0.0, min=0.0, max=10.0)
cls.aperture_blades = IntProperty(name="Aperture Blades", description="Number of blades in aperture for polygonal bokeh (need 3 or more)",
cls.aperture_blades = IntProperty(name="Aperture Blades", description="Number of blades in aperture for polygonal bokeh (at least 3)",
default=0, min=0, max=100)
cls.aperture_rotation = FloatProperty(name="Aperture Rotation", description="Rotation of blades in aperture",
default=0, soft_min=-math.pi, soft_max=math.pi, subtype='ANGLE')
@classmethod
def unregister(cls):
del bpy.types.Camera.cycles
class CyclesMaterialSettings(bpy.types.PropertyGroup):
@classmethod
def register(cls):
bpy.types.Material.cycles = PointerProperty(type=cls, name="Cycles Material Settings", description="Cycles material settings")
cls.sample_as_light = BoolProperty(name="Sample as Light", description="Use direct light sampling, to reduce noise for small or strong emitting materials", default=True)
cls.sample_as_light = BoolProperty(name="Sample as Lamp", description="Use direct light sampling for this material, disabling may reduce overall noise for large objects that emit little light compared to other light sources", default=True)
cls.homogeneous_volume = BoolProperty(name="Homogeneous Volume", description="When using volume rendering, assume volume has the same density everywhere, for faster rendering", default=False)
@classmethod
def unregister(cls):
del bpy.types.Material.cycles
class CyclesLampSettings(bpy.types.PropertyGroup):
@classmethod
def register(cls):
@ -138,6 +144,7 @@ class CyclesLampSettings(bpy.types.PropertyGroup):
def unregister(cls):
del bpy.types.Lamp.cycles
class CyclesWorldSettings(bpy.types.PropertyGroup):
@classmethod
def register(cls):
@ -147,6 +154,7 @@ class CyclesWorldSettings(bpy.types.PropertyGroup):
def unregister(cls):
del bpy.types.World.cycles
class CyclesVisibilitySettings(bpy.types.PropertyGroup):
@classmethod
def register(cls):
@ -162,6 +170,7 @@ class CyclesVisibilitySettings(bpy.types.PropertyGroup):
def unregister(cls):
del bpy.types.Object.cycles_visibility
class CyclesMeshSettings(bpy.types.PropertyGroup):
@classmethod
def register(cls):
@ -181,6 +190,7 @@ class CyclesMeshSettings(bpy.types.PropertyGroup):
del bpy.types.Curve.cycles
del bpy.types.MetaBall.cycles
def register():
bpy.utils.register_class(CyclesRenderSettings)
bpy.utils.register_class(CyclesCameraSettings)
@ -189,7 +199,8 @@ def register():
bpy.utils.register_class(CyclesWorldSettings)
bpy.utils.register_class(CyclesVisibilitySettings)
bpy.utils.register_class(CyclesMeshSettings)
def unregister():
bpy.utils.unregister_class(CyclesRenderSettings)
bpy.utils.unregister_class(CyclesCameraSettings)
@ -198,4 +209,3 @@ def unregister():
bpy.utils.unregister_class(CyclesWorldSettings)
bpy.utils.unregister_class(CyclesMeshSettings)
bpy.utils.unregister_class(CyclesVisibilitySettings)

@ -16,6 +16,8 @@
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# <pep8 compliant>
import bpy
from bpy.types import Panel, Menu
@ -23,6 +25,7 @@ from bpy.types import Panel, Menu
from cycles import enums
from cycles import engine
class CYCLES_MT_integrator_presets(Menu):
bl_label = "Integrator Presets"
preset_subdir = "cycles/integrator"
@ -30,16 +33,18 @@ class CYCLES_MT_integrator_presets(Menu):
COMPAT_ENGINES = {'CYCLES'}
draw = Menu.draw_preset
class CyclesButtonsPanel():
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
@classmethod
def poll(cls, context):
rd = context.scene.render
return rd.engine == 'CYCLES'
class CyclesRender_PT_integrator(CyclesButtonsPanel, Panel):
bl_label = "Integrator"
bl_options = {'DEFAULT_CLOSED'}
@ -49,7 +54,7 @@ class CyclesRender_PT_integrator(CyclesButtonsPanel, Panel):
scene = context.scene
cscene = scene.cycles
row = layout.row(align=True)
row.menu("CYCLES_MT_integrator_presets", text=bpy.types.CYCLES_MT_integrator_presets.bl_label)
row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMIN")
@ -87,7 +92,8 @@ class CyclesRender_PT_integrator(CyclesButtonsPanel, Panel):
#row = col.row()
#row.prop(cscene, "blur_caustics")
#row.active = not cscene.no_caustics
class CyclesRender_PT_film(CyclesButtonsPanel, Panel):
bl_label = "Film"
@ -99,7 +105,7 @@ class CyclesRender_PT_film(CyclesButtonsPanel, Panel):
split = layout.split()
col = split.column();
col = split.column()
col.prop(cscene, "film_exposure")
col.prop(cscene, "film_transparent")
@ -109,6 +115,7 @@ class CyclesRender_PT_film(CyclesButtonsPanel, Panel):
if cscene.filter_type != 'BOX':
sub.prop(cscene, "filter_width", text="Width")
class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
bl_label = "Performance"
bl_options = {'DEFAULT_CLOSED'}
@ -142,6 +149,7 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
sub.prop(cscene, "debug_bvh_type", text="")
sub.prop(cscene, "debug_use_spatial_splits")
class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
bl_label = "Layers"
bl_options = {'DEFAULT_CLOSED'}
@ -178,6 +186,7 @@ class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
layout.prop(rl, "material_override", text="Material")
class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
bl_label = "Post Processing"
bl_options = {'DEFAULT_CLOSED'}
@ -196,6 +205,7 @@ class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
col = split.column()
col.prop(rd, "dither_intensity", text="Dither", slider=True)
class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel):
bl_label = "Depth of Field"
bl_context = "data"
@ -229,6 +239,7 @@ class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel):
sub.prop(ccam, "aperture_blades", text="Blades")
sub.prop(ccam, "aperture_rotation", text="Rotation")
class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
bl_label = "Surface"
bl_context = "material"
@ -277,13 +288,14 @@ class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
split.template_ID(space, "pin_id")
split.separator()
class Cycles_PT_mesh_displacement(CyclesButtonsPanel, Panel):
bl_label = "Displacement"
bl_context = "data"
@classmethod
def poll(cls, context):
return context.mesh or context.curve or context.meta_ball
return CyclesButtonsPanel.poll(context) and (context.mesh or context.curve or context.meta_ball)
def draw(self, context):
layout = self.layout
@ -300,8 +312,9 @@ class Cycles_PT_mesh_displacement(CyclesButtonsPanel, Panel):
cdata = mball.cycles
layout.prop(cdata, "displacement_method", text="Method")
layout.prop(cdata, "use_subdivision");
layout.prop(cdata, "dicing_rate");
layout.prop(cdata, "use_subdivision")
layout.prop(cdata, "dicing_rate")
class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
bl_label = "Ray Visibility"
@ -311,7 +324,7 @@ class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
ob = context.object
return CyclesButtonsPanel.poll(context) and ob and ob.type in ('MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META') # todo: 'LAMP'
return CyclesButtonsPanel.poll(context) and ob and ob.type in ('MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META') # todo: 'LAMP'
def draw(self, context):
layout = self.layout
@ -330,6 +343,7 @@ class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
col.prop(visibility, "transmission")
col.prop(visibility, "shadow")
def find_node(material, nodetype):
if material and material.node_tree:
ntree = material.node_tree
@ -337,16 +351,18 @@ def find_node(material, nodetype):
for node in ntree.nodes:
if hasattr(node, 'type') and node.type == nodetype:
return node
return None
def find_node_input(node, name):
for input in node.inputs:
if input.name == name:
return input
return None
def panel_node_draw(layout, id, output_type, input_name):
if not id.node_tree:
layout.prop(id, "use_nodes", icon='NODETREE')
@ -359,10 +375,11 @@ def panel_node_draw(layout, id, output_type, input_name):
layout.label(text="No output node.")
else:
input = find_node_input(node, input_name)
layout.template_node_view(ntree, node, input);
layout.template_node_view(ntree, node, input)
return True
class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
bl_label = "Lamp"
bl_context = "data"
@ -401,7 +418,8 @@ class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
layout.label(text="Not supported, interpreted as point lamp.")
elif lamp.type == 'HEMI':
layout.label(text="Not supported, interpreted as sun lamp.")
class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
bl_label = "Nodes"
bl_context = "data"
@ -417,6 +435,7 @@ class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
if not panel_node_draw(layout, lamp, 'OUTPUT_LAMP', 'Surface'):
layout.prop(lamp, "color")
class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel):
bl_label = "Surface"
bl_context = "world"
@ -432,6 +451,7 @@ class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel):
if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
layout.prop(world, "horizon_color", text="Color")
class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
bl_label = "Volume"
bl_context = "world"
@ -439,8 +459,8 @@ class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
world = context.world
return False # world and world.node_tree and CyclesButtonsPanel.poll(context)
# world = context.world
return False # world and world.node_tree and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
@ -449,6 +469,7 @@ class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
world = context.world
panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
bl_label = "Surface"
bl_context = "material"
@ -464,6 +485,7 @@ class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'):
layout.prop(mat, "diffuse_color")
class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
bl_label = "Volume"
bl_context = "material"
@ -471,8 +493,8 @@ class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
mat = context.material
return False #mat and mat.node_tree and CyclesButtonsPanel.poll(context)
# mat = context.material
return False # mat and mat.node_tree and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
@ -485,6 +507,7 @@ class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
layout.prop(cmat, "homogeneous_volume")
class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
bl_label = "Displacement"
bl_context = "material"
@ -500,6 +523,7 @@ class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
mat = context.material
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
bl_label = "Settings"
bl_context = "material"
@ -523,6 +547,7 @@ class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
col = split.column()
col.prop(cmat, "sample_as_light")
class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
bl_label = ""
bl_context = "texture"
@ -535,9 +560,9 @@ class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
tex = context.texture
space = context.space_data
pin_id = space.pin_id
use_pin_id = space.use_pin_id;
use_pin_id = space.use_pin_id
user = context.texture_user
node = context.texture_node
# node = context.texture_node
if not use_pin_id or not isinstance(pin_id, bpy.types.Texture):
pin_id = None
@ -555,7 +580,7 @@ class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
col.template_ID(space, "pin_id")
elif user:
col.template_ID(user, "texture", new="texture.new")
if tex:
row = split.row()
row.prop(tex, "use_nodes", icon="NODETREE", text="")
@ -566,6 +591,7 @@ class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
split.label(text="Type:")
split.prop(tex, "type", text="")
class CyclesTexture_PT_nodes(CyclesButtonsPanel, Panel):
bl_label = "Nodes"
bl_context = "texture"
@ -581,6 +607,7 @@ class CyclesTexture_PT_nodes(CyclesButtonsPanel, Panel):
tex = context.texture
panel_node_draw(layout, tex, 'OUTPUT_TEXTURE', 'Color')
class CyclesTexture_PT_node(CyclesButtonsPanel, Panel):
bl_label = "Node"
bl_context = "texture"
@ -597,6 +624,7 @@ class CyclesTexture_PT_node(CyclesButtonsPanel, Panel):
ntree = node.id_data
layout.template_node_view(ntree, node, None)
class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
bl_label = "Mapping"
bl_context = "texture"
@ -610,7 +638,7 @@ class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
tex = context.texture
# tex = context.texture
node = context.texture_node
mapping = node.texture_mapping
@ -628,6 +656,7 @@ class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
row.prop(mapping, "mapping_y", text="")
row.prop(mapping, "mapping_z", text="")
class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
bl_label = "Color"
bl_context = "texture"
@ -635,15 +664,15 @@ class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
tex = context.texture
node = context.texture_node
# tex = context.texture
# node = context.texture_node
return False
#return (node or (tex and tex.use_nodes)) and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
tex = context.texture
# tex = context.texture
node = context.texture_node
mapping = node.color_mapping
@ -668,6 +697,7 @@ class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
if mapping.use_color_ramp:
layout.template_color_ramp(mapping, "color_ramp", expand=True)
def draw_device(self, context):
scene = context.scene
layout = self.layout
@ -686,6 +716,7 @@ def draw_device(self, context):
if cscene.device == 'CPU' and engine.with_osl():
layout.prop(cscene, "shading_system")
def draw_pause(self, context):
layout = self.layout
scene = context.scene
@ -697,6 +728,7 @@ def draw_pause(self, context):
cscene = scene.cycles
layout.prop(cscene, "preview_pause", icon="PAUSE", text="")
def get_panels():
return [
bpy.types.RENDER_PT_render,
@ -752,17 +784,18 @@ def get_panels():
bpy.types.PARTICLE_PT_vertexgroups,
bpy.types.PARTICLE_PT_custom_props]
def register():
bpy.types.RENDER_PT_render.append(draw_device)
bpy.types.VIEW3D_HT_header.append(draw_pause)
for panel in get_panels():
panel.COMPAT_ENGINES.add('CYCLES')
def unregister():
bpy.types.RENDER_PT_render.remove(draw_device)
bpy.types.VIEW3D_HT_header.remove(draw_pause)
for panel in get_panels():
panel.COMPAT_ENGINES.remove('CYCLES')

@ -16,6 +16,8 @@
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# <pep8 compliant>
# XML exporter for generating test files, not intended for end users
import os
@ -24,6 +26,7 @@ from bpy_extras.io_utils import ExportHelper
import xml.etree.ElementTree as etree
import xml.dom.minidom as dom
def strip(root):
root.text = None
root.tail = None
@ -31,6 +34,7 @@ def strip(root):
for elem in root:
strip(elem)
def write(node, fname):
strip(node)
@ -40,6 +44,7 @@ def write(node, fname):
f = open(fname, "w")
f.write(s)
class ExportCyclesXML(bpy.types.Operator, ExportHelper):
''''''
bl_idname = "export_mesh.cycles_xml"
@ -82,18 +87,19 @@ class ExportCyclesXML(bpy.types.Operator, ExportHelper):
verts += " "
node = etree.Element('mesh', attrib={'nverts': nverts, 'verts': verts, 'P': P})
# write to file
write(node, filepath)
return {'FINISHED'}
def register():
pass
def unregister():
pass
if __name__ == "__main__":
register()

@ -100,7 +100,7 @@ static float get_node_output_value(BL::Node b_node, const string& name)
static void get_tex_mapping(TextureMapping *mapping, BL::TexMapping b_mapping)
{
mapping->translation = get_float3(b_mapping.location());
mapping->rotation = get_float3(b_mapping.rotation())*(M_PI/180.0f); /* in degrees! */
mapping->rotation = get_float3(b_mapping.rotation());
mapping->scale = get_float3(b_mapping.scale());
mapping->x_mapping = (TextureMapping::Mapping)b_mapping.mapping_x();
@ -108,6 +108,13 @@ static void get_tex_mapping(TextureMapping *mapping, BL::TexMapping b_mapping)
mapping->z_mapping = (TextureMapping::Mapping)b_mapping.mapping_z();
}
static void get_tex_mapping(TextureMapping *mapping, BL::ShaderNodeMapping b_mapping)
{
mapping->translation = get_float3(b_mapping.location());
mapping->rotation = get_float3(b_mapping.rotation());
mapping->scale = get_float3(b_mapping.scale());
}
static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::Node *b_group_node, BL::ShaderNode b_node)
{
ShaderNode *node = NULL;
@ -174,7 +181,7 @@ static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::Node *
BL::ShaderNodeMapping b_mapping_node(b_node);
MappingNode *mapping = new MappingNode();
get_tex_mapping(&mapping->tex_mapping, b_mapping_node.mapping());
get_tex_mapping(&mapping->tex_mapping, b_mapping_node);
node = mapping;
break;

@ -176,7 +176,13 @@ static inline string get_enum_identifier(PointerRNA& ptr, const char *name)
static inline string blender_absolute_path(BL::BlendData b_data, BL::ID b_id, const string& path)
{
if(path.size() >= 2 && path[0] == '/' && path[1] == '/') {
string dirname = (b_id.library())? b_id.library().filepath(): b_data.filepath();
string dirname;
if(b_id.library())
dirname = blender_absolute_path(b_data, b_id.library(), b_id.library().filepath());
else
dirname = b_data.filepath();
return path_join(path_dirname(dirname), path.substr(2));
}

@ -70,21 +70,6 @@ if(WITH_CYCLES_PARTIO)
endif()
###########################################################################
# Blender
if(WITH_CYCLES_BLENDER)
set(BLENDER_INCLUDE_DIRS
${CMAKE_SOURCE_DIR}/intern/guardedalloc
${CMAKE_SOURCE_DIR}/source/blender/makesdna
${CMAKE_SOURCE_DIR}/source/blender/makesrna
${CMAKE_SOURCE_DIR}/source/blender/blenloader
${CMAKE_BINARY_DIR}/source/blender/makesrna/intern)
add_definitions(-DBLENDER_PLUGIN)
endif()
###########################################################################
# CUDA

@ -48,6 +48,9 @@ public:
{
kg = kernel_globals_create();
/* do now to avoid thread issues */
system_cpu_support_optimized();
if(threads_num == 0)
threads_num = system_cpu_thread_count();
@ -155,12 +158,26 @@ public:
OSLShader::thread_init(kg);
#endif
for(int y = task.y; y < task.y + task.h; y++) {
for(int x = task.x; x < task.x + task.w; x++)
kernel_cpu_path_trace(kg, (float4*)task.buffer, (unsigned int*)task.rng_state, task.sample, x, y);
#ifdef WITH_OPTIMIZED_KERNEL
if(system_cpu_support_optimized()) {
for(int y = task.y; y < task.y + task.h; y++) {
for(int x = task.x; x < task.x + task.w; x++)
kernel_cpu_optimized_path_trace(kg, (float4*)task.buffer, (unsigned int*)task.rng_state, task.sample, x, y);
if(tasks.worker_cancel())
break;
if(tasks.worker_cancel())
break;
}
}
else
#endif
{
for(int y = task.y; y < task.y + task.h; y++) {
for(int x = task.x; x < task.x + task.w; x++)
kernel_cpu_path_trace(kg, (float4*)task.buffer, (unsigned int*)task.rng_state, task.sample, x, y);
if(tasks.worker_cancel())
break;
}
}
#ifdef WITH_OSL
@ -171,9 +188,18 @@ public:
void thread_tonemap(DeviceTask& task)
{
for(int y = task.y; y < task.y + task.h; y++) {
for(int x = task.x; x < task.x + task.w; x++)
kernel_cpu_tonemap(kg, (uchar4*)task.rgba, (float4*)task.buffer, task.sample, task.resolution, x, y);
#ifdef WITH_OPTIMIZED_KERNEL
if(system_cpu_support_optimized()) {
for(int y = task.y; y < task.y + task.h; y++)
for(int x = task.x; x < task.x + task.w; x++)
kernel_cpu_optimized_tonemap(kg, (uchar4*)task.rgba, (float4*)task.buffer, task.sample, task.resolution, x, y);
}
else
#endif
{
for(int y = task.y; y < task.y + task.h; y++)
for(int x = task.x; x < task.x + task.w; x++)
kernel_cpu_tonemap(kg, (uchar4*)task.rgba, (float4*)task.buffer, task.sample, task.resolution, x, y);
}
}
@ -184,11 +210,24 @@ public:
OSLShader::thread_init(kg);
#endif
for(int x = task.displace_x; x < task.displace_x + task.displace_w; x++) {
kernel_cpu_displace(kg, (uint4*)task.displace_input, (float3*)task.displace_offset, x);
#ifdef WITH_OPTIMIZED_KERNEL
if(system_cpu_support_optimized()) {
for(int x = task.displace_x; x < task.displace_x + task.displace_w; x++) {
kernel_cpu_optimized_displace(kg, (uint4*)task.displace_input, (float3*)task.displace_offset, x);
if(tasks.worker_cancel())
break;
if(tasks.worker_cancel())
break;
}
}
else
#endif
{
for(int x = task.displace_x; x < task.displace_x + task.displace_w; x++) {
kernel_cpu_displace(kg, (uint4*)task.displace_input, (float3*)task.displace_offset, x);
if(tasks.worker_cancel())
break;
}
}
#ifdef WITH_OSL

@ -177,6 +177,7 @@ public:
bool opencl_version_check()
{
char version[256];
int major, minor, req_major = 1, req_minor = 1;
clGetPlatformInfo(cpPlatform, CL_PLATFORM_VERSION, sizeof(version), &version, NULL);
@ -265,6 +266,20 @@ public:
build_options += "-I " + kernel_path + ""; /* todo: escape path */
build_options += " -cl-fast-relaxed-math ";
/* Full Shading only on NVIDIA cards at the moment */
char vendor[256];
clGetPlatformInfo(cpPlatform, CL_PLATFORM_NAME, sizeof(vendor), &vendor, NULL);
string name = vendor;
if (name == "NVIDIA CUDA") {
build_options += "-D __SVM__ ";
build_options += "-D __EMISSION__ ";
build_options += "-D __TEXTURES__ ";
build_options += "-D __HOLDOUT__ ";
build_options += "-D __MULTI_CLOSURE__ ";
}
ciErr = clBuildProgram(cpProgram, 0, NULL, build_options.c_str(), NULL, NULL);

@ -8,6 +8,7 @@ set(INC
set(SRC
kernel.cpp
kernel_optimized.cpp
kernel.cl
kernel.cu
)
@ -42,6 +43,7 @@ set(SRC_SVM_HEADERS
svm/bsdf.h
svm/bsdf_ashikhmin_velvet.h
svm/bsdf_diffuse.h
svm/bsdf_oren_nayar.h
svm/bsdf_microfacet.h
svm/bsdf_reflection.h
svm/bsdf_refraction.h
@ -122,11 +124,15 @@ include_directories(${INC})
add_library(cycles_kernel ${SRC} ${SRC_HEADERS} ${SRC_SVM_HEADERS})
if(WITH_CYCLES_OPTIMIZED_KERNEL)
SET_SOURCE_FILES_PROPERTIES(kernel_optimized.cpp PROPERTIES COMPILE_FLAGS ${CYCLES_OPTIMIZED_KERNEL_FLAGS})
endif()
if(WITH_CYCLES_CUDA)
add_dependencies(cycles_kernel cycles_kernel_cuda)
endif()
# OPENCL kernel
# OpenCL kernel
#set(KERNEL_PREPROCESSED ${CMAKE_CURRENT_BINARY_DIR}/kernel_preprocessed.cl)
#add_custom_command(
@ -141,3 +147,4 @@ delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel.cu" ${CYCLES_INSTALL_PATH}/k
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_SVM_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel/svm)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_UTIL_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel)

@ -38,9 +38,14 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t
void kernel_cpu_path_trace(KernelGlobals *kg, float4 *buffer, unsigned int *rng_state, int sample, int x, int y);
void kernel_cpu_tonemap(KernelGlobals *kg, uchar4 *rgba, float4 *buffer, int sample, int resolution, int x, int y);
void kernel_cpu_displace(KernelGlobals *kg, uint4 *input, float3 *offset, int i);
#ifdef WITH_OPTIMIZED_KERNEL
void kernel_cpu_optimized_path_trace(KernelGlobals *kg, float4 *buffer, unsigned int *rng_state, int sample, int x, int y);
void kernel_cpu_optimized_tonemap(KernelGlobals *kg, uchar4 *rgba, float4 *buffer, int sample, int resolution, int x, int y);
void kernel_cpu_optimized_displace(KernelGlobals *kg, uint4 *input, float3 *offset, int i);
#endif
CCL_NAMESPACE_END
#endif /* __KERNEL_H__ */

@ -49,7 +49,7 @@ typedef struct KernelGlobals {
OSLGlobals osl;
#endif
} KernelGLobals;
} KernelGlobals;
#endif

@ -0,0 +1,60 @@
/*
* Copyright 2011, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* Optimized CPU kernel entry points. This file is compiled with SSE3
optimization flags and nearly all functions inlined, while kernel.cpp
is compiled without for other CPU's. */
#ifdef WITH_OPTIMIZED_KERNEL
#include "kernel.h"
#include "kernel_compat_cpu.h"
#include "kernel_math.h"
#include "kernel_types.h"
#include "kernel_globals.h"
#include "kernel_film.h"
#include "kernel_path.h"
#include "kernel_displace.h"
CCL_NAMESPACE_BEGIN
/* Path Tracing */
void kernel_cpu_optimized_path_trace(KernelGlobals *kg, float4 *buffer, unsigned int *rng_state, int sample, int x, int y)
{
kernel_path_trace(kg, buffer, rng_state, sample, x, y);
}
/* Tonemapping */
void kernel_cpu_optimized_tonemap(KernelGlobals *kg, uchar4 *rgba, float4 *buffer, int sample, int resolution, int x, int y)
{
kernel_film_tonemap(kg, rgba, buffer, sample, resolution, x, y);
}
/* Displacement */
void kernel_cpu_optimized_displace(KernelGlobals *kg, uint4 *input, float3 *offset, int i)
{
kernel_displace(kg, input, offset, i);
}
CCL_NAMESPACE_END
#endif

@ -226,8 +226,7 @@ __device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
Ng = triangle_normal_MT(kg, prim, &shader);
/* force smooth shading for displacement */
if(shader >= 0)
shader = -shader;
sd->shader |= SHADER_SMOOTH_NORMAL;
/* watch out: no instance transform currently */

@ -12,6 +12,7 @@ set(SRC
background.cpp
bsdf_ashikhmin_velvet.cpp
bsdf_diffuse.cpp
bsdf_oren_nayar.cpp
bsdf_microfacet.cpp
bsdf_reflection.cpp
bsdf_refraction.cpp

@ -0,0 +1,174 @@
/*
* Copyright 2011, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*
* An implementation of Oren-Nayar reflectance model, public domain
* http://www1.cs.columbia.edu/CAVE/publications/pdfs/Oren_SIGGRAPH94.pdf
*
* NOTE:
* BSDF = A + B * cos() * sin() * tan()
*
* The parameter sigma means different from original.
* A and B are calculated by the following formula:
* 0 <= sigma <= 1
* A = 1 / ((1 + sigma / 2) * pi);
* B = sigma / ((1 + sigma / 2) * pi);
*
* This formula is derived as following:
*
* 0. Normalize A-term and B-term of BSDF *individually*.
* B-term is normalized at maximum point: dot(L, N) = 0.
* A = (1/pi) * A'
* B = (2/pi) * B'
*
* 1. Solve the following equation:
* A' + B' = 1
* B / A = sigma
*/
#include <OpenImageIO/fmath.h>
#include <OSL/genclosure.h>
#include "osl_closures.h"
CCL_NAMESPACE_BEGIN
using namespace OSL;
class OrenNayarClosure: public BSDFClosure {
public:
Vec3 m_N;
float m_sigma;
float m_a, m_b;
OrenNayarClosure(): BSDFClosure(Labels::DIFFUSE) {}
void setup() {
m_sigma = clamp(m_sigma, 0.0f, 1.0f);
m_a = 1.0f / ((1.0f + 0.5f * m_sigma) * M_PI);
m_b = m_sigma / ((1.0f + 0.5f * m_sigma) * M_PI);
}
bool mergeable(const ClosurePrimitive* other) const {
const OrenNayarClosure* comp = static_cast<const OrenNayarClosure*>(other);
return
m_N == comp->m_N &&
m_sigma == comp->m_sigma &&
BSDFClosure::mergeable(other);
}
size_t memsize() const {
return sizeof(*this);
}
const char* name() const {
return "oren_nayar";
}
void print_on(std::ostream& out) const {
out << name() << " (";
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
out << m_sigma;
out << ")";
}
float albedo(const Vec3& omega_out) const {
return 1.0f;
}
Color3 eval_reflect(const Vec3& omega_out, const Vec3& omega_in, float& pdf) const {
if (m_N.dot(omega_in) > 0.0f) {
pdf = float(0.5 * M_1_PI);
float is = get_intensity(m_N, omega_out, omega_in);
return Color3(is, is, is);
}
else {
pdf = 0.0f;
return Color3(0.0f, 0.0f, 0.0f);
}
}
Color3 eval_transmit(const Vec3& omega_out, const Vec3& omega_in, float& pdf) const {
return Color3(0.0f, 0.0f, 0.0f);
}
ustring sample(
const Vec3& Ng,
const Vec3& omega_out, const Vec3& domega_out_dx, const Vec3& domega_out_dy,
float randu, float randv,
Vec3& omega_in, Vec3& domega_in_dx, Vec3& domega_in_dy,
float& pdf, Color3& eval
) const {
sample_uniform_hemisphere (m_N, omega_out, randu, randv, omega_in, pdf);
if (Ng.dot(omega_in) > 0.0f) {
float is = get_intensity(m_N, omega_out, omega_in);
eval.setValue(is, is, is);
// TODO: find a better approximation for the bounce
domega_in_dx = (2.0f * m_N.dot(domega_out_dx)) * m_N - domega_out_dx;
domega_in_dy = (2.0f * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
domega_in_dx *= 125.0f;
domega_in_dy *= 125.0f;
}
else {
pdf = 0.0f;
}
return Labels::REFLECT;
}
private:
float get_intensity(Vec3 const& n, Vec3 const& v, Vec3 const& l) const {
float nl = max(n.dot(l), 0.0f);
float nv = max(n.dot(v), 0.0f);
Vec3 al = l - nl * n;
al.normalize();
Vec3 av = v - nv * n;
av.normalize();
float t = max(al.dot(av), 0.0f);
float cos_a, cos_b;
if (nl < nv) {
cos_a = nl;
cos_b = nv;
}
else {
cos_a = nv;
cos_b = nl;
}
float sin_a = sqrtf(1.0f - cos_a * cos_a);
float tan_b = sqrtf(1.0f - cos_b * cos_b) / (cos_b + FLT_MIN);
return nl * (m_a + m_b * t * sin_a * tan_b);
}
};
ClosureParam bsdf_oren_nayar_params[] = {
CLOSURE_VECTOR_PARAM (OrenNayarClosure, m_N),
CLOSURE_FLOAT_PARAM (OrenNayarClosure, m_sigma),
CLOSURE_STRING_KEYPARAM ("label"),
CLOSURE_FINISH_PARAM (OrenNayarClosure)
};
CLOSURE_PREPARE(bsdf_oren_nayar_prepare, OrenNayarClosure)
CCL_NAMESPACE_END

@ -20,9 +20,13 @@
shader node_diffuse_bsdf(
color Color = color(0.8, 0.8, 0.8),
float Roughness = 0.0,
normal Normal = N,
output closure color BSDF = diffuse(Normal))
{
BSDF = Color*diffuse(Normal);
if(Roughness == 0.0)
BSDF = Color * diffuse(Normal);
else
BSDF = Color * oren_nayar(Normal, Roughness);
}

@ -435,6 +435,7 @@ string concat (string a, string b, string c, string d, string e, string f) {
// Closures
closure color diffuse(normal N) BUILTIN;
closure color oren_nayar(normal N, float sigma) BUILTIN;
closure color translucent(normal N) BUILTIN;
closure color reflection(normal N, float eta) BUILTIN;
closure color reflection(normal N) { return reflection (N, 0.0); }

@ -69,6 +69,7 @@ static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, O
void OSLShader::register_closures(OSL::ShadingSystem *ss)
{
register_closure(ss, "diffuse", OSL_CLOSURE_BSDF_DIFFUSE_ID, bsdf_diffuse_params, bsdf_diffuse_prepare);
register_closure(ss, "oren_nayar", OSL_CLOSURE_BSDF_OREN_NAYAR_ID, bsdf_oren_nayar_params, bsdf_oren_nayar_prepare);
register_closure(ss, "translucent", OSL_CLOSURE_BSDF_TRANSLUCENT_ID, bsdf_translucent_params, bsdf_translucent_prepare);
register_closure(ss, "reflection", OSL_CLOSURE_BSDF_REFLECTION_ID, bsdf_reflection_params, bsdf_reflection_prepare);
register_closure(ss, "refraction", OSL_CLOSURE_BSDF_REFRACTION_ID, bsdf_refraction_params, bsdf_refraction_prepare);

@ -41,6 +41,7 @@ CCL_NAMESPACE_BEGIN
enum {
OSL_CLOSURE_BSDF_DIFFUSE_ID,
OSL_CLOSURE_BSDF_OREN_NAYAR_ID,
OSL_CLOSURE_BSDF_TRANSLUCENT_ID,
OSL_CLOSURE_BSDF_REFLECTION_ID,
OSL_CLOSURE_BSDF_REFRACTION_ID,
@ -62,6 +63,7 @@ enum {
};
extern OSL::ClosureParam bsdf_diffuse_params[];
extern OSL::ClosureParam bsdf_oren_nayar_params[];
extern OSL::ClosureParam bsdf_translucent_params[];
extern OSL::ClosureParam bsdf_reflection_params[];
extern OSL::ClosureParam bsdf_refraction_params[];
@ -82,6 +84,7 @@ extern OSL::ClosureParam closure_holdout_params[];
extern OSL::ClosureParam closure_subsurface_params[];
void bsdf_diffuse_prepare(OSL::RendererServices *, int id, void *data);
void bsdf_oren_nayar_prepare(OSL::RendererServices *, int id, void *data);
void bsdf_translucent_prepare(OSL::RendererServices *, int id, void *data);
void bsdf_reflection_prepare(OSL::RendererServices *, int id, void *data);
void bsdf_refraction_prepare(OSL::RendererServices *, int id, void *data);

@ -45,7 +45,7 @@ typedef struct BsdfMicrofacetGGXClosure {
__device void bsdf_microfacet_ggx_setup(ShaderData *sd, ShaderClosure *sc, float ag, float eta, bool refractive)
{
float m_ag = clamp(ag, 1e-5f, 1.0f);
float m_ag = clamp(ag, 1e-4f, 1.0f);
float m_eta = eta;
sc->data0 = m_ag;
@ -270,7 +270,7 @@ typedef struct BsdfMicrofacetBeckmannClosure {
__device void bsdf_microfacet_beckmann_setup(ShaderData *sd, ShaderClosure *sc, float ab, float eta, bool refractive)
{
float m_ab = clamp(ab, 1e-5f, 1.0f);
float m_ab = clamp(ab, 1e-4f, 1.0f);
float m_eta = eta;
sc->data0 = m_ab;

@ -0,0 +1,145 @@
/*
* Copyright 2011, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*
* An implementation of Oren-Nayar reflectance model, public domain
* http://www1.cs.columbia.edu/CAVE/publications/pdfs/Oren_SIGGRAPH94.pdf
*
* NOTE:
* BSDF = A + B * cos() * sin() * tan()
*
* The parameter sigma means different from original.
* A and B are calculated by the following formula:
* 0 <= sigma <= 1
* A = 1 / ((1 + sigma / 2) * pi);
* B = sigma / ((1 + sigma / 2) * pi);
*
* This formula is derived as following:
*
* 0. Normalize A-term and B-term of BSDF *individually*.
* B-term is normalized at maximum point: dot(L, N) = 0.
* A = (1/pi) * A'
* B = (2/pi) * B'
*
* 1. Solve the following equation:
* A' + B' = 1
* B / A = sigma
*/
#ifndef __BSDF_OREN_NAYAR_H__
#define __BSDF_OREN_NAYAR_H__
CCL_NAMESPACE_BEGIN
typedef struct BsdfOrenNayarClosure {
float m_a;
float m_b;
} BsdfOrenNayarClosure;
__device float3 bsdf_oren_nayar_get_intensity(const ShaderClosure *sc, float3 n, float3 v, float3 l)
{
float nl = max(dot(n, l), 0.0f);
float nv = max(dot(n, v), 0.0f);
float3 al = normalize(l - nl * n);
float3 av = normalize(v - nv * n);
float t = max(dot(al, av), 0.0f);
float cos_a, cos_b;
if(nl < nv) {
cos_a = nl;
cos_b = nv;
}
else {
cos_a = nv;
cos_b = nl;
}
float sin_a = sqrtf(max(1.0f - cos_a * cos_a, 0.0f));
float tan_b = sqrtf(max(1.0f - cos_b * cos_b, 0.0f)) / max(cos_b, 1e-8f);
float is = nl * (sc->data0 + sc->data1 * t * sin_a * tan_b);
return make_float3(is, is, is);
}
__device void bsdf_oren_nayar_setup(ShaderData *sd, ShaderClosure *sc, float sigma)
{
sc->type = CLOSURE_BSDF_OREN_NAYAR_ID;
sd->flag |= SD_BSDF | SD_BSDF_HAS_EVAL;
sigma = clamp(sigma, 0.0f, 1.0f);
float div = 1.0f / ((1.0f + 0.5f * sigma) * M_PI_F);
sc->data0 = 1.0f * div;
sc->data1 = sigma * div;
}
__device void bsdf_oren_nayar_blur(ShaderClosure *sc, float roughness)
{
}
__device float3 bsdf_oren_nayar_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
if (dot(sd->N, omega_in) > 0.0f) {
*pdf = 0.5f * M_1_PI_F;
return bsdf_oren_nayar_get_intensity(sc, sd->N, I, omega_in);
}
else {
*pdf = 0.0f;
return make_float3(0.0f, 0.0f, 0.0f);
}
}
__device float3 bsdf_oren_nayar_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
__device float bsdf_oren_nayar_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__device int bsdf_oren_nayar_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{
sample_uniform_hemisphere(sd->N, randu, randv, omega_in, pdf);
if (dot(sd->Ng, *omega_in) > 0.0f) {
*eval = bsdf_oren_nayar_get_intensity(sc, sd->N, sd->I, *omega_in);
#ifdef __RAY_DIFFERENTIALS__
// TODO: find a better approximation for the bounce
*domega_in_dx = (2.0f * dot(sd->N, sd->dI.dx)) * sd->N - sd->dI.dx;
*domega_in_dy = (2.0f * dot(sd->N, sd->dI.dy)) * sd->N - sd->dI.dy;
*domega_in_dx *= 125.0f;
*domega_in_dy *= 125.0f;
#endif
}
else {
*pdf = 0.0f;
*eval = make_float3(0.0f, 0.0f, 0.0f);
}
return LABEL_REFLECT | LABEL_DIFFUSE;
}
CCL_NAMESPACE_END
#endif /* __BSDF_OREN_NAYAR_H__ */

@ -18,6 +18,7 @@
#include "bsdf_ashikhmin_velvet.h"
#include "bsdf_diffuse.h"
#include "bsdf_oren_nayar.h"
#include "bsdf_microfacet.h"
#include "bsdf_reflection.h"
#include "bsdf_refraction.h"
@ -38,6 +39,9 @@ __device int svm_bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, floa
label = bsdf_diffuse_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
#ifdef __SVM__
case CLOSURE_BSDF_OREN_NAYAR_ID:
label = bsdf_oren_nayar_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_TRANSLUCENT_ID:
label = bsdf_translucent_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
@ -91,6 +95,9 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con
eval = bsdf_diffuse_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break;
#ifdef __SVM__
case CLOSURE_BSDF_OREN_NAYAR_ID:
eval = bsdf_oren_nayar_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSLUCENT_ID:
eval = bsdf_translucent_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break;
@ -137,6 +144,9 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con
eval = bsdf_diffuse_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break;
#ifdef __SVM__
case CLOSURE_BSDF_OREN_NAYAR_ID:
eval = bsdf_oren_nayar_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSLUCENT_ID:
eval = bsdf_translucent_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break;
@ -188,6 +198,9 @@ __device void svm_bsdf_blur(ShaderClosure *sc, float roughness)
bsdf_diffuse_blur(sc, roughness);
break;
#ifdef __SVM__
case CLOSURE_BSDF_OREN_NAYAR_ID:
bsdf_oren_nayar_blur(sc, roughness);
break;
case CLOSURE_BSDF_TRANSLUCENT_ID:
bsdf_translucent_blur(sc, roughness);
break;

@ -80,7 +80,12 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
case CLOSURE_BSDF_DIFFUSE_ID: {
ShaderClosure *sc = svm_node_closure_get(sd);
svm_node_closure_set_mix_weight(sc, mix_weight);
bsdf_diffuse_setup(sd, sc);
float roughness = param1;
if(roughness == 0.0f)
bsdf_diffuse_setup(sd, sc);
else
bsdf_oren_nayar_setup(sd, sc, roughness);
break;
}
case CLOSURE_BSDF_TRANSLUCENT_ID: {

@ -258,6 +258,7 @@ typedef enum ShaderType {
typedef enum ClosureType {
CLOSURE_BSDF_ID,
CLOSURE_BSDF_DIFFUSE_ID,
CLOSURE_BSDF_OREN_NAYAR_ID,
CLOSURE_BSDF_TRANSLUCENT_ID,
CLOSURE_BSDF_REFLECTION_ID,
CLOSURE_BSDF_REFRACTION_ID,

@ -1003,11 +1003,12 @@ void VelvetBsdfNode::compile(OSLCompiler& compiler)
DiffuseBsdfNode::DiffuseBsdfNode()
{
closure = CLOSURE_BSDF_DIFFUSE_ID;
add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f);
}
void DiffuseBsdfNode::compile(SVMCompiler& compiler)
{
BsdfNode::compile(compiler, NULL, NULL);
BsdfNode::compile(compiler, input("Roughness"), NULL);
}
void DiffuseBsdfNode::compile(OSLCompiler& compiler)

@ -11,7 +11,7 @@ set(SRC
util_dynlib.cpp
util_md5.cpp
util_memarena.cpp
util_opencl.c
util_opencl.cpp
util_path.cpp
util_string.cpp
util_system.cpp

@ -7,6 +7,8 @@
// Extracted from the CLCC project - http://clcc.sourceforge.net/
//////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include "util_opencl.h"
#ifndef CLCC_GENERATE_DOCUMENTATION
@ -36,7 +38,7 @@
//#define CLCC_DYNLIB_IMPORT implementation_defined
#endif
#include <stdlib.h>
CCL_NAMESPACE_BEGIN
//! \brief module handle
static CLCC_DYNLIB_HANDLE module = NULL;
@ -315,3 +317,5 @@ const char *clErrorString(cl_int error)
return strings[-error];
}
CCL_NAMESPACE_END

15
intern/cycles/util/util_opencl.h Executable file → Normal file

@ -10,6 +10,8 @@
#ifndef __UTIL_OPENCL_H__
#define __UTIL_OPENCL_H__
CCL_NAMESPACE_BEGIN
//! This file contains a copy of the contents of CL.H and CL_PLATFORM.H from the
//! official OpenCL spec. The purpose of this code is to load the OpenCL dynamic
//! library at run-time and thus allow the executable to function on many
@ -56,15 +58,6 @@
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
******************************************************************************/
#ifdef __APPLE__
/* Contains #defines for AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER below */
#include <AvailabilityMacros.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef CLCC_GENERATE_DOCUMENTATION
#if defined(_WIN32)
@ -1312,9 +1305,7 @@ CLEW_FUN_EXPORT PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFuncti
int clLibraryInit(void);
const char *clErrorString(cl_int error);
#ifdef __cplusplus
}
#endif
CCL_NAMESPACE_END
#endif /* __UTIL_OPENCL_H__ */

@ -118,5 +118,78 @@ int system_cpu_bits()
return (sizeof(void*)*8);
}
#if defined(__x86_64__) || defined(_M_X64) || defined(i386) || defined(_M_IX86)
struct CPUCapabilities {
bool x64;
bool mmx;
bool sse;
bool sse2;
bool sse3;
bool ssse3;
bool sse41;
bool sse42;
bool sse4a;
bool avx;
bool xop;
bool fma3;
bool fma4;
};
bool system_cpu_support_optimized()
{
static CPUCapabilities caps;
static bool caps_init = false;
if(!caps_init) {
int result[4], num, num_ex;
memset(&caps, 0, sizeof(caps));
__cpuid(result, 0);
num = result[0];
__cpuid(result, 0x80000000);
num_ex = result[0];
if(num >= 1){
__cpuid(result, 0x00000001);
caps.mmx = (result[3] & ((int)1 << 23)) != 0;
caps.sse = (result[3] & ((int)1 << 25)) != 0;
caps.sse2 = (result[3] & ((int)1 << 26)) != 0;
caps.sse3 = (result[2] & ((int)1 << 0)) != 0;
caps.ssse3 = (result[2] & ((int)1 << 9)) != 0;
caps.sse41 = (result[2] & ((int)1 << 19)) != 0;
caps.sse42 = (result[2] & ((int)1 << 20)) != 0;
caps.avx = (result[2] & ((int)1 << 28)) != 0;
caps.fma3 = (result[2] & ((int)1 << 12)) != 0;
}
/*if(num_ex >= 0x80000001){
__cpuid(result, 0x80000001);
caps.x64 = (result[3] & ((int)1 << 29)) != 0;
caps.sse4a = (result[2] & ((int)1 << 6)) != 0;
caps.fma4 = (result[2] & ((int)1 << 16)) != 0;
caps.xop = (result[2] & ((int)1 << 11)) != 0;
}*/
caps_init = true;
}
/* optimization flags use these */
return caps.sse && caps.sse2 && caps.sse3;
}
#else
bool system_cpu_support_optimized()
{
return false;
}
#endif
CCL_NAMESPACE_END

@ -26,6 +26,7 @@ CCL_NAMESPACE_BEGIN
int system_cpu_thread_count();
string system_cpu_brand_string();
int system_cpu_bits();
bool system_cpu_support_optimized();
CCL_NAMESPACE_END

@ -578,7 +578,7 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
if (strstr(rstring,"MacBookAir") ||
(strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9')))
m_hasMultiTouchTrackpad = true;
else m_hasMultiTouchTrackpad = true; // experimental, changes only MagicMouse behaviour (zoom->pan) but enables MagicTrackpad for all Macs
else m_hasMultiTouchTrackpad = false;
free( rstring );
rstring = NULL;

@ -24,6 +24,7 @@
#include "segment.hpp"
#include <string>
#include <Eigen/StdVector>
namespace KDL {
/**
@ -34,7 +35,12 @@ namespace KDL {
*/
class Chain {
private:
#if !defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_5)
// Eigen allocator is needed for alignment of Eigen data types
std::vector<Segment, Eigen::aligned_allocator<Segment> > segments;
#else
std::vector<Segment> segments;
#endif
unsigned int nrOfJoints;
unsigned int nrOfSegments;
public:

@ -27,13 +27,20 @@
#include <string>
#include <map>
#if !defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_5)
#include <Eigen/Core>
#endif
namespace KDL
{
//Forward declaration
class TreeElement;
#if !defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_5)
// Eigen allocator is needed for alignment of Eigen data types
typedef std::map<std::string,TreeElement, std::less<std::string>, Eigen::aligned_allocator<std::pair<std::string, TreeElement> > > SegmentMap;
#else
typedef std::map<std::string,TreeElement> SegmentMap;
#endif
class TreeElement
{
private:

@ -62,7 +62,7 @@ def modules(module_cache):
path_list = paths()
# fake module importing
def fake_module(mod_name, mod_path, speedy=True):
def fake_module(mod_name, mod_path, speedy=True, force_support=None):
global error_encoding
if _bpy.app.debug:
@ -134,6 +134,9 @@ def modules(module_cache):
traceback.print_exc()
raise
if force_support is not None:
mod.bl_info["support"] = force_support
return mod
else:
return None
@ -141,6 +144,10 @@ def modules(module_cache):
modules_stale = set(module_cache.keys())
for path in path_list:
# force all contrib addons to be 'TESTING'
force_support = 'TESTING' if path.endswith("addons_contrib") else None
for mod_name, mod_path in _bpy.path.module_names(path):
modules_stale -= {mod_name}
mod = module_cache.get(mod_name)
@ -161,7 +168,7 @@ def modules(module_cache):
mod = None
if mod is None:
mod = fake_module(mod_name, mod_path)
mod = fake_module(mod_name, mod_path, force_support=force_support)
if mod:
module_cache[mod_name] = mod

@ -35,9 +35,9 @@ def drepr(string):
class DataPathBuilder(object):
__slots__ = ("data_path", )
""" Dummy class used to parse fcurve and driver data paths.
"""
__slots__ = ("data_path", )
def __init__(self, attrs):
self.data_path = attrs

@ -154,25 +154,23 @@ def resolve_ncase(path):
returning a string with the path if found else return the original path.
"""
import os
def _ncase_path_found(path):
if not path or os.path.exists(path):
if not path or _os.path.exists(path):
return path, True
# filename may be a directory or a file
filename = os.path.basename(path)
dirpath = os.path.dirname(path)
filename = _os.path.basename(path)
dirpath = _os.path.dirname(path)
suffix = path[:0] # "" but ensure byte/str match
if not filename: # dir ends with a slash?
if len(dirpath) < len(path):
suffix = path[:len(path) - len(dirpath)]
filename = os.path.basename(dirpath)
dirpath = os.path.dirname(dirpath)
filename = _os.path.basename(dirpath)
dirpath = _os.path.dirname(dirpath)
if not os.path.exists(dirpath):
if not _os.path.exists(dirpath):
if dirpath == path:
return path, False
@ -184,8 +182,8 @@ def resolve_ncase(path):
# at this point, the directory exists but not the file
# we are expecting 'dirpath' to be a directory, but it could be a file
if os.path.isdir(dirpath):
files = os.listdir(dirpath)
if _os.path.isdir(dirpath):
files = _os.listdir(dirpath)
else:
return path, False
@ -198,7 +196,7 @@ def resolve_ncase(path):
break
if f_iter_nocase:
return os.path.join(dirpath, f_iter_nocase) + suffix, True
return _os.path.join(dirpath, f_iter_nocase) + suffix, True
else:
# cant find the right one, just return the path as is.
return path, False
@ -216,8 +214,7 @@ def ensure_ext(filepath, ext, case_sensitive=False):
:arg case_sensitive: Check for matching case when comparing extensions.
:type case_sensitive: bool
"""
import os
fn_base, fn_ext = os.path.splitext(filepath)
fn_base, fn_ext = _os.path.splitext(filepath)
if fn_base and fn_ext:
if ((case_sensitive and ext == fn_ext) or
(ext.lower() == fn_ext.lower())):

@ -0,0 +1,4 @@
import bpy
bpy.context.object.data.sensor_width = 23.4
bpy.context.object.data.sensor_height = 15.6
bpy.context.object.data.sensor_fit = 'HORIZONTAL'

@ -0,0 +1,10 @@
import bpy
camera = bpy.context.edit_movieclip.tracking.camera
camera.sensor_width = 23.4
camera.units = 'MILLIMETERS'
camera.focal_length = 24.0
camera.pixel_aspect = 1
camera.k1 = 0.0
camera.k2 = 0.0
camera.k3 = 0.0

@ -24,27 +24,28 @@ from bpy.types import Operator
from bpy_extras.io_utils import unpack_list
def CLIP_track_view_selected(sc, track):
if track.select_anchor:
return True
if sc.show_marker_pattern and track.select_pattern:
return True
if sc.show_marker_search and track.select_search:
return True
return False
class CLIP_OT_track_to_empty(Operator):
"""Create an Empty object which will be copying movement of active track"""
bl_idname = "clip.track_to_empty"
bl_label = "2D Track to Empty"
bl_label = "Link Empty to Track"
bl_options = {'UNDO', 'REGISTER'}
@classmethod
def poll(cls, context):
if context.space_data.type != 'CLIP_EDITOR':
return False
def _link_track(self, context, track):
sc = context.space_data
clip = sc.clip
return clip and clip.tracking.tracks.active
def execute(self, context):
sc = context.space_data
clip = sc.clip
track = clip.tracking.tracks.active
constraint = None
ob = None
@ -63,27 +64,30 @@ class CLIP_OT_track_to_empty(Operator):
constraint.clip = sc.clip
constraint.track = track.name
constraint.reference = 'TRACK'
constraint.use_3d_position = False
def execute(self, context):
sc = context.space_data
clip = sc.clip
for track in clip.tracking.tracks:
if CLIP_track_view_selected(sc, track):
self._link_track(context, track)
return {'FINISHED'}
class CLIP_OT_bundles_to_mesh(Operator):
"""Create vertex cloud using coordinates of bundles"""
class CLIP_OT_tracks_to_mesh(Operator):
"""Create vertex cloud using coordinates of tracks"""
bl_idname = "clip.bundles_to_mesh"
bl_label = "Bundles to Mesh"
bl_idname = "clip.tracks_to_mesh"
bl_label = "Tracks to Mesh"
bl_options = {'UNDO', 'REGISTER'}
@classmethod
def poll(cls, context):
if context.space_data.type != 'CLIP_EDITOR':
return False
sc = context.space_data
clip = sc.clip
return clip
return (sc.type == 'CLIP_EDITOR') and sc.clip
def execute(self, context):
sc = context.space_data
@ -91,7 +95,7 @@ class CLIP_OT_bundles_to_mesh(Operator):
new_verts = []
mesh = bpy.data.meshes.new(name="Bundles")
mesh = bpy.data.meshes.new(name="Tracks")
for track in clip.tracking.tracks:
if track.has_bundle:
new_verts.append(track.bundle)
@ -100,7 +104,7 @@ class CLIP_OT_bundles_to_mesh(Operator):
mesh.vertices.add(len(new_verts))
mesh.vertices.foreach_set("co", unpack_list(new_verts))
ob = bpy.data.objects.new(name="Bundles", object_data=mesh)
ob = bpy.data.objects.new(name="Tracks", object_data=mesh)
bpy.context.scene.objects.link(ob)
@ -112,10 +116,13 @@ class CLIP_OT_delete_proxy(Operator):
bl_idname = "clip.delete_proxy"
bl_label = "Delete Proxy"
bl_options = {'UNDO', 'REGISTER'}
bl_options = {'REGISTER'}
@classmethod
def poll(cls, context):
if context.space_data.type != 'CLIP_EDITOR':
return False
sc = context.space_data
return sc.clip
@ -179,11 +186,12 @@ class CLIP_OT_delete_proxy(Operator):
class CLIP_OT_set_viewport_background(Operator):
"""Set current movie clip as a camera background in 3D viewport"""
"""Set current movie clip as a camera background in 3D viewport \
(works only when a 3D viewport is visible)"""
bl_idname = "clip.set_viewport_background"
bl_label = "Set as Background"
bl_options = {'UNDO', 'REGISTER'}
bl_options = {'REGISTER'}
@classmethod
def poll(cls, context):
@ -203,7 +211,7 @@ class CLIP_OT_set_viewport_background(Operator):
break
if not bgpic:
bgpic = space_v3d.background_images.add()
bgpic = space_v3d.background_images.new()
bgpic.source = 'MOVIE'
bgpic.clip = clip
@ -228,7 +236,8 @@ class CLIP_OT_set_viewport_background(Operator):
class CLIP_OT_constraint_to_fcurve(Operator):
"""Create F-Curves for object which will copy object's movement caused by this constraint"""
"""Create F-Curves for object which will copy \
object's movement caused by this constraint"""
bl_idname = "clip.constraint_to_fcurve"
bl_label = "Constraint to F-Curve"
@ -250,14 +259,10 @@ class CLIP_OT_constraint_to_fcurve(Operator):
con = x
if not con:
return
self.report({'ERROR'},
"Motion Tracking constraint to be converted not found")
if con.type == 'FOLLOW_TRACK' and con.reference == 'BUNDLE':
mat = ob.matrix_world.copy()
ob.constraints.remove(con)
ob.matrix_world = mat
return
return {'CANCELLED'}
# Get clip used for parenting
if con.use_active_clip:
@ -266,7 +271,17 @@ class CLIP_OT_constraint_to_fcurve(Operator):
clip = con.clip
if not clip:
return
self.report({'ERROR'},
"Movie clip to use tracking data from isn't set")
return {'CANCELLED'}
if con.type == 'FOLLOW_TRACK' and con.use_3d_position:
mat = ob.matrix_world.copy()
ob.constraints.remove(con)
ob.matrix_world = mat
return {'FINISHED'}
# Find start and end frames
for track in clip.tracking.tracks:

@ -147,7 +147,7 @@ class ProjectEdit(Operator):
# opengl buffer may fail, we can't help this, but best report it.
try:
ret = bpy.ops.paint.image_from_view()
bpy.ops.paint.image_from_view()
except RuntimeError as err:
self.report({'ERROR'}, str(err))
return {'CANCELLED'}

@ -349,7 +349,7 @@ class AddPresetTrackingTrackColor(AddPresetBase, Operator):
preset_menu = "CLIP_MT_track_color_presets"
preset_defines = [
"track = bpy.context.edit_movieclip.tracking.tracks"
"track = bpy.context.edit_movieclip.tracking.tracks.active"
]
preset_values = [

@ -106,7 +106,7 @@ def operator_path_is_undo(context, data_path):
# luckily we don't do this!
#
# When we cant find the data owner assume no undo is needed.
data_path_head, data_path_sep, data_path_tail = data_path.rpartition(".")
data_path_head = data_path.rpartition(".")[0]
if not data_path_head:
return False

@ -116,11 +116,15 @@ def register():
)
WindowManager.addon_support = EnumProperty(
items=[('OFFICIAL', "Official", ""),
('COMMUNITY', 'Community', ""),
items=[('OFFICIAL', "Official", "Officially supported"),
('COMMUNITY', "Community", "Maintained by community developers"),
('TESTING', "Testing", "Newly contributed scripts (excluded from release builds)"),
],
name="Support",
description="Display support level", default={'OFFICIAL', 'COMMUNITY'}, options={'ENUM_FLAG'})
description="Display support level",
default={'OFFICIAL', 'COMMUNITY'},
options={'ENUM_FLAG'},
)
# done...

@ -414,6 +414,80 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
row.operator("object.multires_external_save", text="Save External...")
row.label()
def OCEAN(self, layout, ob, md):
if not md.is_build_enabled:
layout.label("Built without OceanSim modifier")
return
layout.prop(md, "geometry_mode")
if md.geometry_mode == 'GENERATE':
row = layout.row()
row.prop(md, "repeat_x")
row.prop(md, "repeat_y")
layout.separator()
flow = layout.column_flow()
flow.prop(md, "time")
flow.prop(md, "resolution")
flow.prop(md, "spatial_size")
flow.prop(md, "depth")
layout.label("Waves:")
split = layout.split()
col = split.column()
col.prop(md, "choppiness")
col.prop(md, "wave_scale", text="Scale")
col.prop(md, "wave_scale_min")
col.prop(md, "wind_velocity")
col = split.column()
col.prop(md, "wave_alignment", text="Alignment")
sub = col.column()
sub.active = md.wave_alignment > 0
sub.prop(md, "wave_direction", text="Direction")
sub.prop(md, "damping")
layout.separator()
layout.prop(md, "use_normals")
split = layout.split()
col = split.column()
col.prop(md, "use_foam")
sub = col.row()
sub.active = md.use_foam
sub.prop(md, "foam_coverage", text="Coverage")
col = split.column()
col.active = md.use_foam
col.label("Foam Data Layer Name:")
col.prop(md, "foam_layer_name", text="")
layout.separator()
if md.is_cached:
layout.operator("object.ocean_bake", text="Free Bake").free = True
else:
layout.operator("object.ocean_bake")
split = layout.split()
split.enabled = not md.is_cached
col = split.column(align=True)
col.prop(md, "frame_start", text="Start")
col.prop(md, "frame_end", text="End")
col = split.column(align=True)
col.label(text="Cache path:")
col.prop(md, "filepath", text="")
#col.prop(md, "bake_foam_fade")
def PARTICLE_INSTANCE(self, layout, ob, md):
layout.prop(md, "object")
layout.prop(md, "particle_system_index", text="Particle System")

Some files were not shown because too many files have changed in this diff Show More