Basic Alembic support
All in all, this patch adds an Alembic importer, an Alembic exporter, and a new CacheFile data block which, for now, wraps around an Alembic archive. This data block is made available through a new modifier ("Mesh Sequence Cache") as well as a new constraint ("Transform Cache") to somewhat properly support respectively geometric and transformation data streaming from alembic caches. A more in-depth documentation is to be found on the wiki, as well as a guide to compile alembic: https://wiki.blender.org/index.php/ User:Kevindietrich/AlembicBasicIo. Many thanks to everyone involved in this little project, and huge shout out to "cgstrive" for the thorough testings with Maya, 3ds Max, Houdini and Realflow as well as @fjuhec, @jensverwiebe and @jasperge for the custom builds and compile fixes. Reviewers: sergey, campbellbarton, mont29 Reviewed By: sergey, campbellbarton, mont29 Differential Revision: https://developer.blender.org/D2060
This commit is contained in:
parent
4158737cb2
commit
61050f75b1
@ -323,6 +323,10 @@ option(WITH_CODEC_AVI "Enable Blenders own AVI file support (raw/jpeg)
|
|||||||
option(WITH_CODEC_FFMPEG "Enable FFMPeg Support (http://ffmpeg.org)" ${_init_CODEC_FFMPEG})
|
option(WITH_CODEC_FFMPEG "Enable FFMPeg Support (http://ffmpeg.org)" ${_init_CODEC_FFMPEG})
|
||||||
option(WITH_CODEC_SNDFILE "Enable libsndfile Support (http://www.mega-nerd.com/libsndfile)" OFF)
|
option(WITH_CODEC_SNDFILE "Enable libsndfile Support (http://www.mega-nerd.com/libsndfile)" OFF)
|
||||||
|
|
||||||
|
# Alembic support
|
||||||
|
option(WITH_ALEMBIC "Enable Alembic Support" OFF)
|
||||||
|
option(WITH_ALEMBIC_HDF5 "Enable Legacy Alembic Support (not officially supported)" OFF)
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
option(WITH_CODEC_QUICKTIME "Enable Quicktime Support" ON)
|
option(WITH_CODEC_QUICKTIME "Enable Quicktime Support" ON)
|
||||||
endif()
|
endif()
|
||||||
@ -720,6 +724,11 @@ if(WITH_OPENIMAGEIO)
|
|||||||
set(WITH_IMAGE_TIFF ON)
|
set(WITH_IMAGE_TIFF ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# auto enable alembic linking dependencies
|
||||||
|
if(WITH_ALEMBIC)
|
||||||
|
set(WITH_IMAGE_OPENEXR ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
# don't store paths to libs for portable distribution
|
# don't store paths to libs for portable distribution
|
||||||
if(WITH_INSTALL_PORTABLE)
|
if(WITH_INSTALL_PORTABLE)
|
||||||
set(CMAKE_SKIP_BUILD_RPATH TRUE)
|
set(CMAKE_SKIP_BUILD_RPATH TRUE)
|
||||||
@ -1091,6 +1100,21 @@ if(UNIX AND NOT APPLE)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_ALEMBIC)
|
||||||
|
set(ALEMBIC_ROOT_DIR ${LIBDIR}/alembic)
|
||||||
|
find_package_wrapper(Alembic)
|
||||||
|
|
||||||
|
if(WITH_ALEMBIC_HDF5)
|
||||||
|
set(HDF5_ROOT_DIR ${LIBDIR}/hdf5)
|
||||||
|
find_package_wrapper(HDF5)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT ALEMBIC_FOUND OR (WITH_ALEMBIC_HDF5 AND NOT HDF5_FOUND))
|
||||||
|
set(WITH_ALEMBIC OFF)
|
||||||
|
set(WITH_ALEMBIC_HDF5 OFF)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WITH_BOOST)
|
if(WITH_BOOST)
|
||||||
# uses in build instructions to override include and library variables
|
# uses in build instructions to override include and library variables
|
||||||
if(NOT BOOST_CUSTOM)
|
if(NOT BOOST_CUSTOM)
|
||||||
@ -1660,6 +1684,21 @@ elseif(WIN32)
|
|||||||
set(OPENVDB_LIBPATH ${LIBDIR}/openvdb/lib)
|
set(OPENVDB_LIBPATH ${LIBDIR}/openvdb/lib)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_ALEMBIC)
|
||||||
|
set(ALEMBIC_ROOT_DIR ${LIBDIR}/alembic)
|
||||||
|
find_package(Alembic)
|
||||||
|
|
||||||
|
if(WITH_ALEMBIC_HDF5)
|
||||||
|
set(HDF5_ROOT_DIR ${LIBDIR}/hdf5)
|
||||||
|
find_package(HDF5)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT ALEMBIC_FOUND OR (WITH_ALEMBIC_HDF5 AND NOT HDF5_FOUND))
|
||||||
|
set(WITH_ALEMBIC OFF)
|
||||||
|
set(WITH_ALEMBIC_HDF5 OFF)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WITH_MOD_CLOTH_ELTOPO)
|
if(WITH_MOD_CLOTH_ELTOPO)
|
||||||
set(LAPACK ${LIBDIR}/lapack)
|
set(LAPACK ${LIBDIR}/lapack)
|
||||||
# set(LAPACK_INCLUDE_DIR ${LAPACK}/include)
|
# set(LAPACK_INCLUDE_DIR ${LAPACK}/include)
|
||||||
@ -1959,6 +1998,21 @@ elseif(WIN32)
|
|||||||
set(OPENVDB_DEFINITIONS)
|
set(OPENVDB_DEFINITIONS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_ALEMBIC)
|
||||||
|
set(ALEMBIC_ROOT_DIR ${LIBDIR}/alembic)
|
||||||
|
find_package_wrapper(Alembic)
|
||||||
|
|
||||||
|
if(WITH_ALEMBIC_HDF5)
|
||||||
|
set(HDF5_ROOT_DIR ${LIBDIR}/hdf5)
|
||||||
|
find_package_wrapper(HDF5)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT ALEMBIC_FOUND OR (WITH_ALEMBIC_HDF5 AND NOT HDF5_FOUND))
|
||||||
|
set(WITH_ALEMBIC OFF)
|
||||||
|
set(WITH_ALEMBIC_HDF5 OFF)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
set(PLATFORM_LINKFLAGS "-Xlinker --stack=2097152")
|
set(PLATFORM_LINKFLAGS "-Xlinker --stack=2097152")
|
||||||
|
|
||||||
## DISABLE - causes linking errors
|
## DISABLE - causes linking errors
|
||||||
@ -2043,6 +2097,20 @@ elseif(APPLE)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_ALEMBIC)
|
||||||
|
set(ALEMBIC_ROOT_DIR ${LIBDIR}/alembic)
|
||||||
|
find_package(Alembic)
|
||||||
|
if(WITH_ALEMBIC_HDF5)
|
||||||
|
set(HDF5_ROOT_DIR ${LIBDIR}/hdf5)
|
||||||
|
find_package(HDF5)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT ALEMBIC_FOUND OR (WITH_ALEMBIC_HDF5 AND NOT HDF5_FOUND))
|
||||||
|
set(WITH_ALEMBIC OFF)
|
||||||
|
set(WITH_ALEMBIC_HDF5 OFF)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WITH_OPENSUBDIV)
|
if(WITH_OPENSUBDIV)
|
||||||
set(OPENSUBDIV ${LIBDIR}/opensubdiv)
|
set(OPENSUBDIV ${LIBDIR}/opensubdiv)
|
||||||
set(OPENSUBDIV_LIBPATH ${OPENSUBDIV}/lib)
|
set(OPENSUBDIV_LIBPATH ${OPENSUBDIV}/lib)
|
||||||
@ -3215,6 +3283,7 @@ if(FIRST_RUN)
|
|||||||
info_cfg_option(WITH_FREESTYLE)
|
info_cfg_option(WITH_FREESTYLE)
|
||||||
info_cfg_option(WITH_OPENCOLORIO)
|
info_cfg_option(WITH_OPENCOLORIO)
|
||||||
info_cfg_option(WITH_OPENVDB)
|
info_cfg_option(WITH_OPENVDB)
|
||||||
|
info_cfg_option(WITH_ALEMBIC)
|
||||||
|
|
||||||
info_cfg_text("Compiler Options:")
|
info_cfg_text("Compiler Options:")
|
||||||
info_cfg_option(WITH_BUILDINFO)
|
info_cfg_option(WITH_BUILDINFO)
|
||||||
|
@ -29,13 +29,13 @@ getopt \
|
|||||||
ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,ver-osd:,ver-openvdb:,\
|
ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,ver-osd:,ver-openvdb:,\
|
||||||
force-all,force-python,force-numpy,force-boost,\
|
force-all,force-python,force-numpy,force-boost,\
|
||||||
force-ocio,force-openexr,force-oiio,force-llvm,force-osl,force-osd,force-openvdb,\
|
force-ocio,force-openexr,force-oiio,force-llvm,force-osl,force-osd,force-openvdb,\
|
||||||
force-ffmpeg,force-opencollada,\
|
force-ffmpeg,force-opencollada,force-alembic,\
|
||||||
build-all,build-python,build-numpy,build-boost,\
|
build-all,build-python,build-numpy,build-boost,\
|
||||||
build-ocio,build-openexr,build-oiio,build-llvm,build-osl,build-osd,build-openvdb,\
|
build-ocio,build-openexr,build-oiio,build-llvm,build-osl,build-osd,build-openvdb,\
|
||||||
build-ffmpeg,build-opencollada,\
|
build-ffmpeg,build-opencollada,build-alembic,\
|
||||||
skip-python,skip-numpy,skip-boost,\
|
skip-python,skip-numpy,skip-boost,\
|
||||||
skip-ocio,skip-openexr,skip-oiio,skip-llvm,skip-osl,skip-osd,skip-openvdb,\
|
skip-ocio,skip-openexr,skip-oiio,skip-llvm,skip-osl,skip-osd,skip-openvdb,\
|
||||||
skip-ffmpeg,skip-opencollada \
|
skip-ffmpeg,skip-opencollada,skip-alembic \
|
||||||
-- "$@" \
|
-- "$@" \
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -167,6 +167,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
|
|||||||
--build-openvdb
|
--build-openvdb
|
||||||
Force the build of OpenVDB.
|
Force the build of OpenVDB.
|
||||||
|
|
||||||
|
--build-alembic
|
||||||
|
Force the build of Alembic.
|
||||||
|
|
||||||
--build-opencollada
|
--build-opencollada
|
||||||
Force the build of OpenCOLLADA.
|
Force the build of OpenCOLLADA.
|
||||||
|
|
||||||
@ -216,6 +219,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
|
|||||||
--force-openvdb
|
--force-openvdb
|
||||||
Force the rebuild of OpenVDB.
|
Force the rebuild of OpenVDB.
|
||||||
|
|
||||||
|
--force-alembic
|
||||||
|
Force the rebuild of Alembic.
|
||||||
|
|
||||||
--force-opencollada
|
--force-opencollada
|
||||||
Force the rebuild of OpenCOLLADA.
|
Force the rebuild of OpenCOLLADA.
|
||||||
|
|
||||||
@ -258,6 +264,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
|
|||||||
--skip-openvdb
|
--skip-openvdb
|
||||||
Unconditionally skip OpenVDB installation/building.
|
Unconditionally skip OpenVDB installation/building.
|
||||||
|
|
||||||
|
--skip-alembic
|
||||||
|
Unconditionally skip Alembic installation/building.
|
||||||
|
|
||||||
--skip-opencollada
|
--skip-opencollada
|
||||||
Unconditionally skip OpenCOLLADA installation/building.
|
Unconditionally skip OpenCOLLADA installation/building.
|
||||||
|
|
||||||
@ -343,6 +352,13 @@ OPENVDB_FORCE_BUILD=false
|
|||||||
OPENVDB_FORCE_REBUILD=false
|
OPENVDB_FORCE_REBUILD=false
|
||||||
OPENVDB_SKIP=false
|
OPENVDB_SKIP=false
|
||||||
|
|
||||||
|
# Alembic needs to be compiled for now
|
||||||
|
ALEMBIC_VERSION="1.6.0"
|
||||||
|
ALEMBIC_VERSION_MIN=$ALEMBIC_VERSION
|
||||||
|
ALEMBIC_FORCE_BUILD=false
|
||||||
|
ALEMBIC_FORCE_REBUILD=false
|
||||||
|
ALEMBIC_SKIP=false
|
||||||
|
|
||||||
# Version??
|
# Version??
|
||||||
OPENCOLLADA_VERSION="1.3"
|
OPENCOLLADA_VERSION="1.3"
|
||||||
OPENCOLLADA_FORCE_BUILD=false
|
OPENCOLLADA_FORCE_BUILD=false
|
||||||
@ -525,6 +541,7 @@ while true; do
|
|||||||
OPENVDB_FORCE_BUILD=true
|
OPENVDB_FORCE_BUILD=true
|
||||||
OPENCOLLADA_FORCE_BUILD=true
|
OPENCOLLADA_FORCE_BUILD=true
|
||||||
FFMPEG_FORCE_BUILD=true
|
FFMPEG_FORCE_BUILD=true
|
||||||
|
ALEMBIC_FORCE_BUILD=true
|
||||||
shift; continue
|
shift; continue
|
||||||
;;
|
;;
|
||||||
--build-python)
|
--build-python)
|
||||||
@ -567,6 +584,9 @@ while true; do
|
|||||||
--build-ffmpeg)
|
--build-ffmpeg)
|
||||||
FFMPEG_FORCE_BUILD=true; shift; continue
|
FFMPEG_FORCE_BUILD=true; shift; continue
|
||||||
;;
|
;;
|
||||||
|
--build-alembic)
|
||||||
|
ALEMBIC_FORCE_BUILD=true; shift; continue
|
||||||
|
;;
|
||||||
--force-all)
|
--force-all)
|
||||||
PYTHON_FORCE_REBUILD=true
|
PYTHON_FORCE_REBUILD=true
|
||||||
NUMPY_FORCE_REBUILD=true
|
NUMPY_FORCE_REBUILD=true
|
||||||
@ -580,6 +600,7 @@ while true; do
|
|||||||
OPENVDB_FORCE_REBUILD=true
|
OPENVDB_FORCE_REBUILD=true
|
||||||
OPENCOLLADA_FORCE_REBUILD=true
|
OPENCOLLADA_FORCE_REBUILD=true
|
||||||
FFMPEG_FORCE_REBUILD=true
|
FFMPEG_FORCE_REBUILD=true
|
||||||
|
ALEMBIC_FORCE_REBUILD=true
|
||||||
shift; continue
|
shift; continue
|
||||||
;;
|
;;
|
||||||
--force-python)
|
--force-python)
|
||||||
@ -620,6 +641,9 @@ while true; do
|
|||||||
--force-ffmpeg)
|
--force-ffmpeg)
|
||||||
FFMPEG_FORCE_REBUILD=true; shift; continue
|
FFMPEG_FORCE_REBUILD=true; shift; continue
|
||||||
;;
|
;;
|
||||||
|
--force-alembic)
|
||||||
|
ALEMBIC_FORCE_REBUILD=true; shift; continue
|
||||||
|
;;
|
||||||
--skip-python)
|
--skip-python)
|
||||||
PYTHON_SKIP=true; shift; continue
|
PYTHON_SKIP=true; shift; continue
|
||||||
;;
|
;;
|
||||||
@ -656,6 +680,9 @@ while true; do
|
|||||||
--skip-ffmpeg)
|
--skip-ffmpeg)
|
||||||
FFMPEG_SKIP=true; shift; continue
|
FFMPEG_SKIP=true; shift; continue
|
||||||
;;
|
;;
|
||||||
|
--skip-alembic)
|
||||||
|
ALEMBIC_SKIP=true; shift; continue
|
||||||
|
;;
|
||||||
--)
|
--)
|
||||||
# no more arguments to parse
|
# no more arguments to parse
|
||||||
break
|
break
|
||||||
@ -683,7 +710,7 @@ NUMPY_SOURCE=( "http://sourceforge.net/projects/numpy/files/NumPy/$NUMPY_VERSION
|
|||||||
|
|
||||||
_boost_version_nodots=`echo "$BOOST_VERSION" | sed -r 's/\./_/g'`
|
_boost_version_nodots=`echo "$BOOST_VERSION" | sed -r 's/\./_/g'`
|
||||||
BOOST_SOURCE=( "http://sourceforge.net/projects/boost/files/boost/$BOOST_VERSION/boost_$_boost_version_nodots.tar.bz2/download" )
|
BOOST_SOURCE=( "http://sourceforge.net/projects/boost/files/boost/$BOOST_VERSION/boost_$_boost_version_nodots.tar.bz2/download" )
|
||||||
BOOST_BUILD_MODULES="--with-system --with-filesystem --with-thread --with-regex --with-locale --with-date_time --with-wave --with-iostreams"
|
BOOST_BUILD_MODULES="--with-system --with-filesystem --with-thread --with-regex --with-locale --with-date_time --with-wave --with-iostreams --with-python --with-program_options"
|
||||||
|
|
||||||
OCIO_SOURCE=( "https://github.com/imageworks/OpenColorIO/tarball/v$OCIO_VERSION" )
|
OCIO_SOURCE=( "https://github.com/imageworks/OpenColorIO/tarball/v$OCIO_VERSION" )
|
||||||
|
|
||||||
@ -727,6 +754,12 @@ OPENVDB_SOURCE=( "https://github.com/dreamworksanimation/openvdb/archive/v${OPEN
|
|||||||
#~ OPENVDB_SOURCE_REPO_UID="404659fffa659da075d1c9416e4fc939139a84ee"
|
#~ OPENVDB_SOURCE_REPO_UID="404659fffa659da075d1c9416e4fc939139a84ee"
|
||||||
#~ OPENVDB_SOURCE_REPO_BRANCH="dev"
|
#~ OPENVDB_SOURCE_REPO_BRANCH="dev"
|
||||||
|
|
||||||
|
ALEMBIC_USE_REPO=false
|
||||||
|
ALEMBIC_SOURCE=( "https://github.com/alembic/alembic/archive/${ALEMBIC_VERSION}.tar.gz" )
|
||||||
|
# ALEMBIC_SOURCE_REPO=( "https://github.com/alembic/alembic.git" )
|
||||||
|
# ALEMBIC_SOURCE_REPO_UID="e6c90d4faa32c4550adeaaf3f556dad4b73a92bb"
|
||||||
|
# ALEMBIC_SOURCE_REPO_BRANCH="master"
|
||||||
|
|
||||||
OPENCOLLADA_SOURCE=( "https://github.com/KhronosGroup/OpenCOLLADA.git" )
|
OPENCOLLADA_SOURCE=( "https://github.com/KhronosGroup/OpenCOLLADA.git" )
|
||||||
OPENCOLLADA_REPO_UID="3335ac164e68b2512a40914b14c74db260e6ff7d"
|
OPENCOLLADA_REPO_UID="3335ac164e68b2512a40914b14c74db260e6ff7d"
|
||||||
OPENCOLLADA_REPO_BRANCH="master"
|
OPENCOLLADA_REPO_BRANCH="master"
|
||||||
@ -767,7 +800,8 @@ You may also want to build them yourself (optional ones are [between brackets]):
|
|||||||
* [OpenShadingLanguage $OSL_VERSION_MIN] (from $OSL_SOURCE_REPO, branch $OSL_SOURCE_REPO_BRANCH, commit $OSL_SOURCE_REPO_UID).
|
* [OpenShadingLanguage $OSL_VERSION_MIN] (from $OSL_SOURCE_REPO, branch $OSL_SOURCE_REPO_BRANCH, commit $OSL_SOURCE_REPO_UID).
|
||||||
* [OpenSubDiv $OSD_VERSION_MIN] (from $OSD_SOURCE_REPO, branch $OSD_SOURCE_REPO_BRANCH, commit $OSD_SOURCE_REPO_UID).
|
* [OpenSubDiv $OSD_VERSION_MIN] (from $OSD_SOURCE_REPO, branch $OSD_SOURCE_REPO_BRANCH, commit $OSD_SOURCE_REPO_UID).
|
||||||
* [OpenVDB $OPENVDB_VERSION_MIN] (from $OPENVDB_SOURCE), [Blosc $OPENVDB_BLOSC_VERSION] (from $OPENVDB_BLOSC_SOURCE).
|
* [OpenVDB $OPENVDB_VERSION_MIN] (from $OPENVDB_SOURCE), [Blosc $OPENVDB_BLOSC_VERSION] (from $OPENVDB_BLOSC_SOURCE).
|
||||||
* [OpenCollada] (from $OPENCOLLADA_SOURCE, branch $OPENCOLLADA_REPO_BRANCH, commit $OPENCOLLADA_REPO_UID).\""
|
* [OpenCollada] (from $OPENCOLLADA_SOURCE, branch $OPENCOLLADA_REPO_BRANCH, commit $OPENCOLLADA_REPO_UID).
|
||||||
|
* [Alembic $ALEMBIC_VERSION] (from $ALEMBIC_SOURCE).\""
|
||||||
|
|
||||||
if [ "$DO_SHOW_DEPS" = true ]; then
|
if [ "$DO_SHOW_DEPS" = true ]; then
|
||||||
PRINT ""
|
PRINT ""
|
||||||
@ -1118,7 +1152,7 @@ compile_Boost() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# To be changed each time we make edits that would modify the compiled result!
|
# To be changed each time we make edits that would modify the compiled result!
|
||||||
boost_magic=10
|
boost_magic=11
|
||||||
|
|
||||||
_init_boost
|
_init_boost
|
||||||
|
|
||||||
@ -2138,6 +2172,102 @@ compile_OPENVDB() {
|
|||||||
run_ldconfig "openvdb"
|
run_ldconfig "openvdb"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#### Build Alembic ####
|
||||||
|
_init_alembic() {
|
||||||
|
_src=$SRC/alembic-$ALEMBIC_VERSION
|
||||||
|
_git=false
|
||||||
|
_inst=$INST/alembic-$ALEMBIC_VERSION
|
||||||
|
_inst_shortcut=$INST/alembic
|
||||||
|
}
|
||||||
|
|
||||||
|
clean_ALEMBIC() {
|
||||||
|
_init_alembic
|
||||||
|
_clean
|
||||||
|
}
|
||||||
|
|
||||||
|
compile_ALEMBIC() {
|
||||||
|
if [ "$NO_BUILD" = true ]; then
|
||||||
|
WARNING "--no-build enabled, Alembic will not be compiled!"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
compile_HDF5
|
||||||
|
PRINT ""
|
||||||
|
|
||||||
|
# To be changed each time we make edits that would modify the compiled result!
|
||||||
|
alembic_magic=2
|
||||||
|
_init_alembic
|
||||||
|
|
||||||
|
# Clean install if needed!
|
||||||
|
magic_compile_check alembic-$ALEMBIC_VERSION $alembic_magic
|
||||||
|
if [ $? -eq 1 -o "$ALEMBIC_FORCE_REBUILD" = true ]; then
|
||||||
|
clean_ALEMBIC
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d $_inst ]; then
|
||||||
|
INFO "Building Alembic-$ALEMBIC_VERSION"
|
||||||
|
|
||||||
|
prepare_opt
|
||||||
|
|
||||||
|
if [ ! -d $_src -o true ]; then
|
||||||
|
mkdir -p $SRC
|
||||||
|
download ALEMBIC_SOURCE[@] "$_src.tar.gz"
|
||||||
|
|
||||||
|
INFO "Unpacking Alembic-$ALEMBIC_VERSION"
|
||||||
|
tar -C $SRC -xf $_src.tar.gz
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd $_src
|
||||||
|
|
||||||
|
cmake_d="-D CMAKE_INSTALL_PREFIX=$_inst"
|
||||||
|
|
||||||
|
if [ -d $INST/boost ]; then
|
||||||
|
cmake_d="$cmake_d -D BOOST_ROOT=$INST/boost"
|
||||||
|
cmake_d="$cmake_d -D USE_STATIC_BOOST=ON"
|
||||||
|
else
|
||||||
|
cmake_d="$cmake_d -D USE_STATIC_BOOST=OFF"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$_with_built_openexr" = true ]; then
|
||||||
|
cmake_d="$cmake_d -D ILMBASE_ROOT=$INST/openexr"
|
||||||
|
cmake_d="$cmake_d -D USE_ARNOLD=OFF"
|
||||||
|
cmake_d="$cmake_d -D USE_BINARIES=OFF"
|
||||||
|
cmake_d="$cmake_d -D USE_EXAMPLES=OFF"
|
||||||
|
cmake_d="$cmake_d -D USE_HDF5=OFF"
|
||||||
|
cmake_d="$cmake_d -D USE_MAYA=OFF"
|
||||||
|
cmake_d="$cmake_d -D USE_PRMAN=OFF"
|
||||||
|
cmake_d="$cmake_d -D USE_PYALEMBIC=OFF"
|
||||||
|
cmake_d="$cmake_d -D USE_STATIC_HDF5=OFF"
|
||||||
|
cmake_d="$cmake_d -D ALEMBIC_ILMBASE_LINK_STATIC=OFF"
|
||||||
|
cmake_d="$cmake_d -D ALEMBIC_SHARED_LIBS=OFF"
|
||||||
|
cmake_d="$cmake_d -D ALEMBIC_LIB_USES_BOOST=ON"
|
||||||
|
cmake_d="$cmake_d -D ALEMBIC_LIB_USES_TR1=OFF"
|
||||||
|
INFO "ILMBASE_ROOT=$INST/openexr"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cmake $cmake_d ./
|
||||||
|
make -j$THREADS install
|
||||||
|
make clean
|
||||||
|
|
||||||
|
if [ -d $_inst ]; then
|
||||||
|
_create_inst_shortcut
|
||||||
|
else
|
||||||
|
ERROR "Alembic-$ALEMBIC_VERSION failed to compile, exiting"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
magic_compile_set alembic-$ALEMBIC_VERSION $alembic_magic
|
||||||
|
|
||||||
|
cd $CWD
|
||||||
|
INFO "Done compiling Alembic-$ALEMBIC_VERSION!"
|
||||||
|
else
|
||||||
|
INFO "Own Alembic-$ALEMBIC_VERSION is up to date, nothing to do!"
|
||||||
|
INFO "If you want to force rebuild of this lib, use the --force-alembic option."
|
||||||
|
fi
|
||||||
|
|
||||||
|
run_ldconfig "alembic"
|
||||||
|
}
|
||||||
|
|
||||||
#### Build OpenCOLLADA ####
|
#### Build OpenCOLLADA ####
|
||||||
_init_opencollada() {
|
_init_opencollada() {
|
||||||
_src=$SRC/OpenCOLLADA-$OPENCOLLADA_VERSION
|
_src=$SRC/OpenCOLLADA-$OPENCOLLADA_VERSION
|
||||||
@ -2746,6 +2876,17 @@ install_DEB() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
PRINT ""
|
||||||
|
if [ "$ALEMBIC_SKIP" = true ]; then
|
||||||
|
WARNING "Skipping Alembic installation, as requested..."
|
||||||
|
elif [ "$ALEMBIC_FORCE_BUILD" = true ]; then
|
||||||
|
INFO "Forced Alembic building, as requested..."
|
||||||
|
compile_ALEMBIC
|
||||||
|
else
|
||||||
|
# No package currently, only HDF5!
|
||||||
|
compile_ALEMBIC
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
if [ "$WITH_OPENCOLLADA" = true ]; then
|
if [ "$WITH_OPENCOLLADA" = true ]; then
|
||||||
_do_compile_collada=false
|
_do_compile_collada=false
|
||||||
@ -3283,6 +3424,17 @@ install_RPM() {
|
|||||||
compile_OPENVDB
|
compile_OPENVDB
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
PRINT ""
|
||||||
|
if [ "$ALEMBIC_SKIP" = true ]; then
|
||||||
|
WARNING "Skipping Alembic installation, as requested..."
|
||||||
|
elif [ "$ALEMBIC_FORCE_BUILD" = true ]; then
|
||||||
|
INFO "Forced Alembic building, as requested..."
|
||||||
|
compile_ALEMBIC
|
||||||
|
else
|
||||||
|
# No package currently!
|
||||||
|
compile_ALEMBIC
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
if [ "$WITH_OPENCOLLADA" = true ]; then
|
if [ "$WITH_OPENCOLLADA" = true ]; then
|
||||||
PRINT ""
|
PRINT ""
|
||||||
@ -3693,6 +3845,16 @@ install_ARCH() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
PRINT ""
|
||||||
|
if [ "$ALEMBIC_SKIP" = true ]; then
|
||||||
|
WARNING "Skipping Alembic installation, as requested..."
|
||||||
|
elif [ "$ALEMBIC_FORCE_BUILD" = true ]; then
|
||||||
|
INFO "Forced Alembic building, as requested..."
|
||||||
|
compile_ALEMBIC
|
||||||
|
else
|
||||||
|
compile_ALEMBIC
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
if [ "$WITH_OPENCOLLADA" = true ]; then
|
if [ "$WITH_OPENCOLLADA" = true ]; then
|
||||||
PRINT ""
|
PRINT ""
|
||||||
@ -4000,7 +4162,7 @@ print_info() {
|
|||||||
|
|
||||||
_buildargs="-U *SNDFILE* -U *PYTHON* -U *BOOST* -U *Boost*"
|
_buildargs="-U *SNDFILE* -U *PYTHON* -U *BOOST* -U *Boost*"
|
||||||
_buildargs="$_buildargs -U *OPENCOLORIO* -U *OPENEXR* -U *OPENIMAGEIO* -U *LLVM* -U *CYCLES*"
|
_buildargs="$_buildargs -U *OPENCOLORIO* -U *OPENEXR* -U *OPENIMAGEIO* -U *LLVM* -U *CYCLES*"
|
||||||
_buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *COLLADA* -U *FFMPEG*"
|
_buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *COLLADA* -U *FFMPEG* -U *ALEMBIC*"
|
||||||
|
|
||||||
_1="-D WITH_CODEC_SNDFILE=ON"
|
_1="-D WITH_CODEC_SNDFILE=ON"
|
||||||
PRINT " $_1"
|
PRINT " $_1"
|
||||||
@ -4106,6 +4268,17 @@ print_info() {
|
|||||||
_buildargs="$_buildargs $_1"
|
_buildargs="$_buildargs $_1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$ALEMBIC_SKIP" = false ]; then
|
||||||
|
_1="-D WITH_ALEMBIC=ON"
|
||||||
|
PRINT " $_1"
|
||||||
|
_buildargs="$_buildargs $_1"
|
||||||
|
if [ -d $INST/alembic ]; then
|
||||||
|
_1="-D ALEMBIC_ROOT_DIR=$INST/alembic"
|
||||||
|
PRINT " $_1"
|
||||||
|
_buildargs="$_buildargs $_1"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$NO_SYSTEM_GLEW" = true ]; then
|
if [ "$NO_SYSTEM_GLEW" = true ]; then
|
||||||
_1="-D WITH_SYSTEM_GLEW=OFF"
|
_1="-D WITH_SYSTEM_GLEW=OFF"
|
||||||
PRINT " $_1"
|
PRINT " $_1"
|
||||||
|
70
build_files/cmake/Modules/FindAlembic.cmake
Normal file
70
build_files/cmake/Modules/FindAlembic.cmake
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
# - Find Alembic library
|
||||||
|
# Find the native Alembic includes and libraries
|
||||||
|
# This module defines
|
||||||
|
# ALEMBIC_INCLUDE_DIRS, where to find Alembic headers, Set when
|
||||||
|
# ALEMBIC_INCLUDE_DIR is found.
|
||||||
|
# ALEMBIC_LIBRARIES, libraries to link against to use Alembic.
|
||||||
|
# ALEMBIC_ROOT_DIR, The base directory to search for Alembic.
|
||||||
|
# This can also be an environment variable.
|
||||||
|
# ALEMBIC_FOUND, If false, do not try to use Alembic.
|
||||||
|
#
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# Copyright 2016 Blender Foundation.
|
||||||
|
#
|
||||||
|
# Distributed under the OSI-approved BSD License (the "License");
|
||||||
|
# see accompanying file Copyright.txt for details.
|
||||||
|
#
|
||||||
|
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||||
|
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
# See the License for more information.
|
||||||
|
#=============================================================================
|
||||||
|
|
||||||
|
# If ALEMBIC_ROOT_DIR was defined in the environment, use it.
|
||||||
|
IF(NOT ALEMBIC_ROOT_DIR AND NOT $ENV{ALEMBIC_ROOT_DIR} STREQUAL "")
|
||||||
|
SET(ALEMBIC_ROOT_DIR $ENV{ALEMBIC_ROOT_DIR})
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
SET(_alembic_SEARCH_DIRS
|
||||||
|
${ALEMBIC_ROOT_DIR}
|
||||||
|
/usr/local
|
||||||
|
/sw # Fink
|
||||||
|
/opt/local # DarwinPorts
|
||||||
|
/opt/csw # Blastwave
|
||||||
|
/opt/lib/alembic
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_PATH(ALEMBIC_INCLUDE_DIR
|
||||||
|
NAMES
|
||||||
|
Alembic/Abc/All.h
|
||||||
|
HINTS
|
||||||
|
${_alembic_SEARCH_DIRS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
include
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY(ALEMBIC_LIBRARY
|
||||||
|
NAMES
|
||||||
|
Alembic
|
||||||
|
HINTS
|
||||||
|
${_alembic_SEARCH_DIRS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
lib64 lib lib/static
|
||||||
|
)
|
||||||
|
|
||||||
|
# handle the QUIETLY and REQUIRED arguments and set ALEMBIC_FOUND to TRUE if
|
||||||
|
# all listed variables are TRUE
|
||||||
|
INCLUDE(FindPackageHandleStandardArgs)
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(ALEMBIC DEFAULT_MSG ALEMBIC_LIBRARY ALEMBIC_INCLUDE_DIR)
|
||||||
|
|
||||||
|
IF(ALEMBIC_FOUND)
|
||||||
|
SET(ALEMBIC_LIBRARIES ${ALEMBIC_LIBRARY})
|
||||||
|
SET(ALEMBIC_INCLUDE_DIRS ${ALEMBIC_INCLUDE_DIR})
|
||||||
|
ENDIF(ALEMBIC_FOUND)
|
||||||
|
|
||||||
|
MARK_AS_ADVANCED(
|
||||||
|
ALEMBIC_INCLUDE_DIR
|
||||||
|
ALEMBIC_LIBRARY
|
||||||
|
)
|
||||||
|
|
||||||
|
UNSET(_alembic_SEARCH_DIRS)
|
69
build_files/cmake/Modules/FindHDF5.cmake
Normal file
69
build_files/cmake/Modules/FindHDF5.cmake
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# - Find HDF5 library
|
||||||
|
# Find the native HDF5 includes and libraries
|
||||||
|
# This module defines
|
||||||
|
# HDF5_INCLUDE_DIRS, where to find hdf5.h, Set when HDF5_INCLUDE_DIR is found.
|
||||||
|
# HDF5_LIBRARIES, libraries to link against to use HDF5.
|
||||||
|
# HDF5_ROOT_DIR, The base directory to search for HDF5.
|
||||||
|
# This can also be an environment variable.
|
||||||
|
# HDF5_FOUND, If false, do not try to use HDF5.
|
||||||
|
#
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# Copyright 2016 Blender Foundation.
|
||||||
|
#
|
||||||
|
# Distributed under the OSI-approved BSD License (the "License");
|
||||||
|
# see accompanying file Copyright.txt for details.
|
||||||
|
#
|
||||||
|
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||||
|
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
# See the License for more information.
|
||||||
|
#=============================================================================
|
||||||
|
|
||||||
|
# If HDF5_ROOT_DIR was defined in the environment, use it.
|
||||||
|
IF(NOT HDF5_ROOT_DIR AND NOT $ENV{HDF5_ROOT_DIR} STREQUAL "")
|
||||||
|
SET(HDF5_ROOT_DIR $ENV{HDF5_ROOT_DIR})
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
SET(_hdf5_SEARCH_DIRS
|
||||||
|
${HDF5_ROOT_DIR}
|
||||||
|
/usr/local
|
||||||
|
/sw # Fink
|
||||||
|
/opt/local # DarwinPorts
|
||||||
|
/opt/csw # Blastwave
|
||||||
|
/opt/lib/hdf5
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY(HDF5_LIBRARY
|
||||||
|
NAMES
|
||||||
|
hdf5
|
||||||
|
HINTS
|
||||||
|
${_hdf5_SEARCH_DIRS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
lib64 lib
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_PATH(HDF5_INCLUDE_DIR
|
||||||
|
NAMES
|
||||||
|
hdf5.h
|
||||||
|
HINTS
|
||||||
|
${_hdf5_SEARCH_DIRS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
include
|
||||||
|
)
|
||||||
|
|
||||||
|
# handle the QUIETLY and REQUIRED arguments and set HDF5_FOUND to TRUE if
|
||||||
|
# all listed variables are TRUE
|
||||||
|
INCLUDE(FindPackageHandleStandardArgs)
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(HDF5 DEFAULT_MSG HDF5_LIBRARY HDF5_INCLUDE_DIR)
|
||||||
|
|
||||||
|
IF(HDF5_FOUND)
|
||||||
|
SET(HDF5_LIBRARIES ${HDF5_LIBRARY})
|
||||||
|
SET(HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIR})
|
||||||
|
ENDIF(HDF5_FOUND)
|
||||||
|
|
||||||
|
MARK_AS_ADVANCED(
|
||||||
|
HDF5_INCLUDE_DIR
|
||||||
|
HDF5_LIBRARY
|
||||||
|
)
|
||||||
|
|
||||||
|
UNSET(_hdf5_SEARCH_DIRS)
|
@ -4,6 +4,7 @@
|
|||||||
# cmake -C../blender/build_files/cmake/config/blender_full.cmake ../blender
|
# cmake -C../blender/build_files/cmake/config/blender_full.cmake ../blender
|
||||||
#
|
#
|
||||||
|
|
||||||
|
set(WITH_ALEMBIC ON CACHE BOOL "" FORCE)
|
||||||
set(WITH_BUILDINFO ON CACHE BOOL "" FORCE)
|
set(WITH_BUILDINFO ON CACHE BOOL "" FORCE)
|
||||||
set(WITH_BULLET ON CACHE BOOL "" FORCE)
|
set(WITH_BULLET ON CACHE BOOL "" FORCE)
|
||||||
set(WITH_CODEC_AVI ON CACHE BOOL "" FORCE)
|
set(WITH_CODEC_AVI ON CACHE BOOL "" FORCE)
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
set(WITH_INSTALL_PORTABLE ON CACHE BOOL "" FORCE)
|
set(WITH_INSTALL_PORTABLE ON CACHE BOOL "" FORCE)
|
||||||
set(WITH_SYSTEM_GLEW ON CACHE BOOL "" FORCE)
|
set(WITH_SYSTEM_GLEW ON CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
|
set(WITH_ALEMBIC OFF CACHE BOOL "" FORCE)
|
||||||
set(WITH_BUILDINFO OFF CACHE BOOL "" FORCE)
|
set(WITH_BUILDINFO OFF CACHE BOOL "" FORCE)
|
||||||
set(WITH_BULLET OFF CACHE BOOL "" FORCE)
|
set(WITH_BULLET OFF CACHE BOOL "" FORCE)
|
||||||
set(WITH_CODEC_AVI OFF CACHE BOOL "" FORCE)
|
set(WITH_CODEC_AVI OFF CACHE BOOL "" FORCE)
|
||||||
|
@ -32,3 +32,4 @@ set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
|
|||||||
set(WITH_INTERNATIONAL OFF CACHE BOOL "" FORCE)
|
set(WITH_INTERNATIONAL OFF CACHE BOOL "" FORCE)
|
||||||
set(WITH_BULLET OFF CACHE BOOL "" FORCE)
|
set(WITH_BULLET OFF CACHE BOOL "" FORCE)
|
||||||
set(WITH_OPENVDB OFF CACHE BOOL "" FORCE)
|
set(WITH_OPENVDB OFF CACHE BOOL "" FORCE)
|
||||||
|
set(WITH_ALEMBIC OFF CACHE BOOL "" FORCE)
|
||||||
|
@ -333,6 +333,11 @@ function(SETUP_LIBDIRS)
|
|||||||
link_directories(${LLVM_LIBPATH})
|
link_directories(${LLVM_LIBPATH})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_ALEMBIC)
|
||||||
|
link_directories(${ALEMBIC_LIBPATH})
|
||||||
|
link_directories(${HDF5_LIBPATH})
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WIN32 AND NOT UNIX)
|
if(WIN32 AND NOT UNIX)
|
||||||
link_directories(${PTHREADS_LIBPATH})
|
link_directories(${PTHREADS_LIBPATH})
|
||||||
endif()
|
endif()
|
||||||
@ -434,6 +439,9 @@ function(setup_liblinks
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(${target} ${JPEG_LIBRARIES})
|
target_link_libraries(${target} ${JPEG_LIBRARIES})
|
||||||
|
if(WITH_ALEMBIC)
|
||||||
|
target_link_libraries(${target} ${ALEMBIC_LIBRARIES} ${HDF5_LIBRARIES})
|
||||||
|
endif()
|
||||||
if(WITH_IMAGE_OPENEXR)
|
if(WITH_IMAGE_OPENEXR)
|
||||||
target_link_libraries(${target} ${OPENEXR_LIBRARIES})
|
target_link_libraries(${target} ${OPENEXR_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
@ -607,6 +615,7 @@ function(SETUP_BLENDER_SORTED_LIBS)
|
|||||||
bf_imbuf_openimageio
|
bf_imbuf_openimageio
|
||||||
bf_imbuf_dds
|
bf_imbuf_dds
|
||||||
bf_collada
|
bf_collada
|
||||||
|
bf_alembic
|
||||||
bf_intern_elbeem
|
bf_intern_elbeem
|
||||||
bf_intern_memutil
|
bf_intern_memutil
|
||||||
bf_intern_guardedalloc
|
bf_intern_guardedalloc
|
||||||
|
@ -158,6 +158,13 @@ def write_sysinfo(filepath):
|
|||||||
else:
|
else:
|
||||||
output.write("Blender was built without OpenVDB support\n")
|
output.write("Blender was built without OpenVDB support\n")
|
||||||
|
|
||||||
|
alembic = bpy.app.alembic
|
||||||
|
output.write("Alembic: ")
|
||||||
|
if alembic.supported:
|
||||||
|
output.write("%s\n" % alembic.version_string)
|
||||||
|
else:
|
||||||
|
output.write("Blender was built without Alembic support\n")
|
||||||
|
|
||||||
if not bpy.app.build_options.sdl:
|
if not bpy.app.build_options.sdl:
|
||||||
output.write("SDL: Blender was built without SDL support\n")
|
output.write("SDL: Blender was built without SDL support\n")
|
||||||
|
|
||||||
|
@ -880,6 +880,19 @@ class ConstraintButtonsPanel:
|
|||||||
|
|
||||||
layout.operator("clip.constraint_to_fcurve")
|
layout.operator("clip.constraint_to_fcurve")
|
||||||
|
|
||||||
|
def TRANSFORM_CACHE(self, context, layout, con):
|
||||||
|
layout.label(text="Cache File Properties:")
|
||||||
|
box = layout.box()
|
||||||
|
box.template_cache_file(con, "cache_file")
|
||||||
|
|
||||||
|
cache_file = con.cache_file
|
||||||
|
|
||||||
|
layout.label(text="Constraint Properties:")
|
||||||
|
box = layout.box()
|
||||||
|
|
||||||
|
if cache_file is not None:
|
||||||
|
box.prop_search(con, "object_path", cache_file, "object_paths")
|
||||||
|
|
||||||
def SCRIPT(self, context, layout, con):
|
def SCRIPT(self, context, layout, con):
|
||||||
layout.label("Blender 2.6 doesn't support python constraints yet")
|
layout.label("Blender 2.6 doesn't support python constraints yet")
|
||||||
|
|
||||||
|
@ -181,6 +181,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
|||||||
layout.prop(md, "cache_format")
|
layout.prop(md, "cache_format")
|
||||||
layout.prop(md, "filepath")
|
layout.prop(md, "filepath")
|
||||||
|
|
||||||
|
if md.cache_format == 'ABC':
|
||||||
|
layout.prop(md, "sub_object")
|
||||||
|
|
||||||
layout.label(text="Evaluation:")
|
layout.label(text="Evaluation:")
|
||||||
layout.prop(md, "factor", slider=True)
|
layout.prop(md, "factor", slider=True)
|
||||||
layout.prop(md, "deform_mode")
|
layout.prop(md, "deform_mode")
|
||||||
@ -215,6 +218,22 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
|||||||
row = split.row()
|
row = split.row()
|
||||||
row.prop(md, "flip_axis")
|
row.prop(md, "flip_axis")
|
||||||
|
|
||||||
|
def MESH_SEQUENCE_CACHE(self, layout, ob, md):
|
||||||
|
layout.label(text="Cache File Properties:")
|
||||||
|
box = layout.box()
|
||||||
|
box.template_cache_file(md, "cache_file")
|
||||||
|
|
||||||
|
cache_file = md.cache_file
|
||||||
|
|
||||||
|
layout.label(text="Modifier Properties:")
|
||||||
|
box = layout.box()
|
||||||
|
|
||||||
|
if cache_file is not None:
|
||||||
|
box.prop_search(md, "object_path", cache_file, "object_paths")
|
||||||
|
|
||||||
|
if ob.type == 'MESH':
|
||||||
|
box.row().prop(md, "read_data")
|
||||||
|
|
||||||
def CAST(self, layout, ob, md):
|
def CAST(self, layout, ob, md):
|
||||||
split = layout.split(percentage=0.25)
|
split = layout.split(percentage=0.25)
|
||||||
|
|
||||||
|
@ -158,6 +158,8 @@ class INFO_MT_file_import(Menu):
|
|||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
if bpy.app.build_options.collada:
|
if bpy.app.build_options.collada:
|
||||||
self.layout.operator("wm.collada_import", text="Collada (Default) (.dae)")
|
self.layout.operator("wm.collada_import", text="Collada (Default) (.dae)")
|
||||||
|
if bpy.app.build_options.alembic:
|
||||||
|
self.layout.operator("wm.alembic_import", text="Alembic (.abc)")
|
||||||
|
|
||||||
|
|
||||||
class INFO_MT_file_export(Menu):
|
class INFO_MT_file_export(Menu):
|
||||||
@ -167,6 +169,8 @@ class INFO_MT_file_export(Menu):
|
|||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
if bpy.app.build_options.collada:
|
if bpy.app.build_options.collada:
|
||||||
self.layout.operator("wm.collada_export", text="Collada (Default) (.dae)")
|
self.layout.operator("wm.collada_export", text="Collada (Default) (.dae)")
|
||||||
|
if bpy.app.build_options.alembic:
|
||||||
|
self.layout.operator("wm.alembic_export", text="Alembic (.abc)")
|
||||||
|
|
||||||
|
|
||||||
class INFO_MT_file_external_data(Menu):
|
class INFO_MT_file_external_data(Menu):
|
||||||
|
@ -31,6 +31,7 @@ set(SRC_DNA_INC
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_armature_types.h
|
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_armature_types.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_boid_types.h
|
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_boid_types.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_brush_types.h
|
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_brush_types.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_cachefile_types.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_camera_types.h
|
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_camera_types.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_cloth_types.h
|
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_cloth_types.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_color_types.h
|
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_color_types.h
|
||||||
@ -153,3 +154,6 @@ if(WITH_FREESTYLE)
|
|||||||
add_subdirectory(freestyle)
|
add_subdirectory(freestyle)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_ALEMBIC)
|
||||||
|
add_subdirectory(alembic)
|
||||||
|
endif()
|
||||||
|
110
source/blender/alembic/ABC_alembic.h
Normal file
110
source/blender/alembic/ABC_alembic.h
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ABC_ALEMBIC_H__
|
||||||
|
#define __ABC_ALEMBIC_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct bContext;
|
||||||
|
struct DerivedMesh;
|
||||||
|
struct ListBase;
|
||||||
|
struct Object;
|
||||||
|
struct Scene;
|
||||||
|
|
||||||
|
typedef struct AbcArchiveHandle AbcArchiveHandle;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ABC_ARCHIVE_OGAWA = 0,
|
||||||
|
ABC_ARCHIVE_HDF5 = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
int ABC_get_version(void);
|
||||||
|
|
||||||
|
struct AlembicExportParams {
|
||||||
|
double frame_start;
|
||||||
|
double frame_end;
|
||||||
|
|
||||||
|
double frame_step_xform;
|
||||||
|
double frame_step_shape;
|
||||||
|
|
||||||
|
double shutter_open;
|
||||||
|
double shutter_close;
|
||||||
|
|
||||||
|
/* bools */
|
||||||
|
unsigned int selected_only : 1;
|
||||||
|
unsigned int uvs : 1;
|
||||||
|
unsigned int normals : 1;
|
||||||
|
unsigned int vcolors : 1;
|
||||||
|
unsigned int apply_subdiv : 1;
|
||||||
|
unsigned int flatten_hierarchy : 1;
|
||||||
|
unsigned int visible_layers_only : 1;
|
||||||
|
unsigned int renderable_only : 1;
|
||||||
|
unsigned int face_sets : 1;
|
||||||
|
unsigned int use_subdiv_schema : 1;
|
||||||
|
unsigned int packuv : 1;
|
||||||
|
|
||||||
|
unsigned int compression_type : 1;
|
||||||
|
float global_scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ABC_export(
|
||||||
|
struct Scene *scene,
|
||||||
|
struct bContext *C,
|
||||||
|
const char *filepath,
|
||||||
|
const struct AlembicExportParams *params);
|
||||||
|
|
||||||
|
void ABC_import(struct bContext *C,
|
||||||
|
const char *filepath,
|
||||||
|
float scale,
|
||||||
|
bool is_sequence,
|
||||||
|
bool set_frame_range,
|
||||||
|
int sequence_len,
|
||||||
|
int offset,
|
||||||
|
bool validate_meshes);
|
||||||
|
|
||||||
|
AbcArchiveHandle *ABC_create_handle(const char *filename, struct ListBase *object_paths);
|
||||||
|
|
||||||
|
void ABC_free_handle(AbcArchiveHandle *handle);
|
||||||
|
|
||||||
|
void ABC_get_transform(AbcArchiveHandle *handle,
|
||||||
|
struct Object *ob,
|
||||||
|
const char *object_path,
|
||||||
|
float r_mat[4][4],
|
||||||
|
float time,
|
||||||
|
float scale);
|
||||||
|
|
||||||
|
struct DerivedMesh *ABC_read_mesh(AbcArchiveHandle *handle,
|
||||||
|
struct Object *ob,
|
||||||
|
struct DerivedMesh *dm,
|
||||||
|
const char *object_path,
|
||||||
|
const float time,
|
||||||
|
const char **err_str,
|
||||||
|
int flags);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __ABC_ALEMBIC_H__ */
|
81
source/blender/alembic/CMakeLists.txt
Normal file
81
source/blender/alembic/CMakeLists.txt
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# The Original Code is Copyright (C) 2006, Blender Foundation
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# The Original Code is: all of this file.
|
||||||
|
#
|
||||||
|
# Contributor(s): Kevin Dietrich.
|
||||||
|
#
|
||||||
|
# ***** END GPL LICENSE BLOCK *****
|
||||||
|
|
||||||
|
set(INC
|
||||||
|
.
|
||||||
|
../blenkernel
|
||||||
|
../blenlib
|
||||||
|
../blenloader
|
||||||
|
../editors/include
|
||||||
|
../makesdna
|
||||||
|
../makesrna
|
||||||
|
../windowmanager
|
||||||
|
../../../intern/guardedalloc
|
||||||
|
)
|
||||||
|
|
||||||
|
set(INC_SYS
|
||||||
|
${ALEMBIC_INCLUDE_DIRS}
|
||||||
|
${HDF5_INCLUDE_DIRS}
|
||||||
|
${OPENEXR_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
if(APPLE)
|
||||||
|
list(APPEND INC_SYS
|
||||||
|
${BOOST_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(SRC
|
||||||
|
intern/abc_camera.cc
|
||||||
|
intern/abc_customdata.cc
|
||||||
|
intern/abc_curves.cc
|
||||||
|
intern/abc_exporter.cc
|
||||||
|
intern/abc_hair.cc
|
||||||
|
intern/abc_mesh.cc
|
||||||
|
intern/abc_nurbs.cc
|
||||||
|
intern/abc_object.cc
|
||||||
|
intern/abc_points.cc
|
||||||
|
intern/abc_transform.cc
|
||||||
|
intern/abc_util.cc
|
||||||
|
intern/alembic_capi.cc
|
||||||
|
|
||||||
|
ABC_alembic.h
|
||||||
|
intern/abc_camera.h
|
||||||
|
intern/abc_customdata.h
|
||||||
|
intern/abc_curves.h
|
||||||
|
intern/abc_exporter.h
|
||||||
|
intern/abc_hair.h
|
||||||
|
intern/abc_mesh.h
|
||||||
|
intern/abc_nurbs.h
|
||||||
|
intern/abc_object.h
|
||||||
|
intern/abc_points.h
|
||||||
|
intern/abc_transform.h
|
||||||
|
intern/abc_util.h
|
||||||
|
)
|
||||||
|
|
||||||
|
if(WITH_ALEMBIC_HDF5)
|
||||||
|
add_definitions(-DWITH_ALEMBIC_HDF5)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
blender_add_lib(bf_alembic "${SRC}" "${INC}" "${INC_SYS}")
|
162
source/blender/alembic/intern/abc_camera.cc
Normal file
162
source/blender/alembic/intern/abc_camera.cc
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "abc_camera.h"
|
||||||
|
|
||||||
|
#include "abc_transform.h"
|
||||||
|
#include "abc_util.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "DNA_camera_types.h"
|
||||||
|
#include "DNA_object_types.h"
|
||||||
|
|
||||||
|
#include "BKE_camera.h"
|
||||||
|
#include "BKE_object.h"
|
||||||
|
|
||||||
|
#include "BLI_math.h"
|
||||||
|
#include "BLI_string.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
using Alembic::AbcGeom::ICamera;
|
||||||
|
using Alembic::AbcGeom::ICompoundProperty;
|
||||||
|
using Alembic::AbcGeom::IFloatProperty;
|
||||||
|
using Alembic::AbcGeom::ISampleSelector;
|
||||||
|
|
||||||
|
using Alembic::AbcGeom::OCamera;
|
||||||
|
using Alembic::AbcGeom::OFloatProperty;
|
||||||
|
|
||||||
|
using Alembic::AbcGeom::CameraSample;
|
||||||
|
using Alembic::AbcGeom::kWrapExisting;
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
AbcCameraWriter::AbcCameraWriter(Scene *scene,
|
||||||
|
Object *ob,
|
||||||
|
AbcTransformWriter *parent,
|
||||||
|
uint32_t time_sampling,
|
||||||
|
ExportSettings &settings)
|
||||||
|
: AbcObjectWriter(scene, ob, time_sampling, settings, parent)
|
||||||
|
{
|
||||||
|
OCamera camera(parent->alembicXform(), m_name, m_time_sampling);
|
||||||
|
m_camera_schema = camera.getSchema();
|
||||||
|
|
||||||
|
m_custom_data_container = m_camera_schema.getUserProperties();
|
||||||
|
m_stereo_distance = OFloatProperty(m_custom_data_container, "stereoDistance", m_time_sampling);
|
||||||
|
m_eye_separation = OFloatProperty(m_custom_data_container, "eyeSeparation", m_time_sampling);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcCameraWriter::do_write()
|
||||||
|
{
|
||||||
|
Camera *cam = static_cast<Camera *>(m_object->data);
|
||||||
|
|
||||||
|
m_stereo_distance.set(cam->stereo.convergence_distance);
|
||||||
|
m_eye_separation.set(cam->stereo.interocular_distance);
|
||||||
|
|
||||||
|
const double apperture_x = cam->sensor_x / 10.0;
|
||||||
|
const double apperture_y = cam->sensor_y / 10.0;
|
||||||
|
const double film_aspect = apperture_x / apperture_y;
|
||||||
|
|
||||||
|
m_camera_sample.setFocalLength(cam->lens);
|
||||||
|
m_camera_sample.setHorizontalAperture(apperture_x);
|
||||||
|
m_camera_sample.setVerticalAperture(apperture_y);
|
||||||
|
m_camera_sample.setHorizontalFilmOffset(apperture_x * cam->shiftx);
|
||||||
|
m_camera_sample.setVerticalFilmOffset(apperture_y * cam->shifty * film_aspect);
|
||||||
|
m_camera_sample.setNearClippingPlane(cam->clipsta);
|
||||||
|
m_camera_sample.setFarClippingPlane(cam->clipend);
|
||||||
|
|
||||||
|
if (cam->dof_ob) {
|
||||||
|
Imath::V3f v(m_object->loc[0] - cam->dof_ob->loc[0],
|
||||||
|
m_object->loc[1] - cam->dof_ob->loc[1],
|
||||||
|
m_object->loc[2] - cam->dof_ob->loc[2]);
|
||||||
|
m_camera_sample.setFocusDistance(v.length());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_camera_sample.setFocusDistance(cam->gpu_dof.focus_distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Blender camera does not have an fstop param, so try to find a custom prop
|
||||||
|
* instead. */
|
||||||
|
m_camera_sample.setFStop(cam->gpu_dof.fstop);
|
||||||
|
|
||||||
|
m_camera_sample.setLensSqueezeRatio(1.0);
|
||||||
|
m_camera_schema.set(m_camera_sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
AbcCameraReader::AbcCameraReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
|
||||||
|
: AbcObjectReader(object, settings)
|
||||||
|
{
|
||||||
|
ICamera abc_cam(m_iobject, kWrapExisting);
|
||||||
|
m_schema = abc_cam.getSchema();
|
||||||
|
|
||||||
|
get_min_max_time(m_schema, m_min_time, m_max_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AbcCameraReader::valid() const
|
||||||
|
{
|
||||||
|
return m_schema.valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcCameraReader::readObjectData(Main *bmain, float time)
|
||||||
|
{
|
||||||
|
Camera *bcam = static_cast<Camera *>(BKE_camera_add(bmain, "abc_camera"));
|
||||||
|
|
||||||
|
ISampleSelector sample_sel(time);
|
||||||
|
CameraSample cam_sample;
|
||||||
|
m_schema.get(cam_sample, sample_sel);
|
||||||
|
|
||||||
|
ICompoundProperty customDataContainer = m_schema.getUserProperties();
|
||||||
|
|
||||||
|
if (customDataContainer.valid() &&
|
||||||
|
customDataContainer.getPropertyHeader("stereoDistance") &&
|
||||||
|
customDataContainer.getPropertyHeader("eyeSeparation"))
|
||||||
|
{
|
||||||
|
IFloatProperty convergence_plane(customDataContainer, "stereoDistance");
|
||||||
|
IFloatProperty eye_separation(customDataContainer, "eyeSeparation");
|
||||||
|
|
||||||
|
bcam->stereo.interocular_distance = eye_separation.getValue(sample_sel);
|
||||||
|
bcam->stereo.convergence_distance = convergence_plane.getValue(sample_sel);
|
||||||
|
}
|
||||||
|
|
||||||
|
const float lens = cam_sample.getFocalLength();
|
||||||
|
const float apperture_x = cam_sample.getHorizontalAperture();
|
||||||
|
const float apperture_y = cam_sample.getVerticalAperture();
|
||||||
|
const float h_film_offset = cam_sample.getHorizontalFilmOffset();
|
||||||
|
const float v_film_offset = cam_sample.getVerticalFilmOffset();
|
||||||
|
const float film_aspect = apperture_x / apperture_y;
|
||||||
|
|
||||||
|
bcam->lens = lens;
|
||||||
|
bcam->sensor_x = apperture_x * 10;
|
||||||
|
bcam->sensor_y = apperture_y * 10;
|
||||||
|
bcam->shiftx = h_film_offset / apperture_x;
|
||||||
|
bcam->shifty = v_film_offset / apperture_y / film_aspect;
|
||||||
|
bcam->clipsta = max_ff(0.1f, cam_sample.getNearClippingPlane());
|
||||||
|
bcam->clipend = cam_sample.getFarClippingPlane();
|
||||||
|
bcam->gpu_dof.focus_distance = cam_sample.getFocusDistance();
|
||||||
|
bcam->gpu_dof.fstop = cam_sample.getFStop();
|
||||||
|
|
||||||
|
BLI_strncpy(bcam->id.name + 2, m_data_name.c_str(), m_data_name.size() + 1);
|
||||||
|
|
||||||
|
m_object = BKE_object_add_only_object(bmain, OB_CAMERA, m_object_name.c_str());
|
||||||
|
m_object->data = bcam;
|
||||||
|
}
|
61
source/blender/alembic/intern/abc_camera.h
Normal file
61
source/blender/alembic/intern/abc_camera.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ABC_CAMERA_H__
|
||||||
|
#define __ABC_CAMERA_H__
|
||||||
|
|
||||||
|
#include "abc_object.h"
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
class AbcCameraWriter : public AbcObjectWriter {
|
||||||
|
Alembic::AbcGeom::OCameraSchema m_camera_schema;
|
||||||
|
Alembic::AbcGeom::CameraSample m_camera_sample;
|
||||||
|
Alembic::AbcGeom::OCompoundProperty m_custom_data_container;
|
||||||
|
Alembic::AbcGeom::OFloatProperty m_stereo_distance;
|
||||||
|
Alembic::AbcGeom::OFloatProperty m_eye_separation;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AbcCameraWriter(Scene *scene,
|
||||||
|
Object *ob,
|
||||||
|
AbcTransformWriter *parent,
|
||||||
|
uint32_t time_sampling,
|
||||||
|
ExportSettings &settings);
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void do_write();
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
class AbcCameraReader : public AbcObjectReader {
|
||||||
|
Alembic::AbcGeom::ICameraSchema m_schema;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AbcCameraReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
|
||||||
|
|
||||||
|
bool valid() const;
|
||||||
|
|
||||||
|
void readObjectData(Main *bmain, float time);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __ABC_CAMERA_H__ */
|
355
source/blender/alembic/intern/abc_curves.cc
Normal file
355
source/blender/alembic/intern/abc_curves.cc
Normal file
@ -0,0 +1,355 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2016 Kévin Dietrich.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "abc_curves.h"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#include "abc_transform.h"
|
||||||
|
#include "abc_util.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
#include "DNA_curve_types.h"
|
||||||
|
#include "DNA_object_types.h"
|
||||||
|
|
||||||
|
#include "BLI_listbase.h"
|
||||||
|
|
||||||
|
#include "BKE_curve.h"
|
||||||
|
#include "BKE_object.h"
|
||||||
|
|
||||||
|
#include "ED_curve.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
using Alembic::Abc::IInt32ArrayProperty;
|
||||||
|
using Alembic::Abc::Int32ArraySamplePtr;
|
||||||
|
using Alembic::Abc::FloatArraySamplePtr;
|
||||||
|
using Alembic::Abc::P3fArraySamplePtr;
|
||||||
|
using Alembic::Abc::UcharArraySamplePtr;
|
||||||
|
|
||||||
|
using Alembic::AbcGeom::ICurves;
|
||||||
|
using Alembic::AbcGeom::ICurvesSchema;
|
||||||
|
using Alembic::AbcGeom::IFloatGeomParam;
|
||||||
|
using Alembic::AbcGeom::ISampleSelector;
|
||||||
|
using Alembic::AbcGeom::kWrapExisting;
|
||||||
|
using Alembic::AbcGeom::CurvePeriodicity;
|
||||||
|
|
||||||
|
using Alembic::AbcGeom::OCurves;
|
||||||
|
using Alembic::AbcGeom::OCurvesSchema;
|
||||||
|
using Alembic::AbcGeom::ON3fGeomParam;
|
||||||
|
using Alembic::AbcGeom::OV2fGeomParam;
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
AbcCurveWriter::AbcCurveWriter(Scene *scene,
|
||||||
|
Object *ob,
|
||||||
|
AbcTransformWriter *parent,
|
||||||
|
uint32_t time_sampling,
|
||||||
|
ExportSettings &settings)
|
||||||
|
: AbcObjectWriter(scene, ob, time_sampling, settings, parent)
|
||||||
|
{
|
||||||
|
OCurves curves(parent->alembicXform(), m_name, m_time_sampling);
|
||||||
|
m_schema = curves.getSchema();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcCurveWriter::do_write()
|
||||||
|
{
|
||||||
|
Curve *curve = static_cast<Curve *>(m_object->data);
|
||||||
|
|
||||||
|
std::vector<Imath::V3f> verts;
|
||||||
|
std::vector<int32_t> vert_counts;
|
||||||
|
std::vector<float> widths;
|
||||||
|
std::vector<float> weights;
|
||||||
|
std::vector<float> knots;
|
||||||
|
std::vector<uint8_t> orders;
|
||||||
|
Imath::V3f temp_vert;
|
||||||
|
|
||||||
|
Alembic::AbcGeom::BasisType curve_basis;
|
||||||
|
Alembic::AbcGeom::CurveType curve_type;
|
||||||
|
Alembic::AbcGeom::CurvePeriodicity periodicity;
|
||||||
|
|
||||||
|
Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first);
|
||||||
|
for (; nurbs; nurbs = nurbs->next) {
|
||||||
|
if (nurbs->bp) {
|
||||||
|
curve_basis = Alembic::AbcGeom::kNoBasis;
|
||||||
|
curve_type = Alembic::AbcGeom::kLinear;
|
||||||
|
|
||||||
|
const int totpoint = nurbs->pntsu * nurbs->pntsv;
|
||||||
|
|
||||||
|
const BPoint *point = nurbs->bp;
|
||||||
|
|
||||||
|
for (int i = 0; i < totpoint; ++i, ++point) {
|
||||||
|
copy_zup_yup(temp_vert.getValue(), point->vec);
|
||||||
|
verts.push_back(temp_vert);
|
||||||
|
weights.push_back(point->vec[3]);
|
||||||
|
widths.push_back(point->radius);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (nurbs->bezt) {
|
||||||
|
curve_basis = Alembic::AbcGeom::kBezierBasis;
|
||||||
|
curve_type = Alembic::AbcGeom::kCubic;
|
||||||
|
|
||||||
|
const int totpoint = nurbs->pntsu;
|
||||||
|
|
||||||
|
const BezTriple *bezier = nurbs->bezt;
|
||||||
|
|
||||||
|
/* TODO(kevin): store info about handles, Alembic doesn't have this. */
|
||||||
|
for (int i = 0; i < totpoint; ++i, ++bezier) {
|
||||||
|
copy_zup_yup(temp_vert.getValue(), bezier->vec[1]);
|
||||||
|
verts.push_back(temp_vert);
|
||||||
|
widths.push_back(bezier->radius);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((nurbs->flagu & CU_NURB_ENDPOINT) != 0) {
|
||||||
|
periodicity = Alembic::AbcGeom::kNonPeriodic;
|
||||||
|
}
|
||||||
|
else if ((nurbs->flagu & CU_NURB_CYCLIC) != 0) {
|
||||||
|
periodicity = Alembic::AbcGeom::kPeriodic;
|
||||||
|
|
||||||
|
/* Duplicate the start points to indicate that the curve is actually
|
||||||
|
* cyclic since other software need those.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (int i = 0; i < nurbs->orderu; ++i) {
|
||||||
|
verts.push_back(verts[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nurbs->knotsu != NULL) {
|
||||||
|
const size_t num_knots = KNOTSU(nurbs);
|
||||||
|
|
||||||
|
/* Add an extra knot at the beggining and end of the array since most apps
|
||||||
|
* require/expect them. */
|
||||||
|
knots.resize(num_knots + 2);
|
||||||
|
|
||||||
|
for (int i = 0; i < num_knots; ++i) {
|
||||||
|
knots[i + 1] = nurbs->knotsu[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((nurbs->flagu & CU_NURB_CYCLIC) != 0) {
|
||||||
|
knots[0] = nurbs->knotsu[0];
|
||||||
|
knots[num_knots - 1] = nurbs->knotsu[num_knots - 1];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
knots[0] = (2.0f * nurbs->knotsu[0] - nurbs->knotsu[1]);
|
||||||
|
knots[num_knots - 1] = (2.0f * nurbs->knotsu[num_knots - 1] - nurbs->knotsu[num_knots - 2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
orders.push_back(nurbs->orderu + 1);
|
||||||
|
vert_counts.push_back(verts.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
Alembic::AbcGeom::OFloatGeomParam::Sample width_sample;
|
||||||
|
width_sample.setVals(widths);
|
||||||
|
|
||||||
|
m_sample = OCurvesSchema::Sample(verts,
|
||||||
|
vert_counts,
|
||||||
|
curve_type,
|
||||||
|
periodicity,
|
||||||
|
width_sample,
|
||||||
|
OV2fGeomParam::Sample(), /* UVs */
|
||||||
|
ON3fGeomParam::Sample(), /* normals */
|
||||||
|
curve_basis,
|
||||||
|
weights,
|
||||||
|
orders,
|
||||||
|
knots);
|
||||||
|
|
||||||
|
m_sample.setSelfBounds(bounds());
|
||||||
|
m_schema.set(m_sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
AbcCurveReader::AbcCurveReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
|
||||||
|
: AbcObjectReader(object, settings)
|
||||||
|
{
|
||||||
|
ICurves abc_curves(object, kWrapExisting);
|
||||||
|
m_curves_schema = abc_curves.getSchema();
|
||||||
|
|
||||||
|
get_min_max_time(m_curves_schema, m_min_time, m_max_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AbcCurveReader::valid() const
|
||||||
|
{
|
||||||
|
return m_curves_schema.valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcCurveReader::readObjectData(Main *bmain, float time)
|
||||||
|
{
|
||||||
|
Curve *cu = BKE_curve_add(bmain, m_data_name.c_str(), OB_CURVE);
|
||||||
|
|
||||||
|
cu->flag |= CU_DEFORM_FILL | CU_3D;
|
||||||
|
cu->actvert = CU_ACT_NONE;
|
||||||
|
|
||||||
|
m_object = BKE_object_add_only_object(bmain, OB_CURVE, m_object_name.c_str());
|
||||||
|
m_object->data = cu;
|
||||||
|
|
||||||
|
read_curve_sample(cu, m_curves_schema, time);
|
||||||
|
|
||||||
|
if (has_animations(m_curves_schema, m_settings)) {
|
||||||
|
addCacheModifier();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time)
|
||||||
|
{
|
||||||
|
const ISampleSelector sample_sel(time);
|
||||||
|
ICurvesSchema::Sample smp = schema.getValue(sample_sel);
|
||||||
|
const Int32ArraySamplePtr num_vertices = smp.getCurvesNumVertices();
|
||||||
|
const P3fArraySamplePtr positions = smp.getPositions();
|
||||||
|
const FloatArraySamplePtr weights = smp.getPositionWeights();
|
||||||
|
const FloatArraySamplePtr knots = smp.getKnots();
|
||||||
|
const CurvePeriodicity periodicity = smp.getWrap();
|
||||||
|
const UcharArraySamplePtr orders = smp.getOrders();
|
||||||
|
|
||||||
|
const IFloatGeomParam widths_param = schema.getWidthsParam();
|
||||||
|
FloatArraySamplePtr radiuses;
|
||||||
|
|
||||||
|
if (widths_param.valid()) {
|
||||||
|
IFloatGeomParam::Sample wsample = widths_param.getExpandedValue(sample_sel);
|
||||||
|
radiuses = wsample.getVals();
|
||||||
|
}
|
||||||
|
|
||||||
|
int knot_offset = 0;
|
||||||
|
|
||||||
|
size_t idx = 0;
|
||||||
|
for (size_t i = 0; i < num_vertices->size(); ++i) {
|
||||||
|
const int num_verts = (*num_vertices)[i];
|
||||||
|
|
||||||
|
Nurb *nu = static_cast<Nurb *>(MEM_callocN(sizeof(Nurb), "abc_getnurb"));
|
||||||
|
nu->resolu = cu->resolu;
|
||||||
|
nu->resolv = cu->resolv;
|
||||||
|
nu->pntsu = num_verts;
|
||||||
|
nu->pntsv = 1;
|
||||||
|
nu->flag |= CU_SMOOTH;
|
||||||
|
|
||||||
|
nu->orderu = num_verts;
|
||||||
|
|
||||||
|
if (smp.getType() == Alembic::AbcGeom::kCubic) {
|
||||||
|
nu->orderu = 3;
|
||||||
|
}
|
||||||
|
else if (orders && orders->size() > i) {
|
||||||
|
nu->orderu = static_cast<short>((*orders)[i] - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (periodicity == Alembic::AbcGeom::kNonPeriodic) {
|
||||||
|
nu->flagu |= CU_NURB_ENDPOINT;
|
||||||
|
}
|
||||||
|
else if (periodicity == Alembic::AbcGeom::kPeriodic) {
|
||||||
|
nu->flagu |= CU_NURB_CYCLIC;
|
||||||
|
|
||||||
|
/* Check the number of points which overlap, we don't have
|
||||||
|
* overlapping points in Blender, but other software do use them to
|
||||||
|
* indicate that a curve is actually cyclic. Usually the number of
|
||||||
|
* overlapping points is equal to the order/degree of the curve.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const int start = idx;
|
||||||
|
const int end = idx + num_verts;
|
||||||
|
int overlap = 0;
|
||||||
|
|
||||||
|
for (int j = start, k = end - nu->orderu; j < nu->orderu; ++j, ++k) {
|
||||||
|
const Imath::V3f &p1 = (*positions)[j];
|
||||||
|
const Imath::V3f &p2 = (*positions)[k];
|
||||||
|
|
||||||
|
if (p1 != p2) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
++overlap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Special case, need to figure out how it coincides with knots. */
|
||||||
|
if (overlap == 0 && num_verts > 2 && (*positions)[start] == (*positions)[end - 1]) {
|
||||||
|
overlap = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There is no real cycles. */
|
||||||
|
if (overlap == 0) {
|
||||||
|
nu->flagu &= ~CU_NURB_CYCLIC;
|
||||||
|
nu->flagu |= CU_NURB_ENDPOINT;
|
||||||
|
}
|
||||||
|
|
||||||
|
nu->pntsu -= overlap;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool do_weights = (weights != NULL) && (weights->size() > 1);
|
||||||
|
float weight = 1.0f;
|
||||||
|
|
||||||
|
const bool do_radius = (radiuses != NULL) && (radiuses->size() > 1);
|
||||||
|
float radius = (radiuses && radiuses->size() == 1) ? (*radiuses)[0] : 1.0f;
|
||||||
|
|
||||||
|
nu->type = CU_NURBS;
|
||||||
|
|
||||||
|
nu->bp = static_cast<BPoint *>(MEM_callocN(sizeof(BPoint) * nu->pntsu, "abc_getnurb"));
|
||||||
|
BPoint *bp = nu->bp;
|
||||||
|
|
||||||
|
for (int j = 0; j < nu->pntsu; ++j, ++bp, ++idx) {
|
||||||
|
const Imath::V3f &pos = (*positions)[idx];
|
||||||
|
|
||||||
|
if (do_radius) {
|
||||||
|
radius = (*radiuses)[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_weights) {
|
||||||
|
weight = (*weights)[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_yup_zup(bp->vec, pos.getValue());
|
||||||
|
bp->vec[3] = weight;
|
||||||
|
bp->f1 = SELECT;
|
||||||
|
bp->radius = radius;
|
||||||
|
bp->weight = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (knots && knots->size() != 0) {
|
||||||
|
nu->knotsu = static_cast<float *>(MEM_callocN(KNOTSU(nu) * sizeof(float), "abc_setsplineknotsu"));
|
||||||
|
|
||||||
|
/* TODO: second check is temporary, for until the check for cycles is rock solid. */
|
||||||
|
if (periodicity == Alembic::AbcGeom::kPeriodic && (KNOTSU(nu) == knots->size() - 2)) {
|
||||||
|
/* Skip first and last knots. */
|
||||||
|
for (size_t i = 1; i < knots->size() - 1; ++i) {
|
||||||
|
nu->knotsu[i - 1] = (*knots)[knot_offset + i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* TODO: figure out how to use the knots array from other
|
||||||
|
* software in this case. */
|
||||||
|
BKE_nurb_knot_calc_u(nu);
|
||||||
|
}
|
||||||
|
|
||||||
|
knot_offset += knots->size();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BKE_nurb_knot_calc_u(nu);
|
||||||
|
}
|
||||||
|
|
||||||
|
BLI_addtail(BKE_curve_nurbs_get(cu), nu);
|
||||||
|
}
|
||||||
|
}
|
65
source/blender/alembic/intern/abc_curves.h
Normal file
65
source/blender/alembic/intern/abc_curves.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2016 Kévin Dietrich.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ABC_CURVES_H__
|
||||||
|
#define __ABC_CURVES_H__
|
||||||
|
|
||||||
|
#include "abc_object.h"
|
||||||
|
|
||||||
|
struct Curve;
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
class AbcCurveWriter : public AbcObjectWriter {
|
||||||
|
Alembic::AbcGeom::OCurvesSchema m_schema;
|
||||||
|
Alembic::AbcGeom::OCurvesSchema::Sample m_sample;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AbcCurveWriter(Scene *scene,
|
||||||
|
Object *ob,
|
||||||
|
AbcTransformWriter *parent,
|
||||||
|
uint32_t time_sampling,
|
||||||
|
ExportSettings &settings);
|
||||||
|
|
||||||
|
void do_write();
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
class AbcCurveReader : public AbcObjectReader {
|
||||||
|
Alembic::AbcGeom::ICurvesSchema m_curves_schema;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AbcCurveReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
|
||||||
|
|
||||||
|
bool valid() const;
|
||||||
|
|
||||||
|
void readObjectData(Main *bmain, float time);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
void read_curve_sample(Curve *cu, const Alembic::AbcGeom::ICurvesSchema &schema, const float time);
|
||||||
|
|
||||||
|
#endif /* __ABC_CURVES_H__ */
|
379
source/blender/alembic/intern/abc_customdata.cc
Normal file
379
source/blender/alembic/intern/abc_customdata.cc
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2016 Kévin Dietrich.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "abc_customdata.h"
|
||||||
|
|
||||||
|
#include <Alembic/AbcGeom/All.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "DNA_customdata_types.h"
|
||||||
|
#include "DNA_meshdata_types.h"
|
||||||
|
|
||||||
|
#include "BKE_customdata.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTE: for now only UVs and Vertex Colors are supported for streaming.
|
||||||
|
* Although Alembic only allows for a single UV layer per {I|O}Schema, and does
|
||||||
|
* not have a vertex color concept, there is a convention between DCCs to write
|
||||||
|
* such data in a way that lets other DCC know what they are for. See comments
|
||||||
|
* in the write code for the conventions. */
|
||||||
|
|
||||||
|
using Alembic::AbcGeom::kVertexScope;
|
||||||
|
using Alembic::AbcGeom::kFacevaryingScope;
|
||||||
|
|
||||||
|
using Alembic::Abc::C4fArraySample;
|
||||||
|
using Alembic::Abc::UInt32ArraySample;
|
||||||
|
using Alembic::Abc::V2fArraySample;
|
||||||
|
|
||||||
|
using Alembic::AbcGeom::OV2fGeomParam;
|
||||||
|
using Alembic::AbcGeom::OC4fGeomParam;
|
||||||
|
|
||||||
|
static void get_uvs(const CDStreamConfig &config,
|
||||||
|
std::vector<Imath::V2f> &uvs,
|
||||||
|
std::vector<uint32_t> &uvidx,
|
||||||
|
void *cd_data)
|
||||||
|
{
|
||||||
|
MLoopUV *mloopuv_array = static_cast<MLoopUV *>(cd_data);
|
||||||
|
|
||||||
|
if (!mloopuv_array) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int num_poly = config.totpoly;
|
||||||
|
MPoly *polygons = config.mpoly;
|
||||||
|
|
||||||
|
if (!config.pack_uvs) {
|
||||||
|
int cnt = 0;
|
||||||
|
uvidx.resize(config.totloop);
|
||||||
|
uvs.resize(config.totloop);
|
||||||
|
|
||||||
|
for (int i = 0; i < num_poly; ++i) {
|
||||||
|
MPoly ¤t_poly = polygons[i];
|
||||||
|
MLoopUV *loopuvpoly = mloopuv_array + current_poly.loopstart + current_poly.totloop;
|
||||||
|
|
||||||
|
for (int j = 0; j < current_poly.totloop; ++j, ++cnt) {
|
||||||
|
--loopuvpoly;
|
||||||
|
|
||||||
|
uvidx[cnt] = cnt;
|
||||||
|
uvs[cnt][0] = loopuvpoly->uv[0];
|
||||||
|
uvs[cnt][1] = loopuvpoly->uv[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int i = 0; i < num_poly; ++i) {
|
||||||
|
MPoly ¤t_poly = polygons[i];
|
||||||
|
MLoopUV *loopuvpoly = mloopuv_array + current_poly.loopstart + current_poly.totloop;
|
||||||
|
|
||||||
|
for (int j = 0; j < current_poly.totloop; ++j) {
|
||||||
|
loopuvpoly--;
|
||||||
|
Imath::V2f uv(loopuvpoly->uv[0], loopuvpoly->uv[1]);
|
||||||
|
|
||||||
|
std::vector<Imath::V2f>::iterator it = std::find(uvs.begin(), uvs.end(), uv);
|
||||||
|
|
||||||
|
if (it == uvs.end()) {
|
||||||
|
uvidx.push_back(uvs.size());
|
||||||
|
uvs.push_back(uv);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uvidx.push_back(std::distance(uvs.begin(), it));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *get_uv_sample(UVSample &sample, const CDStreamConfig &config, CustomData *data)
|
||||||
|
{
|
||||||
|
const int active_uvlayer = CustomData_get_active_layer(data, CD_MLOOPUV);
|
||||||
|
|
||||||
|
if (active_uvlayer < 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cd_data = CustomData_get_layer_n(data, CD_MLOOPUV, active_uvlayer);
|
||||||
|
|
||||||
|
get_uvs(config, sample.uvs, sample.indices, cd_data);
|
||||||
|
|
||||||
|
return CustomData_get_layer_name(data, CD_MLOOPUV, active_uvlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convention to write UVs:
|
||||||
|
* - V2fGeomParam on the arbGeomParam
|
||||||
|
* - set scope as face varying
|
||||||
|
* - (optional due to its behaviour) tag as UV using Alembic::AbcGeom::SetIsUV
|
||||||
|
*/
|
||||||
|
static void write_uv(const OCompoundProperty &prop, const CDStreamConfig &config, void *data, const char *name)
|
||||||
|
{
|
||||||
|
std::vector<uint32_t> indices;
|
||||||
|
std::vector<Imath::V2f> uvs;
|
||||||
|
|
||||||
|
get_uvs(config, uvs, indices, data);
|
||||||
|
|
||||||
|
if (indices.empty() || uvs.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OV2fGeomParam param(prop, name, true, kFacevaryingScope, 1);
|
||||||
|
|
||||||
|
OV2fGeomParam::Sample sample(
|
||||||
|
V2fArraySample(&uvs.front(), uvs.size()),
|
||||||
|
UInt32ArraySample(&indices.front(), indices.size()),
|
||||||
|
kFacevaryingScope);
|
||||||
|
|
||||||
|
param.set(sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convention to write Vertex Colors:
|
||||||
|
* - C3fGeomParam/C4fGeomParam on the arbGeomParam
|
||||||
|
* - set scope as vertex varying
|
||||||
|
*/
|
||||||
|
static void write_mcol(const OCompoundProperty &prop, const CDStreamConfig &config, void *data, const char *name)
|
||||||
|
{
|
||||||
|
const float cscale = 1.0f / 255.0f;
|
||||||
|
MPoly *polys = config.mpoly;
|
||||||
|
MLoop *mloops = config.mloop;
|
||||||
|
MCol *cfaces = static_cast<MCol *>(data);
|
||||||
|
|
||||||
|
std::vector<Imath::C4f> buffer(config.totvert);
|
||||||
|
|
||||||
|
Imath::C4f col;
|
||||||
|
|
||||||
|
for (int i = 0; i < config.totpoly; ++i) {
|
||||||
|
MPoly *p = &polys[i];
|
||||||
|
MCol *cface = &cfaces[p->loopstart + p->totloop];
|
||||||
|
MLoop *mloop = &mloops[p->loopstart + p->totloop];
|
||||||
|
|
||||||
|
for (int j = 0; j < p->totloop; ++j) {
|
||||||
|
cface--;
|
||||||
|
mloop--;
|
||||||
|
|
||||||
|
col[0] = cface->a * cscale;
|
||||||
|
col[1] = cface->r * cscale;
|
||||||
|
col[2] = cface->g * cscale;
|
||||||
|
col[3] = cface->b * cscale;
|
||||||
|
|
||||||
|
buffer[mloop->v] = col;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OC4fGeomParam param(prop, name, true, kFacevaryingScope, 1);
|
||||||
|
|
||||||
|
OC4fGeomParam::Sample sample(
|
||||||
|
C4fArraySample(&buffer.front(), buffer.size()),
|
||||||
|
kVertexScope);
|
||||||
|
|
||||||
|
param.set(sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_custom_data(const OCompoundProperty &prop, const CDStreamConfig &config, CustomData *data, int data_type)
|
||||||
|
{
|
||||||
|
CustomDataType cd_data_type = static_cast<CustomDataType>(data_type);
|
||||||
|
|
||||||
|
if (!CustomData_has_layer(data, cd_data_type)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int active_layer = CustomData_get_active_layer(data, cd_data_type);
|
||||||
|
const int tot_layers = CustomData_number_of_layers(data, cd_data_type);
|
||||||
|
|
||||||
|
for (int i = 0; i < tot_layers; ++i) {
|
||||||
|
void *cd_data = CustomData_get_layer_n(data, cd_data_type, i);
|
||||||
|
const char *name = CustomData_get_layer_name(data, cd_data_type, i);
|
||||||
|
|
||||||
|
if (cd_data_type == CD_MLOOPUV) {
|
||||||
|
/* Already exported. */
|
||||||
|
if (i == active_layer) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_uv(prop, config, cd_data, name);
|
||||||
|
}
|
||||||
|
else if (cd_data_type == CD_MLOOPCOL) {
|
||||||
|
write_mcol(prop, config, cd_data, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
using Alembic::Abc::C3fArraySamplePtr;
|
||||||
|
using Alembic::Abc::C4fArraySamplePtr;
|
||||||
|
using Alembic::Abc::PropertyHeader;
|
||||||
|
|
||||||
|
using Alembic::AbcGeom::IC3fGeomParam;
|
||||||
|
using Alembic::AbcGeom::IC4fGeomParam;
|
||||||
|
using Alembic::AbcGeom::IV2fGeomParam;
|
||||||
|
|
||||||
|
static void read_mcols(const CDStreamConfig &config, void *data,
|
||||||
|
const C3fArraySamplePtr &c3f_ptr, const C4fArraySamplePtr &c4f_ptr)
|
||||||
|
{
|
||||||
|
MCol *cfaces = static_cast<MCol *>(data);
|
||||||
|
MPoly *polys = config.mpoly;
|
||||||
|
MLoop *mloops = config.mloop;
|
||||||
|
|
||||||
|
if (c3f_ptr) {
|
||||||
|
for (int i = 0; i < config.totpoly; ++i) {
|
||||||
|
MPoly *p = &polys[i];
|
||||||
|
MCol *cface = &cfaces[p->loopstart + p->totloop];
|
||||||
|
MLoop *mloop = &mloops[p->loopstart + p->totloop];
|
||||||
|
|
||||||
|
for (int j = 0; j < p->totloop; ++j) {
|
||||||
|
cface--;
|
||||||
|
mloop--;
|
||||||
|
const Imath::C3f &color = (*c3f_ptr)[mloop->v];
|
||||||
|
cface->a = FTOCHAR(color[0]);
|
||||||
|
cface->r = FTOCHAR(color[1]);
|
||||||
|
cface->g = FTOCHAR(color[2]);
|
||||||
|
cface->b = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c4f_ptr) {
|
||||||
|
for (int i = 0; i < config.totpoly; ++i) {
|
||||||
|
MPoly *p = &polys[i];
|
||||||
|
MCol *cface = &cfaces[p->loopstart + p->totloop];
|
||||||
|
MLoop *mloop = &mloops[p->loopstart + p->totloop];
|
||||||
|
|
||||||
|
for (int j = 0; j < p->totloop; ++j) {
|
||||||
|
cface--;
|
||||||
|
mloop--;
|
||||||
|
const Imath::C4f &color = (*c4f_ptr)[mloop->v];
|
||||||
|
cface->a = FTOCHAR(color[0]);
|
||||||
|
cface->r = FTOCHAR(color[1]);
|
||||||
|
cface->g = FTOCHAR(color[2]);
|
||||||
|
cface->b = FTOCHAR(color[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void read_uvs(const CDStreamConfig &config, void *data,
|
||||||
|
const Alembic::AbcGeom::V2fArraySamplePtr &uvs,
|
||||||
|
const Alembic::AbcGeom::UInt32ArraySamplePtr &indices)
|
||||||
|
{
|
||||||
|
MPoly *mpolys = config.mpoly;
|
||||||
|
MLoopUV *mloopuvs = static_cast<MLoopUV *>(data);
|
||||||
|
|
||||||
|
unsigned int uv_index, loop_index;
|
||||||
|
|
||||||
|
for (int i = 0; i < config.totpoly; ++i) {
|
||||||
|
MPoly &poly = mpolys[i];
|
||||||
|
|
||||||
|
for (int f = 0; f < poly.totloop; ++f) {
|
||||||
|
loop_index = poly.loopstart + f;
|
||||||
|
uv_index = (*indices)[loop_index];
|
||||||
|
const Imath::V2f &uv = (*uvs)[uv_index];
|
||||||
|
|
||||||
|
MLoopUV &loopuv = mloopuvs[loop_index];
|
||||||
|
loopuv.uv[0] = uv[0];
|
||||||
|
loopuv.uv[1] = uv[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void read_custom_data_ex(const ICompoundProperty &prop,
|
||||||
|
const PropertyHeader &prop_header,
|
||||||
|
const CDStreamConfig &config,
|
||||||
|
const Alembic::Abc::ISampleSelector &iss,
|
||||||
|
int data_type)
|
||||||
|
{
|
||||||
|
if (data_type == CD_MLOOPCOL) {
|
||||||
|
C3fArraySamplePtr c3f_ptr = C3fArraySamplePtr();
|
||||||
|
C4fArraySamplePtr c4f_ptr = C4fArraySamplePtr();
|
||||||
|
|
||||||
|
if (IC3fGeomParam::matches(prop_header)) {
|
||||||
|
IC3fGeomParam color_param(prop, prop_header.getName());
|
||||||
|
IC3fGeomParam::Sample sample;
|
||||||
|
color_param.getIndexed(sample, iss);
|
||||||
|
|
||||||
|
c3f_ptr = sample.getVals();
|
||||||
|
}
|
||||||
|
else if (IC4fGeomParam::matches(prop_header)) {
|
||||||
|
IC4fGeomParam color_param(prop, prop_header.getName());
|
||||||
|
IC4fGeomParam::Sample sample;
|
||||||
|
color_param.getIndexed(sample, iss);
|
||||||
|
|
||||||
|
c4f_ptr = sample.getVals();
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cd_data = config.add_customdata_cb(config.user_data,
|
||||||
|
prop_header.getName().c_str(),
|
||||||
|
data_type);
|
||||||
|
|
||||||
|
read_mcols(config, cd_data, c3f_ptr, c4f_ptr);
|
||||||
|
}
|
||||||
|
else if (data_type == CD_MLOOPUV) {
|
||||||
|
IV2fGeomParam uv_param(prop, prop_header.getName());
|
||||||
|
IV2fGeomParam::Sample sample;
|
||||||
|
uv_param.getIndexed(sample, iss);
|
||||||
|
|
||||||
|
if (uv_param.getScope() != kFacevaryingScope) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cd_data = config.add_customdata_cb(config.user_data,
|
||||||
|
prop_header.getName().c_str(),
|
||||||
|
data_type);
|
||||||
|
|
||||||
|
read_uvs(config, cd_data, sample.getVals(), sample.getIndices());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_custom_data(const ICompoundProperty &prop, const CDStreamConfig &config, const Alembic::Abc::ISampleSelector &iss)
|
||||||
|
{
|
||||||
|
if (!prop.valid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int num_uvs = 0;
|
||||||
|
int num_colors = 0;
|
||||||
|
|
||||||
|
const size_t num_props = prop.getNumProperties();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < num_props; ++i) {
|
||||||
|
const Alembic::Abc::PropertyHeader &prop_header = prop.getPropertyHeader(i);
|
||||||
|
|
||||||
|
/* Read UVs according to convention. */
|
||||||
|
if (IV2fGeomParam::matches(prop_header) && Alembic::AbcGeom::isUV(prop_header)) {
|
||||||
|
if (++num_uvs > MAX_MTFACE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
read_custom_data_ex(prop, prop_header, config, iss, CD_MLOOPUV);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read vertex colors according to convention. */
|
||||||
|
if (IC3fGeomParam::matches(prop_header) || IC4fGeomParam::matches(prop_header)) {
|
||||||
|
if (++num_colors > MAX_MCOL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
read_custom_data_ex(prop, prop_header, config, iss, CD_MLOOPCOL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
93
source/blender/alembic/intern/abc_customdata.h
Normal file
93
source/blender/alembic/intern/abc_customdata.h
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2016 Kévin Dietrich.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ABC_CUSTOMDATA_H__
|
||||||
|
#define __ABC_CUSTOMDATA_H__
|
||||||
|
|
||||||
|
#include <Alembic/Abc/All.h>
|
||||||
|
|
||||||
|
struct CustomData;
|
||||||
|
struct MLoop;
|
||||||
|
struct MLoopUV;
|
||||||
|
struct MPoly;
|
||||||
|
struct MVert;
|
||||||
|
|
||||||
|
using Alembic::Abc::ICompoundProperty;
|
||||||
|
using Alembic::Abc::OCompoundProperty;
|
||||||
|
|
||||||
|
struct UVSample {
|
||||||
|
std::vector<Imath::V2f> uvs;
|
||||||
|
std::vector<uint32_t> indices;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CDStreamConfig {
|
||||||
|
MLoop *mloop;
|
||||||
|
int totloop;
|
||||||
|
|
||||||
|
MPoly *mpoly;
|
||||||
|
int totpoly;
|
||||||
|
|
||||||
|
MVert *mvert;
|
||||||
|
int totvert;
|
||||||
|
|
||||||
|
MLoopUV *mloopuv;
|
||||||
|
|
||||||
|
CustomData *loopdata;
|
||||||
|
|
||||||
|
bool pack_uvs;
|
||||||
|
|
||||||
|
/* TODO(kevin): might need a better way to handle adding and/or updating
|
||||||
|
* custom datas such that it updates the custom data holder and its pointers
|
||||||
|
* properly. */
|
||||||
|
void *user_data;
|
||||||
|
void *(*add_customdata_cb)(void *user_data, const char *name, int data_type);
|
||||||
|
|
||||||
|
CDStreamConfig()
|
||||||
|
: mloop(NULL)
|
||||||
|
, totloop(0)
|
||||||
|
, mpoly(NULL)
|
||||||
|
, totpoly(0)
|
||||||
|
, totvert(0)
|
||||||
|
, pack_uvs(false)
|
||||||
|
, user_data(NULL)
|
||||||
|
, add_customdata_cb(NULL)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Get the UVs for the main UV property on a OSchema.
|
||||||
|
* Returns the name of the UV layer.
|
||||||
|
*
|
||||||
|
* For now the active layer is used, maybe needs a better way to choose this. */
|
||||||
|
const char *get_uv_sample(UVSample &sample, const CDStreamConfig &config, CustomData *data);
|
||||||
|
|
||||||
|
void write_custom_data(const OCompoundProperty &prop,
|
||||||
|
const CDStreamConfig &config,
|
||||||
|
CustomData *data,
|
||||||
|
int data_type);
|
||||||
|
|
||||||
|
void read_custom_data(const ICompoundProperty &prop,
|
||||||
|
const CDStreamConfig &config,
|
||||||
|
const Alembic::Abc::ISampleSelector &iss);
|
||||||
|
|
||||||
|
#endif /* __ABC_CUSTOMDATA_H__ */
|
600
source/blender/alembic/intern/abc_exporter.cc
Normal file
600
source/blender/alembic/intern/abc_exporter.cc
Normal file
@ -0,0 +1,600 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "abc_exporter.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#ifdef WITH_ALEMBIC_HDF5
|
||||||
|
# include <Alembic/AbcCoreHDF5/All.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Alembic/AbcCoreOgawa/All.h>
|
||||||
|
|
||||||
|
#include "abc_camera.h"
|
||||||
|
#include "abc_curves.h"
|
||||||
|
#include "abc_hair.h"
|
||||||
|
#include "abc_mesh.h"
|
||||||
|
#include "abc_nurbs.h"
|
||||||
|
#include "abc_points.h"
|
||||||
|
#include "abc_transform.h"
|
||||||
|
#include "abc_util.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "DNA_camera_types.h"
|
||||||
|
#include "DNA_curve_types.h"
|
||||||
|
#include "DNA_mesh_types.h"
|
||||||
|
#include "DNA_modifier_types.h"
|
||||||
|
#include "DNA_scene_types.h"
|
||||||
|
#include "DNA_space_types.h" /* for FILE_MAX */
|
||||||
|
|
||||||
|
#include "BLI_string.h"
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
/* needed for MSCV because of snprintf from BLI_string */
|
||||||
|
# include "BLI_winstuff.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "BKE_anim.h"
|
||||||
|
#include "BKE_global.h"
|
||||||
|
#include "BKE_idprop.h"
|
||||||
|
#include "BKE_main.h"
|
||||||
|
#include "BKE_modifier.h"
|
||||||
|
#include "BKE_particle.h"
|
||||||
|
#include "BKE_scene.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
using Alembic::Abc::TimeSamplingPtr;
|
||||||
|
using Alembic::Abc::OBox3dProperty;
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
ExportSettings::ExportSettings()
|
||||||
|
: scene(NULL)
|
||||||
|
, selected_only(false)
|
||||||
|
, visible_layers_only(false)
|
||||||
|
, renderable_only(false)
|
||||||
|
, frame_start(1)
|
||||||
|
, frame_end(1)
|
||||||
|
, frame_step_xform(1)
|
||||||
|
, frame_step_shape(1)
|
||||||
|
, shutter_open(0.0)
|
||||||
|
, shutter_close(1.0)
|
||||||
|
, global_scale(1.0f)
|
||||||
|
, flatten_hierarchy(false)
|
||||||
|
, export_normals(false)
|
||||||
|
, export_uvs(false)
|
||||||
|
, export_vcols(false)
|
||||||
|
, export_face_sets(false)
|
||||||
|
, export_vweigths(false)
|
||||||
|
, apply_subdiv(false)
|
||||||
|
, use_subdiv_schema(false)
|
||||||
|
, export_child_hairs(true)
|
||||||
|
, export_ogawa(true)
|
||||||
|
, pack_uv(false)
|
||||||
|
, do_convert_axis(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
static bool object_is_smoke_sim(Object *ob)
|
||||||
|
{
|
||||||
|
ModifierData *md = modifiers_findByType(ob, eModifierType_Smoke);
|
||||||
|
|
||||||
|
if (md) {
|
||||||
|
SmokeModifierData *smd = reinterpret_cast<SmokeModifierData *>(md);
|
||||||
|
return (smd->type == MOD_SMOKE_TYPE_DOMAIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool object_is_shape(Object *ob)
|
||||||
|
{
|
||||||
|
switch (ob->type) {
|
||||||
|
case OB_MESH:
|
||||||
|
if (object_is_smoke_sim(ob)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
case OB_CURVE:
|
||||||
|
case OB_SURF:
|
||||||
|
case OB_CAMERA:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool export_object(const ExportSettings * const settings, Object *ob)
|
||||||
|
{
|
||||||
|
if (settings->selected_only && !parent_selected(ob)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings->visible_layers_only && !(settings->scene->lay & ob->lay)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings->renderable_only && (ob->restrictflag & OB_RESTRICT_RENDER)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
AbcExporter::AbcExporter(Scene *scene, const char *filename, ExportSettings &settings)
|
||||||
|
: m_settings(settings)
|
||||||
|
, m_filename(filename)
|
||||||
|
, m_trans_sampling_index(0)
|
||||||
|
, m_shape_sampling_index(0)
|
||||||
|
, m_scene(scene)
|
||||||
|
{}
|
||||||
|
|
||||||
|
AbcExporter::~AbcExporter()
|
||||||
|
{
|
||||||
|
std::map<std::string, AbcTransformWriter*>::iterator it, e;
|
||||||
|
for (it = m_xforms.begin(), e = m_xforms.end(); it != e; ++it) {
|
||||||
|
delete it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0, e = m_shapes.size(); i != e; ++i) {
|
||||||
|
delete m_shapes[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcExporter::getShutterSamples(double step, bool time_relative,
|
||||||
|
std::vector<double> &samples)
|
||||||
|
{
|
||||||
|
samples.clear();
|
||||||
|
|
||||||
|
const double time_factor = time_relative ? m_scene->r.frs_sec : 1.0;
|
||||||
|
const double shutter_open = m_settings.shutter_open;
|
||||||
|
const double shutter_close = m_settings.shutter_close;
|
||||||
|
|
||||||
|
/* sample all frame */
|
||||||
|
if (shutter_open == 0.0 && shutter_close == 1.0) {
|
||||||
|
for (double t = 0; t < 1.0; t += step) {
|
||||||
|
samples.push_back(t / time_factor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* sample between shutter open & close */
|
||||||
|
const int nsamples = std::max((1.0 / step) - 1.0, 1.0);
|
||||||
|
const double time_inc = (shutter_close - shutter_open) / nsamples;
|
||||||
|
|
||||||
|
for (double t = shutter_open; t <= shutter_close; t += time_inc) {
|
||||||
|
samples.push_back(t / time_factor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Alembic::Abc::TimeSamplingPtr AbcExporter::createTimeSampling(double step)
|
||||||
|
{
|
||||||
|
TimeSamplingPtr time_sampling;
|
||||||
|
std::vector<double> samples;
|
||||||
|
|
||||||
|
if (m_settings.frame_start == m_settings.frame_end) {
|
||||||
|
time_sampling.reset(new Alembic::Abc::TimeSampling());
|
||||||
|
return time_sampling;
|
||||||
|
}
|
||||||
|
|
||||||
|
getShutterSamples(step, true, samples);
|
||||||
|
|
||||||
|
Alembic::Abc::TimeSamplingType ts(static_cast<uint32_t>(samples.size()), 1.0 / m_scene->r.frs_sec);
|
||||||
|
time_sampling.reset(new Alembic::Abc::TimeSampling(ts, samples));
|
||||||
|
|
||||||
|
return time_sampling;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcExporter::getFrameSet(double step, std::set<double> &frames)
|
||||||
|
{
|
||||||
|
frames.clear();
|
||||||
|
|
||||||
|
std::vector<double> shutter_samples;
|
||||||
|
|
||||||
|
getShutterSamples(step, false, shutter_samples);
|
||||||
|
|
||||||
|
for (int frame = m_settings.frame_start; frame <= m_settings.frame_end; ++frame) {
|
||||||
|
for (int j = 0, e = shutter_samples.size(); j < e; ++j) {
|
||||||
|
frames.insert(frame + shutter_samples[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled)
|
||||||
|
{
|
||||||
|
std::string scene_name;
|
||||||
|
|
||||||
|
if (bmain->name[0] != '\0') {
|
||||||
|
char scene_file_name[FILE_MAX];
|
||||||
|
BLI_strncpy(scene_file_name, bmain->name, FILE_MAX);
|
||||||
|
scene_name = scene_file_name;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
scene_name = "untitled";
|
||||||
|
}
|
||||||
|
|
||||||
|
Scene *scene = m_scene;
|
||||||
|
const int fps = FPS;
|
||||||
|
char buf[16];
|
||||||
|
snprintf(buf, 15, "%d", fps);
|
||||||
|
const std::string str_fps = buf;
|
||||||
|
|
||||||
|
Alembic::AbcCoreAbstract::MetaData md;
|
||||||
|
md.set("FramesPerTimeUnit", str_fps);
|
||||||
|
|
||||||
|
Alembic::Abc::Argument arg(md);
|
||||||
|
|
||||||
|
#ifdef WITH_ALEMBIC_HDF5
|
||||||
|
if (!m_settings.export_ogawa) {
|
||||||
|
m_archive = Alembic::Abc::CreateArchiveWithInfo(Alembic::AbcCoreHDF5::WriteArchive(),
|
||||||
|
m_filename,
|
||||||
|
"Blender",
|
||||||
|
scene_name,
|
||||||
|
Alembic::Abc::ErrorHandler::kThrowPolicy,
|
||||||
|
arg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
m_archive = Alembic::Abc::CreateArchiveWithInfo(Alembic::AbcCoreOgawa::WriteArchive(),
|
||||||
|
m_filename,
|
||||||
|
"Blender",
|
||||||
|
scene_name,
|
||||||
|
Alembic::Abc::ErrorHandler::kThrowPolicy,
|
||||||
|
arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create time samplings for transforms and shapes. */
|
||||||
|
|
||||||
|
TimeSamplingPtr trans_time = createTimeSampling(m_settings.frame_step_xform);
|
||||||
|
|
||||||
|
m_trans_sampling_index = m_archive.addTimeSampling(*trans_time);
|
||||||
|
|
||||||
|
TimeSamplingPtr shape_time;
|
||||||
|
|
||||||
|
if ((m_settings.frame_step_shape == m_settings.frame_step_xform) ||
|
||||||
|
(m_settings.frame_start == m_settings.frame_end))
|
||||||
|
{
|
||||||
|
shape_time = trans_time;
|
||||||
|
m_shape_sampling_index = m_trans_sampling_index;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
shape_time = createTimeSampling(m_settings.frame_step_shape);
|
||||||
|
m_shape_sampling_index = m_archive.addTimeSampling(*shape_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
OBox3dProperty archive_bounds_prop = Alembic::AbcGeom::CreateOArchiveBounds(m_archive, m_trans_sampling_index);
|
||||||
|
|
||||||
|
if (m_settings.flatten_hierarchy) {
|
||||||
|
createTransformWritersFlat();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
createTransformWritersHierarchy(bmain->eval_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
createShapeWriters(bmain->eval_ctx);
|
||||||
|
|
||||||
|
/* Make a list of frames to export. */
|
||||||
|
|
||||||
|
std::set<double> xform_frames;
|
||||||
|
getFrameSet(m_settings.frame_step_xform, xform_frames);
|
||||||
|
|
||||||
|
std::set<double> shape_frames;
|
||||||
|
getFrameSet(m_settings.frame_step_shape, shape_frames);
|
||||||
|
|
||||||
|
/* Merge all frames needed. */
|
||||||
|
|
||||||
|
std::set<double> frames(xform_frames);
|
||||||
|
frames.insert(shape_frames.begin(), shape_frames.end());
|
||||||
|
|
||||||
|
/* Export all frames. */
|
||||||
|
|
||||||
|
std::set<double>::const_iterator begin = frames.begin();
|
||||||
|
std::set<double>::const_iterator end = frames.end();
|
||||||
|
|
||||||
|
const float size = static_cast<float>(frames.size());
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
for (; begin != end; ++begin) {
|
||||||
|
progress = (++i / size);
|
||||||
|
|
||||||
|
if (G.is_break) {
|
||||||
|
was_canceled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
double f = *begin;
|
||||||
|
setCurrentFrame(bmain, f);
|
||||||
|
|
||||||
|
if (shape_frames.count(f) != 0) {
|
||||||
|
for (int i = 0, e = m_shapes.size(); i != e; ++i) {
|
||||||
|
m_shapes[i]->write();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xform_frames.count(f) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, AbcTransformWriter *>::iterator xit, xe;
|
||||||
|
for (xit = m_xforms.begin(), xe = m_xforms.end(); xit != xe; ++xit) {
|
||||||
|
xit->second->write();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save the archive 's bounding box. */
|
||||||
|
Imath::Box3d bounds;
|
||||||
|
|
||||||
|
for (xit = m_xforms.begin(), xe = m_xforms.end(); xit != xe; ++xit) {
|
||||||
|
Imath::Box3d box = xit->second->bounds();
|
||||||
|
bounds.extendBy(box);
|
||||||
|
}
|
||||||
|
|
||||||
|
archive_bounds_prop.set(bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcExporter::createTransformWritersHierarchy(EvaluationContext *eval_ctx)
|
||||||
|
{
|
||||||
|
Base *base = static_cast<Base *>(m_scene->base.first);
|
||||||
|
|
||||||
|
while (base) {
|
||||||
|
Object *ob = base->object;
|
||||||
|
|
||||||
|
if (export_object(&m_settings, ob)) {
|
||||||
|
switch(ob->type) {
|
||||||
|
case OB_LAMP:
|
||||||
|
case OB_LATTICE:
|
||||||
|
case OB_MBALL:
|
||||||
|
case OB_SPEAKER:
|
||||||
|
/* We do not export transforms for objects of these classes. */
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
exploreTransform(eval_ctx, ob, ob->parent, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
base = base->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcExporter::createTransformWritersFlat()
|
||||||
|
{
|
||||||
|
Base *base = static_cast<Base *>(m_scene->base.first);
|
||||||
|
|
||||||
|
while (base) {
|
||||||
|
Object *ob = base->object;
|
||||||
|
|
||||||
|
if (export_object(&m_settings, ob) && object_is_shape(ob)) {
|
||||||
|
std::string name = get_id_name(ob);
|
||||||
|
m_xforms[name] = new AbcTransformWriter(ob, m_archive.getTop(), 0, m_trans_sampling_index, m_settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
base = base->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Object *ob, Object *parent, Object *dupliObParent)
|
||||||
|
{
|
||||||
|
createTransformWriter(ob, parent, dupliObParent);
|
||||||
|
|
||||||
|
ListBase *lb = object_duplilist(eval_ctx, m_scene, ob);
|
||||||
|
|
||||||
|
if (lb) {
|
||||||
|
DupliObject *link = static_cast<DupliObject *>(lb->first);
|
||||||
|
Object *dupli_ob = NULL;
|
||||||
|
Object *dupli_parent = NULL;
|
||||||
|
|
||||||
|
while (link) {
|
||||||
|
if (link->type == OB_DUPLIGROUP) {
|
||||||
|
dupli_ob = link->ob;
|
||||||
|
dupli_parent = (dupli_ob->parent) ? dupli_ob->parent : ob;
|
||||||
|
|
||||||
|
exploreTransform(eval_ctx, dupli_ob, dupli_parent, ob);
|
||||||
|
}
|
||||||
|
|
||||||
|
link = link->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free_object_duplilist(lb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupliObParent)
|
||||||
|
{
|
||||||
|
const std::string name = get_object_dag_path_name(ob, dupliObParent);
|
||||||
|
|
||||||
|
/* check if we have already created a transform writer for this object */
|
||||||
|
if (m_xforms.find(name) != m_xforms.end()){
|
||||||
|
std::cerr << "xform " << name << " already exists\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbcTransformWriter *parent_xform = NULL;
|
||||||
|
|
||||||
|
if (parent) {
|
||||||
|
const std::string parentname = get_object_dag_path_name(parent, dupliObParent);
|
||||||
|
parent_xform = getXForm(parentname);
|
||||||
|
|
||||||
|
if (!parent_xform) {
|
||||||
|
if (parent->parent) {
|
||||||
|
createTransformWriter(parent, parent->parent, dupliObParent);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
createTransformWriter(parent, dupliObParent, dupliObParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
parent_xform = getXForm(parentname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent_xform) {
|
||||||
|
m_xforms[name] = new AbcTransformWriter(ob, parent_xform->alembicXform(), parent_xform, m_trans_sampling_index, m_settings);
|
||||||
|
m_xforms[name]->setParent(parent);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_xforms[name] = new AbcTransformWriter(ob, m_archive.getTop(), NULL, m_trans_sampling_index, m_settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcExporter::createShapeWriters(EvaluationContext *eval_ctx)
|
||||||
|
{
|
||||||
|
Base *base = static_cast<Base *>(m_scene->base.first);
|
||||||
|
|
||||||
|
while (base) {
|
||||||
|
Object *ob = base->object;
|
||||||
|
exploreObject(eval_ctx, ob, NULL);
|
||||||
|
|
||||||
|
base = base->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcExporter::exploreObject(EvaluationContext *eval_ctx, Object *ob, Object *dupliObParent)
|
||||||
|
{
|
||||||
|
ListBase *lb = object_duplilist(eval_ctx, m_scene, ob);
|
||||||
|
|
||||||
|
createShapeWriter(ob, dupliObParent);
|
||||||
|
|
||||||
|
if (lb) {
|
||||||
|
DupliObject *dupliob = static_cast<DupliObject *>(lb->first);
|
||||||
|
|
||||||
|
while (dupliob) {
|
||||||
|
if (dupliob->type == OB_DUPLIGROUP) {
|
||||||
|
exploreObject(eval_ctx, dupliob->ob, ob);
|
||||||
|
}
|
||||||
|
|
||||||
|
dupliob = dupliob->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free_object_duplilist(lb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent)
|
||||||
|
{
|
||||||
|
if (!object_is_shape(ob)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!export_object(&m_settings, ob)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
if (m_settings.flatten_hierarchy) {
|
||||||
|
name = get_id_name(ob);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
name = get_object_dag_path_name(ob, dupliObParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
AbcTransformWriter *xform = getXForm(name);
|
||||||
|
|
||||||
|
if (!xform) {
|
||||||
|
std::cerr << __func__ << ": xform " << name << " is NULL\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParticleSystem *psys = static_cast<ParticleSystem *>(ob->particlesystem.first);
|
||||||
|
|
||||||
|
for (; psys; psys = psys->next) {
|
||||||
|
if (!psys_check_enabled(ob, psys, G.is_rendering) || !psys->part) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (psys->part->type == PART_HAIR) {
|
||||||
|
m_settings.export_child_hairs = true;
|
||||||
|
m_shapes.push_back(new AbcHairWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys));
|
||||||
|
}
|
||||||
|
else if (psys->part->type == PART_EMITTER) {
|
||||||
|
m_shapes.push_back(new AbcPointsWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(ob->type) {
|
||||||
|
case OB_MESH:
|
||||||
|
{
|
||||||
|
Mesh *me = static_cast<Mesh *>(ob->data);
|
||||||
|
|
||||||
|
if (!me || me->totvert == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shapes.push_back(new AbcMeshWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OB_SURF:
|
||||||
|
{
|
||||||
|
Curve *cu = static_cast<Curve *>(ob->data);
|
||||||
|
|
||||||
|
if (!cu) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shapes.push_back(new AbcNurbsWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OB_CURVE:
|
||||||
|
{
|
||||||
|
Curve *cu = static_cast<Curve *>(ob->data);
|
||||||
|
|
||||||
|
if (!cu) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shapes.push_back(new AbcCurveWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OB_CAMERA:
|
||||||
|
{
|
||||||
|
Camera *cam = static_cast<Camera *>(ob->data);
|
||||||
|
|
||||||
|
if (cam->type == CAM_PERSP) {
|
||||||
|
m_shapes.push_back(new AbcCameraWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AbcTransformWriter *AbcExporter::getXForm(const std::string &name)
|
||||||
|
{
|
||||||
|
std::map<std::string, AbcTransformWriter *>::iterator it = m_xforms.find(name);
|
||||||
|
|
||||||
|
if (it == m_xforms.end()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcExporter::setCurrentFrame(Main *bmain, double t)
|
||||||
|
{
|
||||||
|
m_scene->r.cfra = std::floor(t);
|
||||||
|
m_scene->r.subframe = t - m_scene->r.cfra;
|
||||||
|
BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, m_scene, m_scene->lay);
|
||||||
|
}
|
112
source/blender/alembic/intern/abc_exporter.h
Normal file
112
source/blender/alembic/intern/abc_exporter.h
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ABC_EXPORTER_H__
|
||||||
|
#define __ABC_EXPORTER_H__
|
||||||
|
|
||||||
|
#include <Alembic/Abc/All.h>
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class AbcObjectWriter;
|
||||||
|
class AbcTransformWriter;
|
||||||
|
|
||||||
|
struct EvaluationContext;
|
||||||
|
struct Main;
|
||||||
|
struct Object;
|
||||||
|
struct Scene;
|
||||||
|
|
||||||
|
struct ExportSettings {
|
||||||
|
ExportSettings();
|
||||||
|
|
||||||
|
Scene *scene;
|
||||||
|
|
||||||
|
bool selected_only;
|
||||||
|
bool visible_layers_only;
|
||||||
|
bool renderable_only;
|
||||||
|
|
||||||
|
double frame_start, frame_end;
|
||||||
|
double frame_step_xform;
|
||||||
|
double frame_step_shape;
|
||||||
|
double shutter_open;
|
||||||
|
double shutter_close;
|
||||||
|
float global_scale;
|
||||||
|
|
||||||
|
bool flatten_hierarchy;
|
||||||
|
|
||||||
|
bool export_normals;
|
||||||
|
bool export_uvs;
|
||||||
|
bool export_vcols;
|
||||||
|
bool export_face_sets;
|
||||||
|
bool export_vweigths;
|
||||||
|
|
||||||
|
bool apply_subdiv;
|
||||||
|
bool use_subdiv_schema;
|
||||||
|
bool export_child_hairs;
|
||||||
|
bool export_ogawa;
|
||||||
|
bool pack_uv;
|
||||||
|
|
||||||
|
bool do_convert_axis;
|
||||||
|
float convert_matrix[3][3];
|
||||||
|
};
|
||||||
|
|
||||||
|
class AbcExporter {
|
||||||
|
ExportSettings &m_settings;
|
||||||
|
|
||||||
|
const char *m_filename;
|
||||||
|
|
||||||
|
Alembic::Abc::OArchive m_archive;
|
||||||
|
unsigned int m_trans_sampling_index, m_shape_sampling_index;
|
||||||
|
|
||||||
|
Scene *m_scene;
|
||||||
|
|
||||||
|
std::map<std::string, AbcTransformWriter *> m_xforms;
|
||||||
|
std::vector<AbcObjectWriter *> m_shapes;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AbcExporter(Scene *scene, const char *filename, ExportSettings &settings);
|
||||||
|
~AbcExporter();
|
||||||
|
|
||||||
|
void operator()(Main *bmain, float &progress, bool &was_canceled);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void getShutterSamples(double step, bool time_relative, std::vector<double> &samples);
|
||||||
|
|
||||||
|
Alembic::Abc::TimeSamplingPtr createTimeSampling(double step);
|
||||||
|
|
||||||
|
void getFrameSet(double step, std::set<double> &frames);
|
||||||
|
|
||||||
|
void createTransformWritersHierarchy(EvaluationContext *eval_ctx);
|
||||||
|
void createTransformWritersFlat();
|
||||||
|
void createTransformWriter(Object *ob, Object *parent, Object *dupliObParent);
|
||||||
|
void exploreTransform(EvaluationContext *eval_ctx, Object *ob, Object *parent, Object *dupliObParent = NULL);
|
||||||
|
void exploreObject(EvaluationContext *eval_ctx, Object *ob, Object *dupliObParent);
|
||||||
|
void createShapeWriters(EvaluationContext *eval_ctx);
|
||||||
|
void createShapeWriter(Object *ob, Object *dupliObParent);
|
||||||
|
|
||||||
|
AbcTransformWriter *getXForm(const std::string &name);
|
||||||
|
|
||||||
|
void setCurrentFrame(Main *bmain, double t);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __ABC_EXPORTER_H__ */
|
290
source/blender/alembic/intern/abc_hair.cc
Normal file
290
source/blender/alembic/intern/abc_hair.cc
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "abc_hair.h"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#include "abc_transform.h"
|
||||||
|
#include "abc_util.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
#include "DNA_modifier_types.h"
|
||||||
|
|
||||||
|
#include "BLI_listbase.h"
|
||||||
|
#include "BLI_math_geom.h"
|
||||||
|
|
||||||
|
#include "BKE_DerivedMesh.h"
|
||||||
|
#include "BKE_object.h"
|
||||||
|
#include "BKE_particle.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
using Alembic::Abc::P3fArraySamplePtr;
|
||||||
|
|
||||||
|
using Alembic::AbcGeom::OCurves;
|
||||||
|
using Alembic::AbcGeom::OCurvesSchema;
|
||||||
|
using Alembic::AbcGeom::ON3fGeomParam;
|
||||||
|
using Alembic::AbcGeom::OV2fGeomParam;
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
AbcHairWriter::AbcHairWriter(Scene *scene,
|
||||||
|
Object *ob,
|
||||||
|
AbcTransformWriter *parent,
|
||||||
|
uint32_t time_sampling,
|
||||||
|
ExportSettings &settings,
|
||||||
|
ParticleSystem *psys)
|
||||||
|
: AbcObjectWriter(scene, ob, time_sampling, settings, parent)
|
||||||
|
{
|
||||||
|
m_psys = psys;
|
||||||
|
|
||||||
|
OCurves curves(parent->alembicXform(), m_name, m_time_sampling);
|
||||||
|
m_schema = curves.getSchema();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcHairWriter::do_write()
|
||||||
|
{
|
||||||
|
if (!m_psys) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParticleSystemModifierData *psmd = psys_get_modifier(m_object, m_psys);
|
||||||
|
|
||||||
|
if (!psmd->dm_final) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DerivedMesh *dm = mesh_create_derived_view(m_scene, m_object, CD_MASK_MESH);
|
||||||
|
DM_ensure_tessface(dm);
|
||||||
|
DM_update_tessface_data(dm);
|
||||||
|
|
||||||
|
std::vector<Imath::V3f> verts;
|
||||||
|
std::vector<int32_t> hvertices;
|
||||||
|
std::vector<Imath::V2f> uv_values;
|
||||||
|
std::vector<Imath::V3f> norm_values;
|
||||||
|
|
||||||
|
if (m_psys->pathcache) {
|
||||||
|
ParticleSettings *part = m_psys->part;
|
||||||
|
|
||||||
|
write_hair_sample(dm, part, verts, norm_values, uv_values, hvertices);
|
||||||
|
|
||||||
|
if (m_settings.export_child_hairs && m_psys->childcache) {
|
||||||
|
write_hair_child_sample(dm, part, verts, norm_values, uv_values, hvertices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dm->release(dm);
|
||||||
|
|
||||||
|
Alembic::Abc::P3fArraySample iPos(verts);
|
||||||
|
m_sample = OCurvesSchema::Sample(iPos, hvertices);
|
||||||
|
m_sample.setBasis(Alembic::AbcGeom::kNoBasis);
|
||||||
|
m_sample.setType(Alembic::AbcGeom::kLinear);
|
||||||
|
m_sample.setWrap(Alembic::AbcGeom::kNonPeriodic);
|
||||||
|
|
||||||
|
if (!uv_values.empty()) {
|
||||||
|
OV2fGeomParam::Sample uv_smp;
|
||||||
|
uv_smp.setVals(uv_values);
|
||||||
|
m_sample.setUVs(uv_smp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!norm_values.empty()) {
|
||||||
|
ON3fGeomParam::Sample norm_smp;
|
||||||
|
norm_smp.setVals(norm_values);
|
||||||
|
m_sample.setNormals(norm_smp);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_sample.setSelfBounds(bounds());
|
||||||
|
m_schema.set(m_sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcHairWriter::write_hair_sample(DerivedMesh *dm,
|
||||||
|
ParticleSettings *part,
|
||||||
|
std::vector<Imath::V3f> &verts,
|
||||||
|
std::vector<Imath::V3f> &norm_values,
|
||||||
|
std::vector<Imath::V2f> &uv_values,
|
||||||
|
std::vector<int32_t> &hvertices)
|
||||||
|
{
|
||||||
|
/* Get untransformed vertices, there's a xform under the hair. */
|
||||||
|
float inv_mat[4][4];
|
||||||
|
invert_m4_m4_safe(inv_mat, m_object->obmat);
|
||||||
|
|
||||||
|
MTFace *mtface = static_cast<MTFace *>(CustomData_get_layer(&dm->faceData, CD_MTFACE));
|
||||||
|
MFace *mface = dm->getTessFaceArray(dm);
|
||||||
|
MVert *mverts = dm->getVertArray(dm);
|
||||||
|
|
||||||
|
if (!mtface || !mface) {
|
||||||
|
std::fprintf(stderr, "Warning, no UV set found for underlying geometry.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
ParticleData * pa = m_psys->particles;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
ParticleCacheKey **cache = m_psys->pathcache;
|
||||||
|
ParticleCacheKey *path;
|
||||||
|
float normal[3];
|
||||||
|
Imath::V3f tmp_nor;
|
||||||
|
|
||||||
|
for (int p = 0; p < m_psys->totpart; ++p, ++pa) {
|
||||||
|
/* underlying info for faces-only emission */
|
||||||
|
path = cache[p];
|
||||||
|
|
||||||
|
if (part->from == PART_FROM_FACE && mtface) {
|
||||||
|
const int num = pa->num_dmcache >= 0 ? pa->num_dmcache : pa->num;
|
||||||
|
|
||||||
|
if (num < dm->getNumTessFaces(dm)) {
|
||||||
|
MFace *face = static_cast<MFace *>(dm->getTessFaceData(dm, num, CD_MFACE));
|
||||||
|
MTFace *tface = mtface + num;
|
||||||
|
|
||||||
|
if (mface) {
|
||||||
|
float r_uv[2], mapfw[4], vec[3];
|
||||||
|
|
||||||
|
psys_interpolate_uvs(tface, face->v4, pa->fuv, r_uv);
|
||||||
|
uv_values.push_back(Imath::V2f(r_uv[0], r_uv[1]));
|
||||||
|
|
||||||
|
psys_interpolate_face(mverts, face, tface, NULL, mapfw, vec, normal, NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
copy_zup_yup(tmp_nor.getValue(), normal);
|
||||||
|
norm_values.push_back(tmp_nor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::fprintf(stderr, "Particle to faces overflow (%d/%d)\n", num, dm->getNumTessFaces(dm));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (part->from == PART_FROM_VERT && mtface) {
|
||||||
|
/* vertex id */
|
||||||
|
const int num = (pa->num_dmcache >= 0) ? pa->num_dmcache : pa->num;
|
||||||
|
|
||||||
|
/* iterate over all faces to find a corresponding underlying UV */
|
||||||
|
for (int n = 0; n < dm->getNumTessFaces(dm); ++n) {
|
||||||
|
MFace *face = static_cast<MFace *>(dm->getTessFaceData(dm, n, CD_MFACE));
|
||||||
|
MTFace *tface = mtface + n;
|
||||||
|
unsigned int vtx[4];
|
||||||
|
vtx[0] = face->v1;
|
||||||
|
vtx[1] = face->v2;
|
||||||
|
vtx[2] = face->v3;
|
||||||
|
vtx[3] = face->v4;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
for (int o = 0; o < 4; ++o) {
|
||||||
|
if (o > 2 && vtx[o] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vtx[o] == num) {
|
||||||
|
uv_values.push_back(Imath::V2f(tface->uv[o][0], tface->uv[o][1]));
|
||||||
|
|
||||||
|
MVert *mv = mverts + vtx[o];
|
||||||
|
|
||||||
|
normal_short_to_float_v3(normal, mv->no);
|
||||||
|
copy_zup_yup(tmp_nor.getValue(), normal);
|
||||||
|
norm_values.push_back(tmp_nor);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int steps = path->segments + 1;
|
||||||
|
hvertices.push_back(steps);
|
||||||
|
|
||||||
|
for (k = 0; k < steps; ++k) {
|
||||||
|
float vert[3];
|
||||||
|
copy_v3_v3(vert, path->co);
|
||||||
|
mul_m4_v3(inv_mat, vert);
|
||||||
|
|
||||||
|
/* Convert Z-up to Y-up. */
|
||||||
|
verts.push_back(Imath::V3f(vert[0], vert[2], -vert[1]));
|
||||||
|
|
||||||
|
++path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcHairWriter::write_hair_child_sample(DerivedMesh *dm,
|
||||||
|
ParticleSettings *part,
|
||||||
|
std::vector<Imath::V3f> &verts,
|
||||||
|
std::vector<Imath::V3f> &norm_values,
|
||||||
|
std::vector<Imath::V2f> &uv_values,
|
||||||
|
std::vector<int32_t> &hvertices)
|
||||||
|
{
|
||||||
|
/* Get untransformed vertices, there's a xform under the hair. */
|
||||||
|
float inv_mat[4][4];
|
||||||
|
invert_m4_m4_safe(inv_mat, m_object->obmat);
|
||||||
|
|
||||||
|
MTFace *mtface = static_cast<MTFace *>(CustomData_get_layer(&dm->faceData, CD_MTFACE));
|
||||||
|
MFace *mface = dm->getTessFaceArray(dm);
|
||||||
|
MVert *mverts = dm->getVertArray(dm);
|
||||||
|
|
||||||
|
if (!mtface || !mface) {
|
||||||
|
std::fprintf(stderr, "Warning, no UV set found for underlying geometry.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
ParticleCacheKey **cache = m_psys->childcache;
|
||||||
|
ParticleCacheKey *path;
|
||||||
|
|
||||||
|
ChildParticle *pc = m_psys->child;
|
||||||
|
|
||||||
|
for (int p = 0; p < m_psys->totchild; ++p, ++pc) {
|
||||||
|
path = cache[p];
|
||||||
|
|
||||||
|
if (part->from == PART_FROM_FACE) {
|
||||||
|
const int num = pc->num;
|
||||||
|
|
||||||
|
MFace *face = static_cast<MFace *>(dm->getTessFaceData(dm, num, CD_MFACE));
|
||||||
|
MTFace *tface = mtface + num;
|
||||||
|
|
||||||
|
if (mface && mtface) {
|
||||||
|
float r_uv[2], tmpnor[3], mapfw[4], vec[3];
|
||||||
|
|
||||||
|
psys_interpolate_uvs(tface, face->v4, pc->fuv, r_uv);
|
||||||
|
uv_values.push_back(Imath::V2f(r_uv[0], r_uv[1]));
|
||||||
|
|
||||||
|
psys_interpolate_face(mverts, face, tface, NULL, mapfw, vec, tmpnor, NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
/* Convert Z-up to Y-up. */
|
||||||
|
norm_values.push_back(Imath::V3f(tmpnor[0], tmpnor[2], -tmpnor[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int steps = path->segments + 1;
|
||||||
|
hvertices.push_back(steps);
|
||||||
|
|
||||||
|
for (int k = 0; k < steps; ++k) {
|
||||||
|
float vert[3];
|
||||||
|
copy_v3_v3(vert, path->co);
|
||||||
|
mul_m4_v3(inv_mat, vert);
|
||||||
|
|
||||||
|
/* Convert Z-up to Y-up. */
|
||||||
|
verts.push_back(Imath::V3f(vert[0], vert[2], -vert[1]));
|
||||||
|
|
||||||
|
++path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
66
source/blender/alembic/intern/abc_hair.h
Normal file
66
source/blender/alembic/intern/abc_hair.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ABC_HAIR_H__
|
||||||
|
#define __ABC_HAIR_H__
|
||||||
|
|
||||||
|
#include "abc_object.h"
|
||||||
|
|
||||||
|
struct DerivedMesh;
|
||||||
|
struct ParticleSettings;
|
||||||
|
struct ParticleSystem;
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
class AbcHairWriter : public AbcObjectWriter {
|
||||||
|
ParticleSystem *m_psys;
|
||||||
|
|
||||||
|
Alembic::AbcGeom::OCurvesSchema m_schema;
|
||||||
|
Alembic::AbcGeom::OCurvesSchema::Sample m_sample;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AbcHairWriter(Scene *scene,
|
||||||
|
Object *ob,
|
||||||
|
AbcTransformWriter *parent,
|
||||||
|
uint32_t time_sampling,
|
||||||
|
ExportSettings &settings,
|
||||||
|
ParticleSystem *psys);
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void do_write();
|
||||||
|
|
||||||
|
void write_hair_sample(DerivedMesh *dm,
|
||||||
|
ParticleSettings *part,
|
||||||
|
std::vector<Imath::V3f> &verts,
|
||||||
|
std::vector<Imath::V3f> &norm_values,
|
||||||
|
std::vector<Imath::V2f> &uv_values,
|
||||||
|
std::vector<int32_t> &hvertices);
|
||||||
|
|
||||||
|
void write_hair_child_sample(DerivedMesh *dm,
|
||||||
|
ParticleSettings *part,
|
||||||
|
std::vector<Imath::V3f> &verts,
|
||||||
|
std::vector<Imath::V3f> &norm_values,
|
||||||
|
std::vector<Imath::V2f> &uv_values,
|
||||||
|
std::vector<int32_t> &hvertices);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __ABC_HAIR_H__ */
|
1213
source/blender/alembic/intern/abc_mesh.cc
Normal file
1213
source/blender/alembic/intern/abc_mesh.cc
Normal file
File diff suppressed because it is too large
Load Diff
152
source/blender/alembic/intern/abc_mesh.h
Normal file
152
source/blender/alembic/intern/abc_mesh.h
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ABC_MESH_H__
|
||||||
|
#define __ABC_MESH_H__
|
||||||
|
|
||||||
|
#include "abc_customdata.h"
|
||||||
|
#include "abc_object.h"
|
||||||
|
|
||||||
|
struct DerivedMesh;
|
||||||
|
struct Mesh;
|
||||||
|
struct ModifierData;
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
class AbcMeshWriter : public AbcObjectWriter {
|
||||||
|
Alembic::AbcGeom::OPolyMeshSchema m_mesh_schema;
|
||||||
|
Alembic::AbcGeom::OPolyMeshSchema::Sample m_mesh_sample;
|
||||||
|
|
||||||
|
Alembic::AbcGeom::OSubDSchema m_subdiv_schema;
|
||||||
|
Alembic::AbcGeom::OSubDSchema::Sample m_subdiv_sample;
|
||||||
|
|
||||||
|
bool m_has_per_face_materials;
|
||||||
|
Alembic::AbcGeom::OFaceSet m_face_set;
|
||||||
|
Alembic::Abc::OArrayProperty m_mat_indices;
|
||||||
|
|
||||||
|
bool m_is_animated;
|
||||||
|
ModifierData *m_subsurf_mod;
|
||||||
|
|
||||||
|
CDStreamConfig m_custom_data_config;
|
||||||
|
|
||||||
|
bool m_is_liquid;
|
||||||
|
bool m_is_subd;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AbcMeshWriter(Scene *scene,
|
||||||
|
Object *ob,
|
||||||
|
AbcTransformWriter *parent,
|
||||||
|
uint32_t time_sampling,
|
||||||
|
ExportSettings &settings);
|
||||||
|
|
||||||
|
~AbcMeshWriter();
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void do_write();
|
||||||
|
|
||||||
|
bool isAnimated() const;
|
||||||
|
|
||||||
|
void writeMesh(DerivedMesh *dm);
|
||||||
|
void writeSubD(DerivedMesh *dm);
|
||||||
|
|
||||||
|
void getMeshInfo(DerivedMesh *dm, std::vector<float> &points,
|
||||||
|
std::vector<int32_t> &facePoints,
|
||||||
|
std::vector<int32_t> &faceCounts,
|
||||||
|
std::vector<int32_t> &creaseIndices,
|
||||||
|
std::vector<int32_t> &creaseLengths,
|
||||||
|
std::vector<float> &creaseSharpness);
|
||||||
|
|
||||||
|
DerivedMesh *getFinalMesh();
|
||||||
|
void freeMesh(DerivedMesh *dm);
|
||||||
|
|
||||||
|
void getMaterialIndices(DerivedMesh *dm, std::vector<int32_t> &indices);
|
||||||
|
|
||||||
|
void writeArbGeoParams(DerivedMesh *dm);
|
||||||
|
void getGeoGroups(DerivedMesh *dm, std::map<std::string, std::vector<int32_t> > &geoGroups);
|
||||||
|
|
||||||
|
/* fluid surfaces support */
|
||||||
|
void getVelocities(DerivedMesh *dm, std::vector<Imath::V3f> &vels);
|
||||||
|
|
||||||
|
template <typename Schema>
|
||||||
|
void writeCommonData(DerivedMesh *dm, Schema &schema);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
class AbcMeshReader : public AbcObjectReader {
|
||||||
|
Alembic::AbcGeom::IPolyMeshSchema m_schema;
|
||||||
|
|
||||||
|
CDStreamConfig m_mesh_data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AbcMeshReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
|
||||||
|
|
||||||
|
bool valid() const;
|
||||||
|
|
||||||
|
void readObjectData(Main *bmain, float time);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_start,
|
||||||
|
const Alembic::AbcGeom::ISampleSelector &sample_sel);
|
||||||
|
};
|
||||||
|
|
||||||
|
void read_mesh_sample(ImportSettings *settings,
|
||||||
|
const Alembic::AbcGeom::IPolyMeshSchema &schema,
|
||||||
|
const Alembic::AbcGeom::ISampleSelector &selector,
|
||||||
|
CDStreamConfig &config,
|
||||||
|
bool &do_normals);
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
class AbcSubDReader : public AbcObjectReader {
|
||||||
|
Alembic::AbcGeom::ISubDSchema m_schema;
|
||||||
|
|
||||||
|
CDStreamConfig m_mesh_data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AbcSubDReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
|
||||||
|
|
||||||
|
bool valid() const;
|
||||||
|
|
||||||
|
void readObjectData(Main *bmain, float time);
|
||||||
|
};
|
||||||
|
|
||||||
|
void read_subd_sample(ImportSettings *settings,
|
||||||
|
const Alembic::AbcGeom::ISubDSchema &schema,
|
||||||
|
const Alembic::AbcGeom::ISampleSelector &selector,
|
||||||
|
CDStreamConfig &config);
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
|
void mesh_add_verts(struct Mesh *mesh, size_t len);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_mverts(MVert *mverts,
|
||||||
|
const Alembic::AbcGeom::P3fArraySamplePtr &positions,
|
||||||
|
const Alembic::AbcGeom::N3fArraySamplePtr &normals);
|
||||||
|
|
||||||
|
CDStreamConfig create_config(Mesh *mesh);
|
||||||
|
|
||||||
|
#endif /* __ABC_MESH_H__ */
|
367
source/blender/alembic/intern/abc_nurbs.cc
Normal file
367
source/blender/alembic/intern/abc_nurbs.cc
Normal file
@ -0,0 +1,367 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "abc_nurbs.h"
|
||||||
|
|
||||||
|
#include "abc_transform.h"
|
||||||
|
#include "abc_util.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
#include "DNA_curve_types.h"
|
||||||
|
#include "DNA_object_types.h"
|
||||||
|
|
||||||
|
#include "BLI_listbase.h"
|
||||||
|
#include "BLI_math.h"
|
||||||
|
#include "BLI_string.h"
|
||||||
|
|
||||||
|
#include "BKE_curve.h"
|
||||||
|
#include "BKE_object.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
using Alembic::AbcGeom::bool_t;
|
||||||
|
using Alembic::AbcGeom::FloatArraySample;
|
||||||
|
using Alembic::AbcGeom::FloatArraySamplePtr;
|
||||||
|
using Alembic::AbcGeom::MetaData;
|
||||||
|
using Alembic::AbcGeom::P3fArraySamplePtr;
|
||||||
|
using Alembic::AbcGeom::kWrapExisting;
|
||||||
|
|
||||||
|
using Alembic::AbcGeom::IBoolProperty;
|
||||||
|
using Alembic::AbcGeom::ICompoundProperty;
|
||||||
|
using Alembic::AbcGeom::INuPatch;
|
||||||
|
using Alembic::AbcGeom::INuPatchSchema;
|
||||||
|
using Alembic::AbcGeom::IObject;
|
||||||
|
using Alembic::AbcGeom::ISampleSelector;
|
||||||
|
|
||||||
|
using Alembic::AbcGeom::OBoolProperty;
|
||||||
|
using Alembic::AbcGeom::OCompoundProperty;
|
||||||
|
using Alembic::AbcGeom::ONuPatch;
|
||||||
|
using Alembic::AbcGeom::ONuPatchSchema;
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
AbcNurbsWriter::AbcNurbsWriter(Scene *scene,
|
||||||
|
Object *ob,
|
||||||
|
AbcTransformWriter *parent,
|
||||||
|
uint32_t time_sampling,
|
||||||
|
ExportSettings &settings)
|
||||||
|
: AbcObjectWriter(scene, ob, time_sampling, settings, parent)
|
||||||
|
{
|
||||||
|
m_is_animated = isAnimated();
|
||||||
|
|
||||||
|
/* if the object is static, use the default static time sampling */
|
||||||
|
if (!m_is_animated) {
|
||||||
|
m_time_sampling = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Curve *curve = static_cast<Curve *>(m_object->data);
|
||||||
|
size_t numNurbs = BLI_listbase_count(&curve->nurb);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < numNurbs; ++i) {
|
||||||
|
std::stringstream str;
|
||||||
|
str << m_name << '_' << i;
|
||||||
|
|
||||||
|
while (parent->alembicXform().getChildHeader(str.str())) {
|
||||||
|
str << "_";
|
||||||
|
}
|
||||||
|
|
||||||
|
ONuPatch nurbs(parent->alembicXform(), str.str().c_str(), m_time_sampling);
|
||||||
|
m_nurbs_schema.push_back(nurbs.getSchema());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AbcNurbsWriter::isAnimated() const
|
||||||
|
{
|
||||||
|
/* check if object has shape keys */
|
||||||
|
Curve *cu = static_cast<Curve *>(m_object->data);
|
||||||
|
return (cu->key != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_knots(std::vector<float> &knots, const int num_knots, float *nu_knots)
|
||||||
|
{
|
||||||
|
if (num_knots <= 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add an extra knot at the beggining and end of the array since most apps
|
||||||
|
* require/expect them. */
|
||||||
|
knots.reserve(num_knots + 2);
|
||||||
|
|
||||||
|
knots.push_back(0.0f);
|
||||||
|
|
||||||
|
for (int i = 0; i < num_knots; ++i) {
|
||||||
|
knots.push_back(nu_knots[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
knots[0] = 2.0f * knots[1] - knots[2];
|
||||||
|
knots.push_back(2.0f * knots[num_knots] - knots[num_knots - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcNurbsWriter::do_write()
|
||||||
|
{
|
||||||
|
/* we have already stored a sample for this object. */
|
||||||
|
if (!m_first_frame && !m_is_animated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ELEM(m_object->type, OB_SURF, OB_CURVE)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Curve *curve = static_cast<Curve *>(m_object->data);
|
||||||
|
ListBase *nulb;
|
||||||
|
|
||||||
|
if (m_object->curve_cache->deformed_nurbs.first != NULL) {
|
||||||
|
nulb = &m_object->curve_cache->deformed_nurbs;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nulb = BKE_curve_nurbs_get(curve);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t count = 0;
|
||||||
|
for (Nurb *nu = static_cast<Nurb *>(nulb->first); nu; nu = nu->next, ++count) {
|
||||||
|
std::vector<float> knotsU;
|
||||||
|
get_knots(knotsU, KNOTSU(nu), nu->knotsu);
|
||||||
|
|
||||||
|
std::vector<float> knotsV;
|
||||||
|
get_knots(knotsV, KNOTSV(nu), nu->knotsv);
|
||||||
|
|
||||||
|
const int size = nu->pntsu * nu->pntsv;
|
||||||
|
std::vector<Imath::V3f> positions(size);
|
||||||
|
std::vector<float> weights(size);
|
||||||
|
|
||||||
|
const BPoint *bp = nu->bp;
|
||||||
|
|
||||||
|
for (int i = 0; i < size; ++i, ++bp) {
|
||||||
|
copy_zup_yup(positions[i].getValue(), bp->vec);
|
||||||
|
weights[i] = bp->vec[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
ONuPatchSchema::Sample sample;
|
||||||
|
sample.setUOrder(nu->orderu + 1);
|
||||||
|
sample.setVOrder(nu->orderv + 1);
|
||||||
|
sample.setPositions(positions);
|
||||||
|
sample.setPositionWeights(weights);
|
||||||
|
sample.setUKnot(FloatArraySample(knotsU));
|
||||||
|
sample.setVKnot(FloatArraySample(knotsV));
|
||||||
|
sample.setNu(nu->pntsu);
|
||||||
|
sample.setNv(nu->pntsv);
|
||||||
|
|
||||||
|
/* TODO(kevin): to accomodate other software we should duplicate control
|
||||||
|
* points to indicate that a NURBS is cyclic. */
|
||||||
|
OCompoundProperty user_props = m_nurbs_schema[count].getUserProperties();
|
||||||
|
|
||||||
|
if ((nu->flagu & CU_NURB_ENDPOINT) != 0) {
|
||||||
|
OBoolProperty prop(user_props, "endpoint_u");
|
||||||
|
prop.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((nu->flagv & CU_NURB_ENDPOINT) != 0) {
|
||||||
|
OBoolProperty prop(user_props, "endpoint_v");
|
||||||
|
prop.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((nu->flagu & CU_NURB_CYCLIC) != 0) {
|
||||||
|
OBoolProperty prop(user_props, "cyclic_u");
|
||||||
|
prop.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((nu->flagv & CU_NURB_CYCLIC) != 0) {
|
||||||
|
OBoolProperty prop(user_props, "cyclic_v");
|
||||||
|
prop.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_nurbs_schema[count].set(sample);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
AbcNurbsReader::AbcNurbsReader(const IObject &object, ImportSettings &settings)
|
||||||
|
: AbcObjectReader(object, settings)
|
||||||
|
{
|
||||||
|
getNurbsPatches(m_iobject);
|
||||||
|
get_min_max_time(m_schemas[0].first, m_min_time, m_max_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AbcNurbsReader::valid() const
|
||||||
|
{
|
||||||
|
if (m_schemas.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector< std::pair<INuPatchSchema, IObject> >::const_iterator it;
|
||||||
|
for (it = m_schemas.begin(); it != m_schemas.end(); ++it) {
|
||||||
|
const INuPatchSchema &schema = it->first;
|
||||||
|
|
||||||
|
if (!schema.valid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool set_knots(const FloatArraySamplePtr &knots, float *&nu_knots)
|
||||||
|
{
|
||||||
|
if (!knots || knots->size() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip first and last knots, as they are used for padding. */
|
||||||
|
const size_t num_knots = knots->size() - 2;
|
||||||
|
nu_knots = static_cast<float *>(MEM_callocN(num_knots * sizeof(float), "abc_setsplineknotsu"));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < num_knots; ++i) {
|
||||||
|
nu_knots[i] = (*knots)[i + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcNurbsReader::readObjectData(Main *bmain, float time)
|
||||||
|
{
|
||||||
|
Curve *cu = static_cast<Curve *>(BKE_curve_add(bmain, "abc_curve", OB_SURF));
|
||||||
|
cu->actvert = CU_ACT_NONE;
|
||||||
|
|
||||||
|
std::vector< std::pair<INuPatchSchema, IObject> >::iterator it;
|
||||||
|
|
||||||
|
for (it = m_schemas.begin(); it != m_schemas.end(); ++it) {
|
||||||
|
Nurb *nu = static_cast<Nurb *>(MEM_callocN(sizeof(Nurb), "abc_getnurb"));
|
||||||
|
nu->flag = CU_SMOOTH;
|
||||||
|
nu->type = CU_NURBS;
|
||||||
|
nu->resolu = cu->resolu;
|
||||||
|
nu->resolv = cu->resolv;
|
||||||
|
|
||||||
|
const ISampleSelector sample_sel(time);
|
||||||
|
const INuPatchSchema &schema = it->first;
|
||||||
|
const INuPatchSchema::Sample smp = schema.getValue(sample_sel);
|
||||||
|
|
||||||
|
nu->orderu = smp.getUOrder() - 1;
|
||||||
|
nu->orderv = smp.getVOrder() - 1;
|
||||||
|
nu->pntsu = smp.getNumU();
|
||||||
|
nu->pntsv = smp.getNumV();
|
||||||
|
|
||||||
|
/* Read positions and weights. */
|
||||||
|
|
||||||
|
const P3fArraySamplePtr positions = smp.getPositions();
|
||||||
|
const FloatArraySamplePtr weights = smp.getPositionWeights();
|
||||||
|
|
||||||
|
const size_t num_points = positions->size();
|
||||||
|
|
||||||
|
nu->bp = static_cast<BPoint *>(MEM_callocN(num_points * sizeof(BPoint), "abc_setsplinetype"));
|
||||||
|
|
||||||
|
BPoint *bp = nu->bp;
|
||||||
|
float posw_in = 1.0f;
|
||||||
|
|
||||||
|
for (int i = 0; i < num_points; ++i, ++bp) {
|
||||||
|
const Imath::V3f &pos_in = (*positions)[i];
|
||||||
|
|
||||||
|
if (weights) {
|
||||||
|
posw_in = (*weights)[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_yup_zup(bp->vec, pos_in.getValue());
|
||||||
|
bp->vec[3] = posw_in;
|
||||||
|
bp->f1 = SELECT;
|
||||||
|
bp->radius = 1.0f;
|
||||||
|
bp->weight = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read knots. */
|
||||||
|
|
||||||
|
if (!set_knots(smp.getUKnot(), nu->knotsu)) {
|
||||||
|
BKE_nurb_knot_calc_u(nu);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!set_knots(smp.getVKnot(), nu->knotsv)) {
|
||||||
|
BKE_nurb_knot_calc_v(nu);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read flags. */
|
||||||
|
|
||||||
|
ICompoundProperty user_props = schema.getUserProperties();
|
||||||
|
|
||||||
|
if (has_property(user_props, "enpoint_u")) {
|
||||||
|
nu->flagu |= CU_NURB_ENDPOINT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_property(user_props, "enpoint_v")) {
|
||||||
|
nu->flagv |= CU_NURB_ENDPOINT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_property(user_props, "cyclic_u")) {
|
||||||
|
nu->flagu |= CU_NURB_CYCLIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_property(user_props, "cyclic_v")) {
|
||||||
|
nu->flagv |= CU_NURB_CYCLIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLI_addtail(BKE_curve_nurbs_get(cu), nu);
|
||||||
|
}
|
||||||
|
|
||||||
|
BLI_strncpy(cu->id.name + 2, m_data_name.c_str(), m_data_name.size() + 1);
|
||||||
|
|
||||||
|
m_object = BKE_object_add_only_object(bmain, OB_SURF, m_object_name.c_str());
|
||||||
|
m_object->data = cu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcNurbsReader::getNurbsPatches(const IObject &obj)
|
||||||
|
{
|
||||||
|
if (!obj.valid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int num_children = obj.getNumChildren();
|
||||||
|
|
||||||
|
if (num_children == 0) {
|
||||||
|
INuPatch abc_nurb(obj, kWrapExisting);
|
||||||
|
INuPatchSchema schem = abc_nurb.getSchema();
|
||||||
|
m_schemas.push_back(std::pair<INuPatchSchema, IObject>(schem, obj));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < num_children; ++i) {
|
||||||
|
bool ok = true;
|
||||||
|
IObject child(obj, obj.getChildHeader(i).getName());
|
||||||
|
|
||||||
|
if (!m_name.empty() && child.valid() && !begins_with(child.getFullName(), m_name)) {
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!child.valid()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MetaData &md = child.getMetaData();
|
||||||
|
|
||||||
|
if (INuPatch::matches(md) && ok) {
|
||||||
|
INuPatch abc_nurb(child, kWrapExisting);
|
||||||
|
INuPatchSchema schem = abc_nurb.getSchema();
|
||||||
|
m_schemas.push_back(std::pair<INuPatchSchema, IObject>(schem, child));
|
||||||
|
}
|
||||||
|
|
||||||
|
getNurbsPatches(child);
|
||||||
|
}
|
||||||
|
}
|
63
source/blender/alembic/intern/abc_nurbs.h
Normal file
63
source/blender/alembic/intern/abc_nurbs.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ABC_NURBS_H__
|
||||||
|
#define __ABC_NURBS_H__
|
||||||
|
|
||||||
|
#include "abc_object.h"
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
class AbcNurbsWriter : public AbcObjectWriter {
|
||||||
|
std::vector<Alembic::AbcGeom::ONuPatchSchema> m_nurbs_schema;
|
||||||
|
bool m_is_animated;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AbcNurbsWriter(Scene *scene,
|
||||||
|
Object *ob,
|
||||||
|
AbcTransformWriter *parent,
|
||||||
|
uint32_t time_sampling,
|
||||||
|
ExportSettings &settings);
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void do_write();
|
||||||
|
|
||||||
|
bool isAnimated() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
class AbcNurbsReader : public AbcObjectReader {
|
||||||
|
std::vector< std::pair<Alembic::AbcGeom::INuPatchSchema, Alembic::Abc::IObject> > m_schemas;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AbcNurbsReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
|
||||||
|
|
||||||
|
bool valid() const;
|
||||||
|
|
||||||
|
void readObjectData(Main *bmain, float time);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void getNurbsPatches(const Alembic::Abc::IObject &obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __ABC_NURBS_H__ */
|
238
source/blender/alembic/intern/abc_object.cc
Normal file
238
source/blender/alembic/intern/abc_object.cc
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "abc_object.h"
|
||||||
|
|
||||||
|
#include "abc_util.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
|
#include "DNA_constraint_types.h"
|
||||||
|
#include "DNA_modifier_types.h"
|
||||||
|
#include "DNA_object_types.h"
|
||||||
|
#include "DNA_space_types.h" /* for FILE_MAX */
|
||||||
|
|
||||||
|
#include "BKE_constraint.h"
|
||||||
|
#include "BKE_depsgraph.h"
|
||||||
|
#include "BKE_idprop.h"
|
||||||
|
#include "BKE_library.h"
|
||||||
|
#include "BKE_modifier.h"
|
||||||
|
#include "BKE_object.h"
|
||||||
|
|
||||||
|
#include "BLI_listbase.h"
|
||||||
|
#include "BLI_math.h"
|
||||||
|
#include "BLI_string.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
using Alembic::AbcGeom::IObject;
|
||||||
|
using Alembic::AbcGeom::IXform;
|
||||||
|
using Alembic::AbcGeom::IXformSchema;
|
||||||
|
|
||||||
|
using Alembic::AbcGeom::OCompoundProperty;
|
||||||
|
using Alembic::AbcGeom::ODoubleArrayProperty;
|
||||||
|
using Alembic::AbcGeom::ODoubleProperty;
|
||||||
|
using Alembic::AbcGeom::OFloatArrayProperty;
|
||||||
|
using Alembic::AbcGeom::OFloatProperty;
|
||||||
|
using Alembic::AbcGeom::OInt32ArrayProperty;
|
||||||
|
using Alembic::AbcGeom::OInt32Property;
|
||||||
|
using Alembic::AbcGeom::OStringArrayProperty;
|
||||||
|
using Alembic::AbcGeom::OStringProperty;
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
AbcObjectWriter::AbcObjectWriter(Scene *scene,
|
||||||
|
Object *ob,
|
||||||
|
uint32_t time_sampling,
|
||||||
|
ExportSettings &settings,
|
||||||
|
AbcObjectWriter *parent)
|
||||||
|
: m_object(ob)
|
||||||
|
, m_settings(settings)
|
||||||
|
, m_scene(scene)
|
||||||
|
, m_time_sampling(time_sampling)
|
||||||
|
, m_first_frame(true)
|
||||||
|
{
|
||||||
|
m_name = get_id_name(m_object) + "Shape";
|
||||||
|
|
||||||
|
if (parent) {
|
||||||
|
parent->addChild(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AbcObjectWriter::~AbcObjectWriter()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void AbcObjectWriter::addChild(AbcObjectWriter *child)
|
||||||
|
{
|
||||||
|
m_children.push_back(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
Imath::Box3d AbcObjectWriter::bounds()
|
||||||
|
{
|
||||||
|
BoundBox *bb = BKE_object_boundbox_get(this->m_object);
|
||||||
|
|
||||||
|
if (!bb) {
|
||||||
|
if (this->m_object->type != OB_CAMERA) {
|
||||||
|
std::cerr << "Boundbox is null!\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return Imath::Box3d();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert Z-up to Y-up. */
|
||||||
|
this->m_bounds.min.x = bb->vec[0][0];
|
||||||
|
this->m_bounds.min.y = bb->vec[0][2];
|
||||||
|
this->m_bounds.min.z = -bb->vec[0][1];
|
||||||
|
|
||||||
|
this->m_bounds.max.x = bb->vec[6][0];
|
||||||
|
this->m_bounds.max.y = bb->vec[6][2];
|
||||||
|
this->m_bounds.max.z = -bb->vec[6][1];
|
||||||
|
|
||||||
|
return this->m_bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcObjectWriter::write()
|
||||||
|
{
|
||||||
|
do_write();
|
||||||
|
m_first_frame = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
AbcObjectReader::AbcObjectReader(const IObject &object, ImportSettings &settings)
|
||||||
|
: m_name("")
|
||||||
|
, m_object_name("")
|
||||||
|
, m_data_name("")
|
||||||
|
, m_object(NULL)
|
||||||
|
, m_iobject(object)
|
||||||
|
, m_settings(&settings)
|
||||||
|
, m_min_time(std::numeric_limits<chrono_t>::max())
|
||||||
|
, m_max_time(std::numeric_limits<chrono_t>::min())
|
||||||
|
{
|
||||||
|
m_name = object.getFullName();
|
||||||
|
std::vector<std::string> parts;
|
||||||
|
split(m_name, '/', parts);
|
||||||
|
|
||||||
|
if (parts.size() >= 2) {
|
||||||
|
m_object_name = parts[parts.size() - 2];
|
||||||
|
m_data_name = parts[parts.size() - 1];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_object_name = m_data_name = parts[parts.size() - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AbcObjectReader::~AbcObjectReader()
|
||||||
|
{}
|
||||||
|
|
||||||
|
const IObject &AbcObjectReader::iobject() const
|
||||||
|
{
|
||||||
|
return m_iobject;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object *AbcObjectReader::object() const
|
||||||
|
{
|
||||||
|
return m_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcObjectReader::readObjectMatrix(const float time)
|
||||||
|
{
|
||||||
|
IXform ixform;
|
||||||
|
bool has_alembic_parent = false;
|
||||||
|
|
||||||
|
/* Check that we have an empty object (locator, bone head/tail...). */
|
||||||
|
if (IXform::matches(m_iobject.getMetaData())) {
|
||||||
|
ixform = IXform(m_iobject, Alembic::AbcGeom::kWrapExisting);
|
||||||
|
|
||||||
|
/* See comment below. */
|
||||||
|
has_alembic_parent = m_iobject.getParent().getParent().valid();
|
||||||
|
}
|
||||||
|
/* Check that we have an object with actual data. */
|
||||||
|
else if (IXform::matches(m_iobject.getParent().getMetaData())) {
|
||||||
|
ixform = IXform(m_iobject.getParent(), Alembic::AbcGeom::kWrapExisting);
|
||||||
|
|
||||||
|
/* This is a bit hackish, but we need to make sure that extra
|
||||||
|
* transformations added to the matrix (rotation/scale) are only applied
|
||||||
|
* to root objects. The way objects and their hierarchy are created will
|
||||||
|
* need to be revisited at some point but for now this seems to do the
|
||||||
|
* trick.
|
||||||
|
*
|
||||||
|
* Explanation of the trick:
|
||||||
|
* The first getParent() will return this object's transformation matrix.
|
||||||
|
* The second getParent() will get the parent of the transform, but this
|
||||||
|
* might be the archive root ('/') which is valid, so we go passed it to
|
||||||
|
* make sure that there is no parent.
|
||||||
|
*/
|
||||||
|
has_alembic_parent = m_iobject.getParent().getParent().getParent().valid();
|
||||||
|
}
|
||||||
|
/* Should not happen. */
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const IXformSchema &schema(ixform.getSchema());
|
||||||
|
|
||||||
|
if (!schema.valid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Alembic::AbcGeom::ISampleSelector sample_sel(time);
|
||||||
|
Alembic::AbcGeom::XformSample xs;
|
||||||
|
schema.get(xs, sample_sel);
|
||||||
|
|
||||||
|
create_input_transform(sample_sel, ixform, m_object, m_object->obmat, m_settings->scale, has_alembic_parent);
|
||||||
|
|
||||||
|
invert_m4_m4(m_object->imat, m_object->obmat);
|
||||||
|
|
||||||
|
BKE_object_apply_mat4(m_object, m_object->obmat, false, false);
|
||||||
|
|
||||||
|
if (!schema.isConstant()) {
|
||||||
|
bConstraint *con = BKE_constraint_add_for_object(m_object, NULL, CONSTRAINT_TYPE_TRANSFORM_CACHE);
|
||||||
|
bTransformCacheConstraint *data = static_cast<bTransformCacheConstraint *>(con->data);
|
||||||
|
BLI_strncpy(data->object_path, m_iobject.getFullName().c_str(), FILE_MAX);
|
||||||
|
|
||||||
|
data->cache_file = m_settings->cache_file;
|
||||||
|
id_us_plus(&data->cache_file->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcObjectReader::addCacheModifier() const
|
||||||
|
{
|
||||||
|
ModifierData *md = modifier_new(eModifierType_MeshSequenceCache);
|
||||||
|
BLI_addtail(&m_object->modifiers, md);
|
||||||
|
|
||||||
|
MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
|
||||||
|
|
||||||
|
mcmd->cache_file = m_settings->cache_file;
|
||||||
|
id_us_plus(&mcmd->cache_file->id);
|
||||||
|
|
||||||
|
BLI_strncpy(mcmd->object_path, m_iobject.getFullName().c_str(), FILE_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
chrono_t AbcObjectReader::minTime() const
|
||||||
|
{
|
||||||
|
return m_min_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
chrono_t AbcObjectReader::maxTime() const
|
||||||
|
{
|
||||||
|
return m_max_time;
|
||||||
|
}
|
169
source/blender/alembic/intern/abc_object.h
Normal file
169
source/blender/alembic/intern/abc_object.h
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ABC_OBJECT_H__
|
||||||
|
#define __ABC_OBJECT_H__
|
||||||
|
|
||||||
|
#include <Alembic/Abc/All.h>
|
||||||
|
#include <Alembic/AbcGeom/All.h>
|
||||||
|
|
||||||
|
#include "abc_exporter.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "DNA_ID.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
class AbcTransformWriter;
|
||||||
|
|
||||||
|
struct Main;
|
||||||
|
struct Object;
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
class AbcObjectWriter {
|
||||||
|
protected:
|
||||||
|
Object *m_object;
|
||||||
|
ExportSettings &m_settings;
|
||||||
|
|
||||||
|
Scene *m_scene;
|
||||||
|
uint32_t m_time_sampling;
|
||||||
|
|
||||||
|
Imath::Box3d m_bounds;
|
||||||
|
std::vector<AbcObjectWriter *> m_children;
|
||||||
|
|
||||||
|
std::vector< std::pair<std::string, IDProperty *> > m_props;
|
||||||
|
|
||||||
|
bool m_first_frame;
|
||||||
|
std::string m_name;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AbcObjectWriter(Scene *scene,
|
||||||
|
Object *ob,
|
||||||
|
uint32_t time_sampling,
|
||||||
|
ExportSettings &settings,
|
||||||
|
AbcObjectWriter *parent = NULL);
|
||||||
|
|
||||||
|
virtual ~AbcObjectWriter();
|
||||||
|
|
||||||
|
void addChild(AbcObjectWriter *child);
|
||||||
|
|
||||||
|
virtual Imath::Box3d bounds();
|
||||||
|
|
||||||
|
void write();
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void do_write() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
class CacheFile;
|
||||||
|
|
||||||
|
struct ImportSettings {
|
||||||
|
bool do_convert_mat;
|
||||||
|
float conversion_mat[4][4];
|
||||||
|
|
||||||
|
int from_up;
|
||||||
|
int from_forward;
|
||||||
|
float scale;
|
||||||
|
bool is_sequence;
|
||||||
|
bool set_frame_range;
|
||||||
|
|
||||||
|
/* Length and frame offset of file sequences. */
|
||||||
|
int sequence_len;
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
/* From MeshSeqCacheModifierData.read_flag */
|
||||||
|
int read_flag;
|
||||||
|
|
||||||
|
bool validate_meshes;
|
||||||
|
|
||||||
|
CacheFile *cache_file;
|
||||||
|
|
||||||
|
ImportSettings()
|
||||||
|
: do_convert_mat(false)
|
||||||
|
, from_up(0)
|
||||||
|
, from_forward(0)
|
||||||
|
, scale(1.0f)
|
||||||
|
, is_sequence(false)
|
||||||
|
, set_frame_range(false)
|
||||||
|
, sequence_len(1)
|
||||||
|
, offset(0)
|
||||||
|
, read_flag(0)
|
||||||
|
, validate_meshes(false)
|
||||||
|
, cache_file(NULL)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Schema>
|
||||||
|
static bool has_animations(Schema &schema, ImportSettings *settings)
|
||||||
|
{
|
||||||
|
if (settings->is_sequence) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!schema.isConstant()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
using Alembic::AbcCoreAbstract::chrono_t;
|
||||||
|
|
||||||
|
class AbcObjectReader {
|
||||||
|
protected:
|
||||||
|
std::string m_name;
|
||||||
|
std::string m_object_name;
|
||||||
|
std::string m_data_name;
|
||||||
|
Object *m_object;
|
||||||
|
Alembic::Abc::IObject m_iobject;
|
||||||
|
|
||||||
|
ImportSettings *m_settings;
|
||||||
|
|
||||||
|
chrono_t m_min_time;
|
||||||
|
chrono_t m_max_time;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit AbcObjectReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
|
||||||
|
|
||||||
|
virtual ~AbcObjectReader();
|
||||||
|
|
||||||
|
const Alembic::Abc::IObject &iobject() const;
|
||||||
|
|
||||||
|
Object *object() const;
|
||||||
|
|
||||||
|
virtual bool valid() const = 0;
|
||||||
|
|
||||||
|
virtual void readObjectData(Main *bmain, float time) = 0;
|
||||||
|
|
||||||
|
void readObjectMatrix(const float time);
|
||||||
|
|
||||||
|
void addCacheModifier() const;
|
||||||
|
|
||||||
|
chrono_t minTime() const;
|
||||||
|
chrono_t maxTime() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __ABC_OBJECT_H__ */
|
198
source/blender/alembic/intern/abc_points.cc
Normal file
198
source/blender/alembic/intern/abc_points.cc
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2016 Kévin Dietrich.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "abc_points.h"
|
||||||
|
|
||||||
|
#include "abc_mesh.h"
|
||||||
|
#include "abc_transform.h"
|
||||||
|
#include "abc_util.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "DNA_mesh_types.h"
|
||||||
|
|
||||||
|
#include "BKE_lattice.h"
|
||||||
|
#include "BKE_mesh.h"
|
||||||
|
#include "BKE_object.h"
|
||||||
|
#include "BKE_particle.h"
|
||||||
|
#include "BKE_scene.h"
|
||||||
|
|
||||||
|
#include "BLI_math.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
using Alembic::AbcGeom::kVertexScope;
|
||||||
|
using Alembic::AbcGeom::kWrapExisting;
|
||||||
|
using Alembic::AbcGeom::P3fArraySamplePtr;
|
||||||
|
using Alembic::AbcGeom::N3fArraySamplePtr;
|
||||||
|
|
||||||
|
using Alembic::AbcGeom::ICompoundProperty;
|
||||||
|
using Alembic::AbcGeom::IN3fArrayProperty;
|
||||||
|
using Alembic::AbcGeom::IPoints;
|
||||||
|
using Alembic::AbcGeom::IPointsSchema;
|
||||||
|
using Alembic::AbcGeom::ISampleSelector;
|
||||||
|
|
||||||
|
using Alembic::AbcGeom::OPoints;
|
||||||
|
using Alembic::AbcGeom::OPointsSchema;
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
AbcPointsWriter::AbcPointsWriter(Scene *scene,
|
||||||
|
Object *ob,
|
||||||
|
AbcTransformWriter *parent,
|
||||||
|
uint32_t time_sampling,
|
||||||
|
ExportSettings &settings,
|
||||||
|
ParticleSystem *psys)
|
||||||
|
: AbcObjectWriter(scene, ob, time_sampling, settings, parent)
|
||||||
|
{
|
||||||
|
m_psys = psys;
|
||||||
|
|
||||||
|
OPoints points(parent->alembicXform(), m_name, m_time_sampling);
|
||||||
|
m_schema = points.getSchema();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcPointsWriter::do_write()
|
||||||
|
{
|
||||||
|
if (!m_psys) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Imath::V3f> points;
|
||||||
|
std::vector<Imath::V3f> velocities;
|
||||||
|
std::vector<float> widths;
|
||||||
|
std::vector<uint64_t> ids;
|
||||||
|
|
||||||
|
ParticleKey state;
|
||||||
|
|
||||||
|
ParticleSimulationData sim;
|
||||||
|
sim.scene = m_scene;
|
||||||
|
sim.ob = m_object;
|
||||||
|
sim.psys = m_psys;
|
||||||
|
|
||||||
|
m_psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
|
||||||
|
|
||||||
|
uint64_t index = 0;
|
||||||
|
for (int p = 0; p < m_psys->totpart; p++) {
|
||||||
|
float pos[3], vel[3];
|
||||||
|
|
||||||
|
if (m_psys->particles[p].flag & (PARS_NO_DISP | PARS_UNEXIST)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.time = BKE_scene_frame_get(m_scene);
|
||||||
|
|
||||||
|
if (psys_get_particle_state(&sim, p, &state, 0) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* location */
|
||||||
|
mul_v3_m4v3(pos, m_object->imat, state.co);
|
||||||
|
|
||||||
|
/* velocity */
|
||||||
|
sub_v3_v3v3(vel, state.co, m_psys->particles[p].prev_state.co);
|
||||||
|
|
||||||
|
/* Convert Z-up to Y-up. */
|
||||||
|
points.push_back(Imath::V3f(pos[0], pos[2], -pos[1]));
|
||||||
|
velocities.push_back(Imath::V3f(vel[0], vel[2], -vel[1]));
|
||||||
|
widths.push_back(m_psys->particles[p].size);
|
||||||
|
ids.push_back(index++);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_psys->lattice_deform_data) {
|
||||||
|
end_latt_deform(m_psys->lattice_deform_data);
|
||||||
|
m_psys->lattice_deform_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Alembic::Abc::P3fArraySample psample(points);
|
||||||
|
Alembic::Abc::UInt64ArraySample idsample(ids);
|
||||||
|
Alembic::Abc::V3fArraySample vsample(velocities);
|
||||||
|
Alembic::Abc::FloatArraySample wsample_array(widths);
|
||||||
|
Alembic::AbcGeom::OFloatGeomParam::Sample wsample(wsample_array, kVertexScope);
|
||||||
|
|
||||||
|
m_sample = OPointsSchema::Sample(psample, idsample, vsample, wsample);
|
||||||
|
m_sample.setSelfBounds(bounds());
|
||||||
|
|
||||||
|
m_schema.set(m_sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
AbcPointsReader::AbcPointsReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
|
||||||
|
: AbcObjectReader(object, settings)
|
||||||
|
{
|
||||||
|
IPoints ipoints(m_iobject, kWrapExisting);
|
||||||
|
m_schema = ipoints.getSchema();
|
||||||
|
get_min_max_time(m_schema, m_min_time, m_max_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AbcPointsReader::valid() const
|
||||||
|
{
|
||||||
|
return m_schema.valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcPointsReader::readObjectData(Main *bmain, float time)
|
||||||
|
{
|
||||||
|
Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str());
|
||||||
|
|
||||||
|
const ISampleSelector sample_sel(time);
|
||||||
|
m_sample = m_schema.getValue(sample_sel);
|
||||||
|
|
||||||
|
const P3fArraySamplePtr &positions = m_sample.getPositions();
|
||||||
|
utils::mesh_add_verts(mesh, positions->size());
|
||||||
|
|
||||||
|
CDStreamConfig config = create_config(mesh);
|
||||||
|
read_points_sample(m_schema, sample_sel, config, time);
|
||||||
|
|
||||||
|
if (m_settings->validate_meshes) {
|
||||||
|
BKE_mesh_validate(mesh, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str());
|
||||||
|
m_object->data = mesh;
|
||||||
|
|
||||||
|
if (has_animations(m_schema, m_settings)) {
|
||||||
|
addCacheModifier();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_points_sample(const IPointsSchema &schema,
|
||||||
|
const ISampleSelector &selector,
|
||||||
|
CDStreamConfig &config,
|
||||||
|
float time)
|
||||||
|
{
|
||||||
|
Alembic::AbcGeom::IPointsSchema::Sample sample = schema.getValue(selector);
|
||||||
|
|
||||||
|
const P3fArraySamplePtr &positions = sample.getPositions();
|
||||||
|
|
||||||
|
ICompoundProperty prop = schema.getArbGeomParams();
|
||||||
|
N3fArraySamplePtr vnormals;
|
||||||
|
|
||||||
|
if (has_property(prop, "N")) {
|
||||||
|
const IN3fArrayProperty &normals_prop = IN3fArrayProperty(prop, "N", time);
|
||||||
|
|
||||||
|
if (normals_prop) {
|
||||||
|
vnormals = normals_prop.getValue(selector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
read_mverts(config.mvert, positions, vnormals);
|
||||||
|
}
|
70
source/blender/alembic/intern/abc_points.h
Normal file
70
source/blender/alembic/intern/abc_points.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2016 Kévin Dietrich.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ABC_POINTS_H__
|
||||||
|
#define __ABC_POINTS_H__
|
||||||
|
|
||||||
|
#include "abc_object.h"
|
||||||
|
#include "abc_customdata.h"
|
||||||
|
|
||||||
|
class ParticleSystem;
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
class AbcPointsWriter : public AbcObjectWriter {
|
||||||
|
Alembic::AbcGeom::OPointsSchema m_schema;
|
||||||
|
Alembic::AbcGeom::OPointsSchema::Sample m_sample;
|
||||||
|
ParticleSystem *m_psys;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AbcPointsWriter(Scene *scene,
|
||||||
|
Object *ob,
|
||||||
|
AbcTransformWriter *parent,
|
||||||
|
uint32_t time_sampling,
|
||||||
|
ExportSettings &settings,
|
||||||
|
ParticleSystem *psys);
|
||||||
|
|
||||||
|
void do_write();
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
class AbcPointsReader : public AbcObjectReader {
|
||||||
|
Alembic::AbcGeom::IPointsSchema m_schema;
|
||||||
|
Alembic::AbcGeom::IPointsSchema::Sample m_sample;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AbcPointsReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
|
||||||
|
|
||||||
|
bool valid() const;
|
||||||
|
|
||||||
|
void readObjectData(Main *bmain, float time);
|
||||||
|
};
|
||||||
|
|
||||||
|
void read_points_sample(const Alembic::AbcGeom::IPointsSchema &schema,
|
||||||
|
const Alembic::AbcGeom::ISampleSelector &selector,
|
||||||
|
CDStreamConfig &config,
|
||||||
|
float time);
|
||||||
|
|
||||||
|
#endif /* __ABC_POINTS_H__ */
|
152
source/blender/alembic/intern/abc_transform.cc
Normal file
152
source/blender/alembic/intern/abc_transform.cc
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "abc_transform.h"
|
||||||
|
|
||||||
|
#include <OpenEXR/ImathBoxAlgo.h>
|
||||||
|
|
||||||
|
#include "abc_util.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "DNA_object_types.h"
|
||||||
|
|
||||||
|
#include "BLI_math.h"
|
||||||
|
|
||||||
|
#include "BKE_object.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
using Alembic::AbcGeom::OObject;
|
||||||
|
using Alembic::AbcGeom::OXform;
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
static bool has_parent_camera(Object *ob)
|
||||||
|
{
|
||||||
|
if (!ob->parent) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object *parent = ob->parent;
|
||||||
|
|
||||||
|
if (parent->type == OB_CAMERA) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return has_parent_camera(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
AbcTransformWriter::AbcTransformWriter(Object *ob,
|
||||||
|
const OObject &abc_parent,
|
||||||
|
AbcTransformWriter *parent,
|
||||||
|
unsigned int time_sampling,
|
||||||
|
ExportSettings &settings)
|
||||||
|
: AbcObjectWriter(NULL, ob, time_sampling, settings, parent)
|
||||||
|
{
|
||||||
|
m_is_animated = hasAnimation(m_object);
|
||||||
|
m_parent = NULL;
|
||||||
|
|
||||||
|
if (!m_is_animated) {
|
||||||
|
time_sampling = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_xform = OXform(abc_parent, get_id_name(m_object), time_sampling);
|
||||||
|
m_schema = m_xform.getSchema();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcTransformWriter::do_write()
|
||||||
|
{
|
||||||
|
if (m_first_frame) {
|
||||||
|
m_visibility = Alembic::AbcGeom::CreateVisibilityProperty(m_xform, m_xform.getSchema().getTimeSampling());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_visibility.set(!(m_object->restrictflag & OB_RESTRICT_VIEW));
|
||||||
|
|
||||||
|
if (!m_first_frame && !m_is_animated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float mat[4][4];
|
||||||
|
create_transform_matrix(m_object, mat);
|
||||||
|
|
||||||
|
/* Only apply rotation to root camera, parenting will propagate it. */
|
||||||
|
if (m_object->type == OB_CAMERA && !has_parent_camera(m_object)) {
|
||||||
|
float rot_mat[4][4];
|
||||||
|
unit_m4(rot_mat);
|
||||||
|
rotate_m4(rot_mat, 'X', -M_PI_2);
|
||||||
|
mul_m4_m4m4(mat, mat, rot_mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_object->parent) {
|
||||||
|
/* Only apply scaling to root objects, parenting will propagate it. */
|
||||||
|
float scale_mat[4][4];
|
||||||
|
scale_m4_fl(scale_mat, m_settings.global_scale);
|
||||||
|
mul_m4_m4m4(mat, mat, scale_mat);
|
||||||
|
mul_v3_fl(mat[3], m_settings.global_scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_matrix = convert_matrix(mat);
|
||||||
|
|
||||||
|
m_sample.setMatrix(m_matrix);
|
||||||
|
m_schema.set(m_sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
Imath::Box3d AbcTransformWriter::bounds()
|
||||||
|
{
|
||||||
|
Imath::Box3d bounds;
|
||||||
|
|
||||||
|
for (int i = 0; i < m_children.size(); ++i) {
|
||||||
|
Imath::Box3d box(m_children[i]->bounds());
|
||||||
|
bounds.extendBy(box);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Imath::transform(bounds, m_matrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AbcTransformWriter::hasAnimation(Object */*ob*/) const
|
||||||
|
{
|
||||||
|
/* TODO(kevin): implement this. */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
AbcEmptyReader::AbcEmptyReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
|
||||||
|
: AbcObjectReader(object, settings)
|
||||||
|
{
|
||||||
|
Alembic::AbcGeom::IXform xform(object, Alembic::AbcGeom::kWrapExisting);
|
||||||
|
m_schema = xform.getSchema();
|
||||||
|
|
||||||
|
get_min_max_time(m_schema, m_min_time, m_max_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AbcEmptyReader::valid() const
|
||||||
|
{
|
||||||
|
return m_schema.valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbcEmptyReader::readObjectData(Main *bmain, float /*time*/)
|
||||||
|
{
|
||||||
|
m_object = BKE_object_add_only_object(bmain, OB_EMPTY, m_object_name.c_str());
|
||||||
|
m_object->data = NULL;
|
||||||
|
}
|
73
source/blender/alembic/intern/abc_transform.h
Normal file
73
source/blender/alembic/intern/abc_transform.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ABC_TRANSFORM_H__
|
||||||
|
#define __ABC_TRANSFORM_H__
|
||||||
|
|
||||||
|
#include "abc_object.h"
|
||||||
|
|
||||||
|
#include <Alembic/AbcGeom/All.h>
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
class AbcTransformWriter : public AbcObjectWriter {
|
||||||
|
Alembic::AbcGeom::OXform m_xform;
|
||||||
|
Alembic::AbcGeom::OXformSchema m_schema;
|
||||||
|
Alembic::AbcGeom::XformSample m_sample;
|
||||||
|
Alembic::AbcGeom::OVisibilityProperty m_visibility;
|
||||||
|
Alembic::Abc::M44d m_matrix;
|
||||||
|
|
||||||
|
bool m_is_animated;
|
||||||
|
Object *m_parent;
|
||||||
|
bool m_visible;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AbcTransformWriter(Object *ob,
|
||||||
|
const Alembic::AbcGeom::OObject &abc_parent,
|
||||||
|
AbcTransformWriter *parent,
|
||||||
|
unsigned int time_sampling,
|
||||||
|
ExportSettings &settings);
|
||||||
|
|
||||||
|
Alembic::AbcGeom::OXform &alembicXform() { return m_xform;}
|
||||||
|
virtual Imath::Box3d bounds();
|
||||||
|
void setParent(Object *p) { m_parent = p; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void do_write();
|
||||||
|
|
||||||
|
bool hasAnimation(Object *ob) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
class AbcEmptyReader : public AbcObjectReader {
|
||||||
|
Alembic::AbcGeom::IXformSchema m_schema;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AbcEmptyReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
|
||||||
|
|
||||||
|
bool valid() const;
|
||||||
|
|
||||||
|
void readObjectData(Main *bmain, float time);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __ABC_TRANSFORM_H__ */
|
437
source/blender/alembic/intern/abc_util.cc
Normal file
437
source/blender/alembic/intern/abc_util.cc
Normal file
@ -0,0 +1,437 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "abc_util.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "DNA_object_types.h"
|
||||||
|
|
||||||
|
#include "BLI_math.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string get_id_name(Object *ob)
|
||||||
|
{
|
||||||
|
if (!ob) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return get_id_name(&ob->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string get_id_name(ID *id)
|
||||||
|
{
|
||||||
|
std::string name(id->name + 2);
|
||||||
|
std::replace(name.begin(), name.end(), ' ', '_');
|
||||||
|
std::replace(name.begin(), name.end(), '.', '_');
|
||||||
|
std::replace(name.begin(), name.end(), ':', '_');
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string get_object_dag_path_name(Object *ob, Object *dupli_parent)
|
||||||
|
{
|
||||||
|
std::string name = get_id_name(ob);
|
||||||
|
|
||||||
|
Object *p = ob->parent;
|
||||||
|
|
||||||
|
while (p) {
|
||||||
|
name = get_id_name(p) + "/" + name;
|
||||||
|
p = p->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dupli_parent && (ob != dupli_parent)) {
|
||||||
|
name = get_id_name(dupli_parent) + "/" + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool object_selected(Object *ob)
|
||||||
|
{
|
||||||
|
return ob->flag & SELECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parent_selected(Object *ob)
|
||||||
|
{
|
||||||
|
if (object_selected(ob)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool do_export = false;
|
||||||
|
|
||||||
|
Object *parent = ob->parent;
|
||||||
|
|
||||||
|
while (parent != NULL) {
|
||||||
|
if (object_selected(parent)) {
|
||||||
|
do_export = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent = parent->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return do_export;
|
||||||
|
}
|
||||||
|
|
||||||
|
Imath::M44d convert_matrix(float mat[4][4])
|
||||||
|
{
|
||||||
|
Imath::M44d m;
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
for (int j = 0; j < 4; ++j) {
|
||||||
|
m[i][j] = mat[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
void split(const std::string &s, const char delim, std::vector<std::string> &tokens)
|
||||||
|
{
|
||||||
|
tokens.clear();
|
||||||
|
|
||||||
|
std::stringstream ss(s);
|
||||||
|
std::string item;
|
||||||
|
|
||||||
|
while (std::getline(ss, item, delim)) {
|
||||||
|
if (!item.empty()) {
|
||||||
|
tokens.push_back(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a rotation matrix for each axis from euler angles.
|
||||||
|
* Euler angles are swaped to change coordinate system. */
|
||||||
|
static void create_rotation_matrix(
|
||||||
|
float rot_x_mat[3][3], float rot_y_mat[3][3],
|
||||||
|
float rot_z_mat[3][3], const float euler[3], const bool to_yup)
|
||||||
|
{
|
||||||
|
const float rx = euler[0];
|
||||||
|
const float ry = (to_yup) ? euler[2] : -euler[2];
|
||||||
|
const float rz = (to_yup) ? -euler[1] : euler[1];
|
||||||
|
|
||||||
|
unit_m3(rot_x_mat);
|
||||||
|
unit_m3(rot_y_mat);
|
||||||
|
unit_m3(rot_z_mat);
|
||||||
|
|
||||||
|
rot_x_mat[1][1] = cos(rx);
|
||||||
|
rot_x_mat[2][1] = -sin(rx);
|
||||||
|
rot_x_mat[1][2] = sin(rx);
|
||||||
|
rot_x_mat[2][2] = cos(rx);
|
||||||
|
|
||||||
|
rot_y_mat[2][2] = cos(ry);
|
||||||
|
rot_y_mat[0][2] = -sin(ry);
|
||||||
|
rot_y_mat[2][0] = sin(ry);
|
||||||
|
rot_y_mat[0][0] = cos(ry);
|
||||||
|
|
||||||
|
rot_z_mat[0][0] = cos(rz);
|
||||||
|
rot_z_mat[1][0] = -sin(rz);
|
||||||
|
rot_z_mat[0][1] = sin(rz);
|
||||||
|
rot_z_mat[1][1] = cos(rz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Recompute transform matrix of object in new coordinate system
|
||||||
|
* (from Y-Up to Z-Up). */
|
||||||
|
void create_transform_matrix(float r_mat[4][4])
|
||||||
|
{
|
||||||
|
float rot_mat[3][3], rot[3][3], scale_mat[4][4], invmat[4][4], transform_mat[4][4];
|
||||||
|
float rot_x_mat[3][3], rot_y_mat[3][3], rot_z_mat[3][3];
|
||||||
|
float loc[3], scale[3], euler[3];
|
||||||
|
|
||||||
|
zero_v3(loc);
|
||||||
|
zero_v3(scale);
|
||||||
|
zero_v3(euler);
|
||||||
|
unit_m3(rot);
|
||||||
|
unit_m3(rot_mat);
|
||||||
|
unit_m4(scale_mat);
|
||||||
|
unit_m4(transform_mat);
|
||||||
|
unit_m4(invmat);
|
||||||
|
|
||||||
|
/* Compute rotation matrix. */
|
||||||
|
|
||||||
|
/* Extract location, rotation, and scale from matrix. */
|
||||||
|
mat4_to_loc_rot_size(loc, rot, scale, r_mat);
|
||||||
|
|
||||||
|
/* Get euler angles from rotation matrix. */
|
||||||
|
mat3_to_eulO(euler, ROT_MODE_XYZ, rot);
|
||||||
|
|
||||||
|
/* Create X, Y, Z rotation matrices from euler angles. */
|
||||||
|
create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, false);
|
||||||
|
|
||||||
|
/* Concatenate rotation matrices. */
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
|
||||||
|
|
||||||
|
/* Add rotation matrix to transformation matrix. */
|
||||||
|
copy_m4_m3(transform_mat, rot_mat);
|
||||||
|
|
||||||
|
/* Add translation to transformation matrix. */
|
||||||
|
copy_yup_zup(transform_mat[3], loc);
|
||||||
|
|
||||||
|
/* Create scale matrix. */
|
||||||
|
scale_mat[0][0] = scale[0];
|
||||||
|
scale_mat[1][1] = scale[2];
|
||||||
|
scale_mat[2][2] = scale[1];
|
||||||
|
|
||||||
|
/* Add scale to transformation matrix. */
|
||||||
|
mul_m4_m4m4(transform_mat, transform_mat, scale_mat);
|
||||||
|
|
||||||
|
copy_m4_m4(r_mat, transform_mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_input_transform(const Alembic::AbcGeom::ISampleSelector &sample_sel,
|
||||||
|
const Alembic::AbcGeom::IXform &ixform, Object *ob,
|
||||||
|
float r_mat[4][4], float scale, bool has_alembic_parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
const Alembic::AbcGeom::IXformSchema &ixform_schema = ixform.getSchema();
|
||||||
|
Alembic::AbcGeom::XformSample xs;
|
||||||
|
ixform_schema.get(xs, sample_sel);
|
||||||
|
const Imath::M44d &xform = xs.getMatrix();
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
for (int j = 0; j < 4; ++j) {
|
||||||
|
r_mat[i][j] = xform[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ob->type == OB_CAMERA) {
|
||||||
|
float cam_to_yup[4][4];
|
||||||
|
unit_m4(cam_to_yup);
|
||||||
|
rotate_m4(cam_to_yup, 'X', M_PI_2);
|
||||||
|
mul_m4_m4m4(r_mat, r_mat, cam_to_yup);
|
||||||
|
}
|
||||||
|
|
||||||
|
create_transform_matrix(r_mat);
|
||||||
|
|
||||||
|
if (ob->parent) {
|
||||||
|
mul_m4_m4m4(r_mat, ob->parent->obmat, r_mat);
|
||||||
|
}
|
||||||
|
/* TODO(kevin) */
|
||||||
|
else if (!has_alembic_parent) {
|
||||||
|
/* Only apply scaling to root objects, parenting will propagate it. */
|
||||||
|
float scale_mat[4][4];
|
||||||
|
scale_m4_fl(scale_mat, scale);
|
||||||
|
mul_m4_m4m4(r_mat, r_mat, scale_mat);
|
||||||
|
mul_v3_fl(r_mat[3], scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Recompute transform matrix of object in new coordinate system (from Z-Up to Y-Up). */
|
||||||
|
void create_transform_matrix(Object *obj, float transform_mat[4][4])
|
||||||
|
{
|
||||||
|
float rot_mat[3][3], rot[3][3], scale_mat[4][4], invmat[4][4], mat[4][4];
|
||||||
|
float rot_x_mat[3][3], rot_y_mat[3][3], rot_z_mat[3][3];
|
||||||
|
float loc[3], scale[3], euler[3];
|
||||||
|
|
||||||
|
zero_v3(loc);
|
||||||
|
zero_v3(scale);
|
||||||
|
zero_v3(euler);
|
||||||
|
unit_m3(rot);
|
||||||
|
unit_m3(rot_mat);
|
||||||
|
unit_m4(scale_mat);
|
||||||
|
unit_m4(transform_mat);
|
||||||
|
unit_m4(invmat);
|
||||||
|
unit_m4(mat);
|
||||||
|
|
||||||
|
/* get local matrix. */
|
||||||
|
if (obj->parent) {
|
||||||
|
invert_m4_m4(invmat, obj->parent->obmat);
|
||||||
|
mul_m4_m4m4(mat, invmat, obj->obmat);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
copy_m4_m4(mat, obj->obmat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute rotation matrix. */
|
||||||
|
switch (obj->rotmode) {
|
||||||
|
case ROT_MODE_AXISANGLE:
|
||||||
|
{
|
||||||
|
/* Get euler angles from axis angle rotation. */
|
||||||
|
axis_angle_to_eulO(euler, ROT_MODE_XYZ, obj->rotAxis, obj->rotAngle);
|
||||||
|
|
||||||
|
/* Create X, Y, Z rotation matrices from euler angles. */
|
||||||
|
create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
|
||||||
|
|
||||||
|
/* Concatenate rotation matrices. */
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
|
||||||
|
|
||||||
|
/* Extract location and scale from matrix. */
|
||||||
|
mat4_to_loc_rot_size(loc, rot, scale, mat);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ROT_MODE_QUAT:
|
||||||
|
{
|
||||||
|
float q[4];
|
||||||
|
copy_v4_v4(q, obj->quat);
|
||||||
|
|
||||||
|
/* Swap axis. */
|
||||||
|
q[2] = obj->quat[3];
|
||||||
|
q[3] = -obj->quat[2];
|
||||||
|
|
||||||
|
/* Compute rotation matrix from quaternion. */
|
||||||
|
quat_to_mat3(rot_mat, q);
|
||||||
|
|
||||||
|
/* Extract location and scale from matrix. */
|
||||||
|
mat4_to_loc_rot_size(loc, rot, scale, mat);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ROT_MODE_XYZ:
|
||||||
|
{
|
||||||
|
/* Extract location, rotation, and scale form matrix. */
|
||||||
|
mat4_to_loc_rot_size(loc, rot, scale, mat);
|
||||||
|
|
||||||
|
/* Get euler angles from rotation matrix. */
|
||||||
|
mat3_to_eulO(euler, ROT_MODE_XYZ, rot);
|
||||||
|
|
||||||
|
/* Create X, Y, Z rotation matrices from euler angles. */
|
||||||
|
create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
|
||||||
|
|
||||||
|
/* Concatenate rotation matrices. */
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ROT_MODE_XZY:
|
||||||
|
{
|
||||||
|
/* Extract location, rotation, and scale form matrix. */
|
||||||
|
mat4_to_loc_rot_size(loc, rot, scale, mat);
|
||||||
|
|
||||||
|
/* Get euler angles from rotation matrix. */
|
||||||
|
mat3_to_eulO(euler, ROT_MODE_XZY, rot);
|
||||||
|
|
||||||
|
/* Create X, Y, Z rotation matrices from euler angles. */
|
||||||
|
create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
|
||||||
|
|
||||||
|
/* Concatenate rotation matrices. */
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ROT_MODE_YXZ:
|
||||||
|
{
|
||||||
|
/* Extract location, rotation, and scale form matrix. */
|
||||||
|
mat4_to_loc_rot_size(loc, rot, scale, mat);
|
||||||
|
|
||||||
|
/* Get euler angles from rotation matrix. */
|
||||||
|
mat3_to_eulO(euler, ROT_MODE_YXZ, rot);
|
||||||
|
|
||||||
|
/* Create X, Y, Z rotation matrices from euler angles. */
|
||||||
|
create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
|
||||||
|
|
||||||
|
/* Concatenate rotation matrices. */
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ROT_MODE_YZX:
|
||||||
|
{
|
||||||
|
/* Extract location, rotation, and scale form matrix. */
|
||||||
|
mat4_to_loc_rot_size(loc, rot, scale, mat);
|
||||||
|
|
||||||
|
/* Get euler angles from rotation matrix. */
|
||||||
|
mat3_to_eulO(euler, ROT_MODE_YZX, rot);
|
||||||
|
|
||||||
|
/* Create X, Y, Z rotation matrices from euler angles. */
|
||||||
|
create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
|
||||||
|
|
||||||
|
/* Concatenate rotation matrices. */
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ROT_MODE_ZXY:
|
||||||
|
{
|
||||||
|
/* Extract location, rotation, and scale form matrix. */
|
||||||
|
mat4_to_loc_rot_size(loc, rot, scale, mat);
|
||||||
|
|
||||||
|
/* Get euler angles from rotation matrix. */
|
||||||
|
mat3_to_eulO(euler, ROT_MODE_ZXY, rot);
|
||||||
|
|
||||||
|
/* Create X, Y, Z rotation matrices from euler angles. */
|
||||||
|
create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
|
||||||
|
|
||||||
|
/* Concatenate rotation matrices. */
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ROT_MODE_ZYX:
|
||||||
|
{
|
||||||
|
/* Extract location, rotation, and scale form matrix. */
|
||||||
|
mat4_to_loc_rot_size(loc, rot, scale, mat);
|
||||||
|
|
||||||
|
/* Get euler angles from rotation matrix. */
|
||||||
|
mat3_to_eulO(euler, ROT_MODE_ZYX, rot);
|
||||||
|
|
||||||
|
/* Create X, Y, Z rotation matrices from euler angles. */
|
||||||
|
create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
|
||||||
|
|
||||||
|
/* Concatenate rotation matrices. */
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
|
||||||
|
mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add rotation matrix to transformation matrix. */
|
||||||
|
copy_m4_m3(transform_mat, rot_mat);
|
||||||
|
|
||||||
|
/* Add translation to transformation matrix. */
|
||||||
|
copy_zup_yup(transform_mat[3], loc);
|
||||||
|
|
||||||
|
/* Create scale matrix. */
|
||||||
|
scale_mat[0][0] = scale[0];
|
||||||
|
scale_mat[1][1] = scale[2];
|
||||||
|
scale_mat[2][2] = scale[1];
|
||||||
|
|
||||||
|
/* Add scale to transformation matrix. */
|
||||||
|
mul_m4_m4m4(transform_mat, transform_mat, scale_mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name)
|
||||||
|
{
|
||||||
|
if (!prop.valid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prop.getPropertyHeader(name) != NULL;
|
||||||
|
}
|
125
source/blender/alembic/intern/abc_util.h
Normal file
125
source/blender/alembic/intern/abc_util.h
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Contributor(s): Esteban Tovagliari, Cedric Paille, Kevin Dietrich
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ABC_UTIL_H__
|
||||||
|
#define __ABC_UTIL_H__
|
||||||
|
|
||||||
|
#include <Alembic/Abc/All.h>
|
||||||
|
#include <Alembic/AbcGeom/All.h>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# define ABC_INLINE static __forceinline
|
||||||
|
#else
|
||||||
|
# define ABC_INLINE static inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using Alembic::Abc::chrono_t;
|
||||||
|
|
||||||
|
class ImportSettings;
|
||||||
|
|
||||||
|
struct ID;
|
||||||
|
struct Object;
|
||||||
|
|
||||||
|
std::string get_id_name(ID *id);
|
||||||
|
std::string get_id_name(Object *ob);
|
||||||
|
std::string get_object_dag_path_name(Object *ob, Object *dupli_parent);
|
||||||
|
|
||||||
|
bool object_selected(Object *ob);
|
||||||
|
bool parent_selected(Object *ob);
|
||||||
|
|
||||||
|
Imath::M44d convert_matrix(float mat[4][4]);
|
||||||
|
void create_transform_matrix(float r_mat[4][4]);
|
||||||
|
void create_transform_matrix(Object *obj, float transform_mat[4][4]);
|
||||||
|
|
||||||
|
void split(const std::string &s, const char delim, std::vector<std::string> &tokens);
|
||||||
|
|
||||||
|
template<class TContainer>
|
||||||
|
bool begins_with(const TContainer &input, const TContainer &match)
|
||||||
|
{
|
||||||
|
return input.size() >= match.size()
|
||||||
|
&& std::equal(match.begin(), match.end(), input.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_input_transform(const Alembic::AbcGeom::ISampleSelector &sample_sel,
|
||||||
|
const Alembic::AbcGeom::IXform &ixform, Object *ob,
|
||||||
|
float r_mat[4][4], float scale, bool has_alembic_parent = false);
|
||||||
|
|
||||||
|
template <typename Schema>
|
||||||
|
void get_min_max_time(const Schema &schema, chrono_t &min, chrono_t &max)
|
||||||
|
{
|
||||||
|
const Alembic::Abc::TimeSamplingPtr &time_samp = schema.getTimeSampling();
|
||||||
|
|
||||||
|
if (!schema.isConstant()) {
|
||||||
|
const size_t num_samps = schema.getNumSamples();
|
||||||
|
|
||||||
|
if (num_samps > 0) {
|
||||||
|
const chrono_t min_time = time_samp->getSampleTime(0);
|
||||||
|
min = std::min(min, min_time);
|
||||||
|
|
||||||
|
const chrono_t max_time = time_samp->getSampleTime(num_samps - 1);
|
||||||
|
max = std::max(max, max_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name);
|
||||||
|
|
||||||
|
/* ************************** */
|
||||||
|
|
||||||
|
/* TODO(kevin): for now keeping these transformations hardcoded to make sure
|
||||||
|
* everything works properly, and also because Alembic is almost exclusively
|
||||||
|
* used in Y-up software, but eventually they'll be set by the user in the UI
|
||||||
|
* like other importers/exporters do, to support other axis. */
|
||||||
|
|
||||||
|
/* Copy from Y-up to Z-up. */
|
||||||
|
|
||||||
|
ABC_INLINE void copy_yup_zup(float zup[3], const float yup[3])
|
||||||
|
{
|
||||||
|
zup[0] = yup[0];
|
||||||
|
zup[1] = -yup[2];
|
||||||
|
zup[2] = yup[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
ABC_INLINE void copy_yup_zup(short zup[3], const short yup[3])
|
||||||
|
{
|
||||||
|
zup[0] = yup[0];
|
||||||
|
zup[1] = -yup[2];
|
||||||
|
zup[2] = yup[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy from Z-up to Y-up. */
|
||||||
|
|
||||||
|
ABC_INLINE void copy_zup_yup(float yup[3], const float zup[3])
|
||||||
|
{
|
||||||
|
yup[0] = zup[0];
|
||||||
|
yup[1] = zup[2];
|
||||||
|
yup[2] = -zup[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
ABC_INLINE void copy_zup_yup(short yup[3], const short zup[3])
|
||||||
|
{
|
||||||
|
yup[0] = zup[0];
|
||||||
|
yup[1] = zup[2];
|
||||||
|
yup[2] = -zup[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __ABC_UTIL_H__ */
|
1136
source/blender/alembic/intern/alembic_capi.cc
Normal file
1136
source/blender/alembic/intern/alembic_capi.cc
Normal file
File diff suppressed because it is too large
Load Diff
67
source/blender/blenkernel/BKE_cachefile.h
Normal file
67
source/blender/blenkernel/BKE_cachefile.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2016 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s): Kevin Dietrich.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __BKE_CACHEFILE_H__
|
||||||
|
#define __BKE_CACHEFILE_H__
|
||||||
|
|
||||||
|
/** \file BKE_cachefile.h
|
||||||
|
* \ingroup bke
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct CacheFile;
|
||||||
|
struct Main;
|
||||||
|
struct Scene;
|
||||||
|
|
||||||
|
void *BKE_cachefile_add(struct Main *bmain, const char *name);
|
||||||
|
|
||||||
|
void BKE_cachefile_init(struct CacheFile *cache_file);
|
||||||
|
|
||||||
|
void BKE_cachefile_free(struct CacheFile *cache_file);
|
||||||
|
|
||||||
|
struct CacheFile *BKE_cachefile_copy(struct Main *bmain, struct CacheFile *cache_file);
|
||||||
|
|
||||||
|
void BKE_cachefile_make_local(struct Main *bmain, struct CacheFile *cache_file, const bool lib_local);
|
||||||
|
|
||||||
|
void BKE_cachefile_reload(const struct Main *bmain, struct CacheFile *cache_file);
|
||||||
|
|
||||||
|
void BKE_cachefile_ensure_handle(const struct Main *bmain, struct CacheFile *cache_file);
|
||||||
|
|
||||||
|
void BKE_cachefile_update_frame(struct Main *bmain, struct Scene *scene, float ctime, const float fps);
|
||||||
|
|
||||||
|
bool BKE_cachefile_filepath_get(
|
||||||
|
const struct Main *bmain, const struct CacheFile *cache_file, float frame,
|
||||||
|
char r_filename[1024]);
|
||||||
|
|
||||||
|
float BKE_cachefile_time_offset(struct CacheFile *cache_file, const float time, const float fps);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __BKE_CACHEFILE_H__ */
|
@ -39,6 +39,7 @@ extern "C" {
|
|||||||
|
|
||||||
struct ARegion;
|
struct ARegion;
|
||||||
struct bScreen;
|
struct bScreen;
|
||||||
|
struct CacheFile;
|
||||||
struct ListBase;
|
struct ListBase;
|
||||||
struct Main;
|
struct Main;
|
||||||
struct Object;
|
struct Object;
|
||||||
@ -271,6 +272,8 @@ struct Text *CTX_data_edit_text(const bContext *C);
|
|||||||
struct MovieClip *CTX_data_edit_movieclip(const bContext *C);
|
struct MovieClip *CTX_data_edit_movieclip(const bContext *C);
|
||||||
struct Mask *CTX_data_edit_mask(const bContext *C);
|
struct Mask *CTX_data_edit_mask(const bContext *C);
|
||||||
|
|
||||||
|
struct CacheFile *CTX_data_edit_cachefile(const bContext *C);
|
||||||
|
|
||||||
int CTX_data_selected_nodes(const bContext *C, ListBase *list);
|
int CTX_data_selected_nodes(const bContext *C, ListBase *list);
|
||||||
|
|
||||||
struct EditBone *CTX_data_active_bone(const bContext *C);
|
struct EditBone *CTX_data_active_bone(const bContext *C);
|
||||||
|
@ -94,7 +94,7 @@ void id_clear_lib_data_ex(struct Main *bmain, struct ID *id, const bool id_in_ma
|
|||||||
|
|
||||||
struct ListBase *which_libbase(struct Main *mainlib, short type);
|
struct ListBase *which_libbase(struct Main *mainlib, short type);
|
||||||
|
|
||||||
#define MAX_LIBARRAY 34
|
#define MAX_LIBARRAY 35
|
||||||
int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]);
|
int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]);
|
||||||
|
|
||||||
/* Main API */
|
/* Main API */
|
||||||
|
@ -102,6 +102,7 @@ typedef struct Main {
|
|||||||
ListBase movieclip;
|
ListBase movieclip;
|
||||||
ListBase mask;
|
ListBase mask;
|
||||||
ListBase linestyle;
|
ListBase linestyle;
|
||||||
|
ListBase cachefiles;
|
||||||
|
|
||||||
char id_tag_update[256];
|
char id_tag_update[256];
|
||||||
|
|
||||||
|
@ -81,6 +81,7 @@ set(SRC
|
|||||||
intern/brush.c
|
intern/brush.c
|
||||||
intern/bullet.c
|
intern/bullet.c
|
||||||
intern/bvhutils.c
|
intern/bvhutils.c
|
||||||
|
intern/cachefile.c
|
||||||
intern/camera.c
|
intern/camera.c
|
||||||
intern/cdderivedmesh.c
|
intern/cdderivedmesh.c
|
||||||
intern/cloth.c
|
intern/cloth.c
|
||||||
@ -207,6 +208,7 @@ set(SRC
|
|||||||
BKE_brush.h
|
BKE_brush.h
|
||||||
BKE_bullet.h
|
BKE_bullet.h
|
||||||
BKE_bvhutils.h
|
BKE_bvhutils.h
|
||||||
|
BKE_cachefile.h
|
||||||
BKE_camera.h
|
BKE_camera.h
|
||||||
BKE_ccg.h
|
BKE_ccg.h
|
||||||
BKE_cdderivedmesh.h
|
BKE_cdderivedmesh.h
|
||||||
@ -500,6 +502,13 @@ if(WITH_FREESTYLE)
|
|||||||
add_definitions(-DWITH_FREESTYLE)
|
add_definitions(-DWITH_FREESTYLE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_ALEMBIC)
|
||||||
|
list(APPEND INC
|
||||||
|
../alembic
|
||||||
|
)
|
||||||
|
add_definitions(-DWITH_ALEMBIC)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WITH_OPENSUBDIV)
|
if(WITH_OPENSUBDIV)
|
||||||
add_definitions(-DWITH_OPENSUBDIV)
|
add_definitions(-DWITH_OPENSUBDIV)
|
||||||
list(APPEND INC_SYS
|
list(APPEND INC_SYS
|
||||||
|
@ -97,6 +97,7 @@ bool id_type_can_have_animdata(const short id_type)
|
|||||||
case ID_MC:
|
case ID_MC:
|
||||||
case ID_MSK:
|
case ID_MSK:
|
||||||
case ID_GD:
|
case ID_GD:
|
||||||
|
case ID_CF:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* no AnimData */
|
/* no AnimData */
|
||||||
@ -1160,6 +1161,9 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u
|
|||||||
|
|
||||||
/* grease pencil */
|
/* grease pencil */
|
||||||
ANIMDATA_IDS_CB(mainptr->gpencil.first);
|
ANIMDATA_IDS_CB(mainptr->gpencil.first);
|
||||||
|
|
||||||
|
/* cache files */
|
||||||
|
ANIMDATA_IDS_CB(mainptr->cachefiles.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fix all RNA-Paths throughout the database (directly access the Global.main version)
|
/* Fix all RNA-Paths throughout the database (directly access the Global.main version)
|
||||||
@ -1250,6 +1254,9 @@ void BKE_animdata_fix_paths_rename_all(ID *ref_id, const char *prefix, const cha
|
|||||||
|
|
||||||
/* grease pencil */
|
/* grease pencil */
|
||||||
RENAMEFIX_ANIM_IDS(mainptr->gpencil.first);
|
RENAMEFIX_ANIM_IDS(mainptr->gpencil.first);
|
||||||
|
|
||||||
|
/* cache files */
|
||||||
|
RENAMEFIX_ANIM_IDS(mainptr->cachefiles.first);
|
||||||
|
|
||||||
/* scenes */
|
/* scenes */
|
||||||
RENAMEFIX_ANIM_NODETREE_IDS(mainptr->scene.first, Scene);
|
RENAMEFIX_ANIM_NODETREE_IDS(mainptr->scene.first, Scene);
|
||||||
@ -2873,6 +2880,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime)
|
|||||||
|
|
||||||
/* grease pencil */
|
/* grease pencil */
|
||||||
EVAL_ANIM_IDS(main->gpencil.first, ADT_RECALC_ANIM);
|
EVAL_ANIM_IDS(main->gpencil.first, ADT_RECALC_ANIM);
|
||||||
|
|
||||||
|
/* cache files */
|
||||||
|
EVAL_ANIM_IDS(main->cachefiles.first, ADT_RECALC_ANIM);
|
||||||
|
|
||||||
/* objects */
|
/* objects */
|
||||||
/* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets
|
/* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
#include "DNA_brush_types.h"
|
#include "DNA_brush_types.h"
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
#include "DNA_image_types.h"
|
#include "DNA_image_types.h"
|
||||||
#include "DNA_mesh_types.h"
|
#include "DNA_mesh_types.h"
|
||||||
#include "DNA_modifier_types.h"
|
#include "DNA_modifier_types.h"
|
||||||
@ -653,6 +654,12 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
|
|||||||
rewrite_path_fixed(clip->name, visit_cb, absbase, bpath_user_data);
|
rewrite_path_fixed(clip->name, visit_cb, absbase, bpath_user_data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ID_CF:
|
||||||
|
{
|
||||||
|
CacheFile *cache_file = (CacheFile *)id;
|
||||||
|
rewrite_path_fixed(cache_file->filepath, visit_cb, absbase, bpath_user_data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
/* Nothing to do for other IDs that don't contain file paths. */
|
/* Nothing to do for other IDs that don't contain file paths. */
|
||||||
break;
|
break;
|
||||||
|
173
source/blender/blenkernel/intern/cachefile.c
Normal file
173
source/blender/blenkernel/intern/cachefile.c
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2016 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s): Kevin Dietrich.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file blender/blenkernel/intern/cachefile.c
|
||||||
|
* \ingroup bke
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "DNA_anim_types.h"
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
|
#include "DNA_scene_types.h"
|
||||||
|
|
||||||
|
#include "BLI_fileops.h"
|
||||||
|
#include "BLI_listbase.h"
|
||||||
|
#include "BLI_path_util.h"
|
||||||
|
#include "BLI_string.h"
|
||||||
|
#include "BLI_utildefines.h"
|
||||||
|
|
||||||
|
#include "BKE_animsys.h"
|
||||||
|
#include "BKE_cachefile.h"
|
||||||
|
#include "BKE_global.h"
|
||||||
|
#include "BKE_library.h"
|
||||||
|
#include "BKE_main.h"
|
||||||
|
#include "BKE_scene.h"
|
||||||
|
|
||||||
|
#ifdef WITH_ALEMBIC
|
||||||
|
# include "ABC_alembic.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *BKE_cachefile_add(Main *bmain, const char *name)
|
||||||
|
{
|
||||||
|
CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, name);
|
||||||
|
|
||||||
|
BKE_cachefile_init(cache_file);
|
||||||
|
|
||||||
|
return cache_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BKE_cachefile_init(CacheFile *cache_file)
|
||||||
|
{
|
||||||
|
cache_file->handle = NULL;
|
||||||
|
cache_file->filepath[0] = '\0';
|
||||||
|
cache_file->override_frame = false;
|
||||||
|
cache_file->frame = 0.0f;
|
||||||
|
cache_file->is_sequence = false;
|
||||||
|
cache_file->scale = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Free (or release) any data used by this cachefile (does not free the cachefile itself). */
|
||||||
|
void BKE_cachefile_free(CacheFile *cache_file)
|
||||||
|
{
|
||||||
|
BKE_animdata_free((ID *)cache_file, false);
|
||||||
|
|
||||||
|
#ifdef WITH_ALEMBIC
|
||||||
|
ABC_free_handle(cache_file->handle);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BLI_freelistN(&cache_file->object_paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
CacheFile *BKE_cachefile_copy(Main *bmain, CacheFile *cache_file)
|
||||||
|
{
|
||||||
|
CacheFile *new_cache_file = BKE_libblock_copy(bmain, &cache_file->id);
|
||||||
|
new_cache_file->handle = NULL;
|
||||||
|
|
||||||
|
BLI_listbase_clear(&cache_file->object_paths);
|
||||||
|
|
||||||
|
BKE_id_copy_ensure_local(bmain, &cache_file->id, &new_cache_file->id);
|
||||||
|
|
||||||
|
return new_cache_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BKE_cachefile_make_local(Main *bmain, CacheFile *cache_file, const bool lib_local)
|
||||||
|
{
|
||||||
|
BKE_id_make_local_generic(bmain, &cache_file->id, true, lib_local);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BKE_cachefile_reload(const Main *bmain, CacheFile *cache_file)
|
||||||
|
{
|
||||||
|
char filepath[FILE_MAX];
|
||||||
|
|
||||||
|
BLI_strncpy(filepath, cache_file->filepath, sizeof(filepath));
|
||||||
|
BLI_path_abs(filepath, ID_BLEND_PATH(bmain, &cache_file->id));
|
||||||
|
|
||||||
|
#ifdef WITH_ALEMBIC
|
||||||
|
if (cache_file->handle) {
|
||||||
|
ABC_free_handle(cache_file->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
cache_file->handle = ABC_create_handle(filepath, &cache_file->object_paths);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void BKE_cachefile_ensure_handle(const Main *bmain, CacheFile *cache_file)
|
||||||
|
{
|
||||||
|
if (cache_file->handle == NULL) {
|
||||||
|
BKE_cachefile_reload(bmain, cache_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BKE_cachefile_update_frame(Main *bmain, Scene *scene, const float ctime, const float fps)
|
||||||
|
{
|
||||||
|
CacheFile *cache_file;
|
||||||
|
char filename[FILE_MAX];
|
||||||
|
|
||||||
|
for (cache_file = bmain->cachefiles.first; cache_file; cache_file = cache_file->id.next) {
|
||||||
|
/* Execute drivers only, as animation has already been done. */
|
||||||
|
BKE_animsys_evaluate_animdata(scene, &cache_file->id, cache_file->adt, ctime, ADT_RECALC_DRIVERS);
|
||||||
|
|
||||||
|
if (!cache_file->is_sequence) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float time = BKE_cachefile_time_offset(cache_file, ctime, fps);
|
||||||
|
|
||||||
|
if (BKE_cachefile_filepath_get(bmain, cache_file, time, filename)) {
|
||||||
|
#ifdef WITH_ALEMBIC
|
||||||
|
ABC_free_handle(cache_file->handle);
|
||||||
|
cache_file->handle = ABC_create_handle(filename, NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BKE_cachefile_filepath_get(
|
||||||
|
const Main *bmain, const CacheFile *cache_file, float frame,
|
||||||
|
char r_filepath[FILE_MAX])
|
||||||
|
{
|
||||||
|
BLI_strncpy(r_filepath, cache_file->filepath, FILE_MAX);
|
||||||
|
BLI_path_abs(r_filepath, ID_BLEND_PATH(bmain, &cache_file->id));
|
||||||
|
|
||||||
|
int fframe;
|
||||||
|
int frame_len;
|
||||||
|
|
||||||
|
if (cache_file->is_sequence && BLI_path_frame_get(r_filepath, &fframe, &frame_len)) {
|
||||||
|
char ext[32];
|
||||||
|
BLI_path_frame_strip(r_filepath, true, ext);
|
||||||
|
BLI_path_frame(r_filepath, frame, frame_len);
|
||||||
|
BLI_ensure_extension(r_filepath, FILE_MAX, ext);
|
||||||
|
|
||||||
|
/* TODO(kevin): store sequence range? */
|
||||||
|
return BLI_exists(r_filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
float BKE_cachefile_time_offset(CacheFile *cache_file, const float time, const float fps)
|
||||||
|
{
|
||||||
|
const float frame = (cache_file->override_frame ? cache_file->frame : time);
|
||||||
|
return cache_file->is_sequence ? frame : frame / fps;
|
||||||
|
}
|
@ -3402,7 +3402,7 @@ void CDDM_calc_edges(DerivedMesh *dm)
|
|||||||
BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2);
|
BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2);
|
||||||
j = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
|
j = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
|
||||||
|
|
||||||
if (j == 0) {
|
if (j == 0 || !eindex) {
|
||||||
med->flag = ME_EDGEDRAW | ME_EDGERENDER;
|
med->flag = ME_EDGEDRAW | ME_EDGERENDER;
|
||||||
*index = ORIGINDEX_NONE;
|
*index = ORIGINDEX_NONE;
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include "BLT_translation.h"
|
#include "BLT_translation.h"
|
||||||
|
|
||||||
#include "DNA_armature_types.h"
|
#include "DNA_armature_types.h"
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
#include "DNA_constraint_types.h"
|
#include "DNA_constraint_types.h"
|
||||||
#include "DNA_modifier_types.h"
|
#include "DNA_modifier_types.h"
|
||||||
#include "DNA_object_types.h"
|
#include "DNA_object_types.h"
|
||||||
@ -63,6 +64,7 @@
|
|||||||
#include "BKE_anim.h" /* for the curve calculation part */
|
#include "BKE_anim.h" /* for the curve calculation part */
|
||||||
#include "BKE_armature.h"
|
#include "BKE_armature.h"
|
||||||
#include "BKE_bvhutils.h"
|
#include "BKE_bvhutils.h"
|
||||||
|
#include "BKE_cachefile.h"
|
||||||
#include "BKE_camera.h"
|
#include "BKE_camera.h"
|
||||||
#include "BKE_constraint.h"
|
#include "BKE_constraint.h"
|
||||||
#include "BKE_curve.h"
|
#include "BKE_curve.h"
|
||||||
@ -86,6 +88,10 @@
|
|||||||
# include "BPY_extern.h"
|
# include "BPY_extern.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_ALEMBIC
|
||||||
|
# include "ABC_alembic.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------------- */
|
||||||
/* Useful macros for testing various common flag combinations */
|
/* Useful macros for testing various common flag combinations */
|
||||||
|
|
||||||
@ -4333,6 +4339,73 @@ static bConstraintTypeInfo CTI_OBJECTSOLVER = {
|
|||||||
objectsolver_evaluate /* evaluate */
|
objectsolver_evaluate /* evaluate */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* ----------- Transform Cache ------------- */
|
||||||
|
|
||||||
|
static void transformcache_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
|
||||||
|
{
|
||||||
|
bTransformCacheConstraint *data = con->data;
|
||||||
|
func(con, (ID **)&data->cache_file, false, userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void transformcache_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
|
||||||
|
{
|
||||||
|
#ifdef WITH_ALEMBIC
|
||||||
|
bTransformCacheConstraint *data = con->data;
|
||||||
|
Scene *scene = cob->scene;
|
||||||
|
|
||||||
|
const float frame = BKE_scene_frame_get(scene);
|
||||||
|
const float time = BKE_cachefile_time_offset(data->cache_file, frame, FPS);
|
||||||
|
|
||||||
|
CacheFile *cache_file = data->cache_file;
|
||||||
|
|
||||||
|
BKE_cachefile_ensure_handle(G.main, cache_file);
|
||||||
|
|
||||||
|
ABC_get_transform(cache_file->handle, cob->ob, data->object_path,
|
||||||
|
cob->matrix, time, cache_file->scale);
|
||||||
|
#else
|
||||||
|
UNUSED_VARS(con, cob);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
UNUSED_VARS(targets);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void transformcache_copy(bConstraint *con, bConstraint *srccon)
|
||||||
|
{
|
||||||
|
bTransformCacheConstraint *src = srccon->data;
|
||||||
|
bTransformCacheConstraint *dst = con->data;
|
||||||
|
|
||||||
|
BLI_strncpy(dst->object_path, src->object_path, sizeof(dst->object_path));
|
||||||
|
dst->cache_file = src->cache_file;
|
||||||
|
|
||||||
|
if (dst->cache_file) {
|
||||||
|
id_us_plus(&dst->cache_file->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void transformcache_free(bConstraint *con)
|
||||||
|
{
|
||||||
|
bTransformCacheConstraint *data = con->data;
|
||||||
|
|
||||||
|
if (data->cache_file) {
|
||||||
|
id_us_min(&data->cache_file->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bConstraintTypeInfo CTI_TRANSFORM_CACHE = {
|
||||||
|
CONSTRAINT_TYPE_TRANSFORM_CACHE, /* type */
|
||||||
|
sizeof(bTransformCacheConstraint), /* size */
|
||||||
|
"Transform Cache", /* name */
|
||||||
|
"bTransformCacheConstraint", /* struct name */
|
||||||
|
transformcache_free, /* free data */
|
||||||
|
transformcache_id_looper, /* id looper */
|
||||||
|
transformcache_copy, /* copy data */
|
||||||
|
NULL, /* new data */
|
||||||
|
NULL, /* get constraint targets */
|
||||||
|
NULL, /* flush constraint targets */
|
||||||
|
NULL, /* get target matrix */
|
||||||
|
transformcache_evaluate /* evaluate */
|
||||||
|
};
|
||||||
|
|
||||||
/* ************************* Constraints Type-Info *************************** */
|
/* ************************* Constraints Type-Info *************************** */
|
||||||
/* All of the constraints api functions use bConstraintTypeInfo structs to carry out
|
/* All of the constraints api functions use bConstraintTypeInfo structs to carry out
|
||||||
* and operations that involve constraint specific code.
|
* and operations that involve constraint specific code.
|
||||||
@ -4374,6 +4447,7 @@ static void constraints_init_typeinfo(void)
|
|||||||
constraintsTypeInfo[26] = &CTI_FOLLOWTRACK; /* Follow Track Constraint */
|
constraintsTypeInfo[26] = &CTI_FOLLOWTRACK; /* Follow Track Constraint */
|
||||||
constraintsTypeInfo[27] = &CTI_CAMERASOLVER; /* Camera Solver Constraint */
|
constraintsTypeInfo[27] = &CTI_CAMERASOLVER; /* Camera Solver Constraint */
|
||||||
constraintsTypeInfo[28] = &CTI_OBJECTSOLVER; /* Object Solver Constraint */
|
constraintsTypeInfo[28] = &CTI_OBJECTSOLVER; /* Object Solver Constraint */
|
||||||
|
constraintsTypeInfo[29] = &CTI_TRANSFORM_CACHE; /* Transform Cache Constraint */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function should be used for getting the appropriate type-info when only
|
/* This function should be used for getting the appropriate type-info when only
|
||||||
|
@ -1067,6 +1067,11 @@ struct EditBone *CTX_data_active_bone(const bContext *C)
|
|||||||
return ctx_data_pointer_get(C, "active_bone");
|
return ctx_data_pointer_get(C, "active_bone");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CacheFile *CTX_data_edit_cachefile(const bContext *C)
|
||||||
|
{
|
||||||
|
return ctx_data_pointer_get(C, "edit_cachefile");
|
||||||
|
}
|
||||||
|
|
||||||
int CTX_data_selected_bones(const bContext *C, ListBase *list)
|
int CTX_data_selected_bones(const bContext *C, ListBase *list)
|
||||||
{
|
{
|
||||||
return ctx_data_collection_get(C, "selected_bones", list);
|
return ctx_data_collection_get(C, "selected_bones", list);
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
|
|
||||||
#include "DNA_anim_types.h"
|
#include "DNA_anim_types.h"
|
||||||
#include "DNA_camera_types.h"
|
#include "DNA_camera_types.h"
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
#include "DNA_group_types.h"
|
#include "DNA_group_types.h"
|
||||||
#include "DNA_lamp_types.h"
|
#include "DNA_lamp_types.h"
|
||||||
#include "DNA_lattice_types.h"
|
#include "DNA_lattice_types.h"
|
||||||
@ -2173,7 +2174,12 @@ static void dag_object_time_update_flags(Main *bmain, Scene *scene, Object *ob)
|
|||||||
|
|
||||||
if (cti) {
|
if (cti) {
|
||||||
/* special case for camera tracking -- it doesn't use targets to define relations */
|
/* special case for camera tracking -- it doesn't use targets to define relations */
|
||||||
if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
|
if (ELEM(cti->type,
|
||||||
|
CONSTRAINT_TYPE_FOLLOWTRACK,
|
||||||
|
CONSTRAINT_TYPE_CAMERASOLVER,
|
||||||
|
CONSTRAINT_TYPE_OBJECTSOLVER,
|
||||||
|
CONSTRAINT_TYPE_TRANSFORM_CACHE))
|
||||||
|
{
|
||||||
ob->recalc |= OB_RECALC_OB;
|
ob->recalc |= OB_RECALC_OB;
|
||||||
}
|
}
|
||||||
else if (cti->get_constraint_targets) {
|
else if (cti->get_constraint_targets) {
|
||||||
@ -3001,6 +3007,33 @@ void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag)
|
|||||||
/* BLI_assert(!"invalid flag for this 'idtype'"); */
|
/* BLI_assert(!"invalid flag for this 'idtype'"); */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (GS(id->name) == ID_CF) {
|
||||||
|
for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
|
||||||
|
ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache);
|
||||||
|
|
||||||
|
if (md) {
|
||||||
|
MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md;
|
||||||
|
|
||||||
|
if (mcmd->cache_file && (&mcmd->cache_file->id == id)) {
|
||||||
|
ob->recalc |= OB_RECALC_DATA;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (bConstraint *con = ob->constraints.first; con; con = con->next) {
|
||||||
|
if (con->type != CONSTRAINT_TYPE_TRANSFORM_CACHE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bTransformCacheConstraint *data = con->data;
|
||||||
|
|
||||||
|
if (data->cache_file && (&data->cache_file->id == id)) {
|
||||||
|
ob->recalc |= OB_RECALC_DATA;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DAG_id_tag_update(ID *id, short flag)
|
void DAG_id_tag_update(ID *id, short flag)
|
||||||
|
@ -60,6 +60,7 @@ static IDType idtypes[] = {
|
|||||||
{ ID_AR, "Armature", "armatures", BLT_I18NCONTEXT_ID_ARMATURE, IDTYPE_FLAGS_ISLINKABLE },
|
{ ID_AR, "Armature", "armatures", BLT_I18NCONTEXT_ID_ARMATURE, IDTYPE_FLAGS_ISLINKABLE },
|
||||||
{ ID_BR, "Brush", "brushes", BLT_I18NCONTEXT_ID_BRUSH, IDTYPE_FLAGS_ISLINKABLE },
|
{ ID_BR, "Brush", "brushes", BLT_I18NCONTEXT_ID_BRUSH, IDTYPE_FLAGS_ISLINKABLE },
|
||||||
{ ID_CA, "Camera", "cameras", BLT_I18NCONTEXT_ID_CAMERA, IDTYPE_FLAGS_ISLINKABLE },
|
{ ID_CA, "Camera", "cameras", BLT_I18NCONTEXT_ID_CAMERA, IDTYPE_FLAGS_ISLINKABLE },
|
||||||
|
{ ID_CF, "CacheFile", "cache_files", BLT_I18NCONTEXT_ID_CACHEFILE, IDTYPE_FLAGS_ISLINKABLE },
|
||||||
{ ID_CU, "Curve", "curves", BLT_I18NCONTEXT_ID_CURVE, IDTYPE_FLAGS_ISLINKABLE },
|
{ ID_CU, "Curve", "curves", BLT_I18NCONTEXT_ID_CURVE, IDTYPE_FLAGS_ISLINKABLE },
|
||||||
{ ID_GD, "GPencil", "grease_pencil", BLT_I18NCONTEXT_ID_GPENCIL, IDTYPE_FLAGS_ISLINKABLE }, /* rename gpencil */
|
{ ID_GD, "GPencil", "grease_pencil", BLT_I18NCONTEXT_ID_GPENCIL, IDTYPE_FLAGS_ISLINKABLE }, /* rename gpencil */
|
||||||
{ ID_GR, "Group", "groups", BLT_I18NCONTEXT_ID_GROUP, IDTYPE_FLAGS_ISLINKABLE },
|
{ ID_GR, "Group", "groups", BLT_I18NCONTEXT_ID_GROUP, IDTYPE_FLAGS_ISLINKABLE },
|
||||||
@ -184,6 +185,7 @@ int BKE_idcode_to_idfilter(const short idcode)
|
|||||||
CASE_IDFILTER(AR);
|
CASE_IDFILTER(AR);
|
||||||
CASE_IDFILTER(BR);
|
CASE_IDFILTER(BR);
|
||||||
CASE_IDFILTER(CA);
|
CASE_IDFILTER(CA);
|
||||||
|
CASE_IDFILTER(CF);
|
||||||
CASE_IDFILTER(CU);
|
CASE_IDFILTER(CU);
|
||||||
CASE_IDFILTER(GD);
|
CASE_IDFILTER(GD);
|
||||||
CASE_IDFILTER(GR);
|
CASE_IDFILTER(GR);
|
||||||
@ -227,6 +229,7 @@ short BKE_idcode_from_idfilter(const int idfilter)
|
|||||||
CASE_IDFILTER(AR);
|
CASE_IDFILTER(AR);
|
||||||
CASE_IDFILTER(BR);
|
CASE_IDFILTER(BR);
|
||||||
CASE_IDFILTER(CA);
|
CASE_IDFILTER(CA);
|
||||||
|
CASE_IDFILTER(CF);
|
||||||
CASE_IDFILTER(CU);
|
CASE_IDFILTER(CU);
|
||||||
CASE_IDFILTER(GD);
|
CASE_IDFILTER(GD);
|
||||||
CASE_IDFILTER(GR);
|
CASE_IDFILTER(GR);
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#include "DNA_anim_types.h"
|
#include "DNA_anim_types.h"
|
||||||
#include "DNA_armature_types.h"
|
#include "DNA_armature_types.h"
|
||||||
#include "DNA_brush_types.h"
|
#include "DNA_brush_types.h"
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
#include "DNA_camera_types.h"
|
#include "DNA_camera_types.h"
|
||||||
#include "DNA_group_types.h"
|
#include "DNA_group_types.h"
|
||||||
#include "DNA_gpencil_types.h"
|
#include "DNA_gpencil_types.h"
|
||||||
@ -56,6 +57,7 @@
|
|||||||
#include "DNA_material_types.h"
|
#include "DNA_material_types.h"
|
||||||
#include "DNA_mesh_types.h"
|
#include "DNA_mesh_types.h"
|
||||||
#include "DNA_meta_types.h"
|
#include "DNA_meta_types.h"
|
||||||
|
#include "DNA_modifier_types.h"
|
||||||
#include "DNA_movieclip_types.h"
|
#include "DNA_movieclip_types.h"
|
||||||
#include "DNA_mask_types.h"
|
#include "DNA_mask_types.h"
|
||||||
#include "DNA_node_types.h"
|
#include "DNA_node_types.h"
|
||||||
@ -81,6 +83,7 @@
|
|||||||
#include "BKE_bpath.h"
|
#include "BKE_bpath.h"
|
||||||
#include "BKE_brush.h"
|
#include "BKE_brush.h"
|
||||||
#include "BKE_camera.h"
|
#include "BKE_camera.h"
|
||||||
|
#include "BKE_cachefile.h"
|
||||||
#include "BKE_context.h"
|
#include "BKE_context.h"
|
||||||
#include "BKE_curve.h"
|
#include "BKE_curve.h"
|
||||||
#include "BKE_depsgraph.h"
|
#include "BKE_depsgraph.h"
|
||||||
@ -425,6 +428,9 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local)
|
|||||||
case ID_PC:
|
case ID_PC:
|
||||||
if (!test) BKE_paint_curve_make_local(bmain, (PaintCurve *)id, lib_local);
|
if (!test) BKE_paint_curve_make_local(bmain, (PaintCurve *)id, lib_local);
|
||||||
return true;
|
return true;
|
||||||
|
case ID_CF:
|
||||||
|
if (!test) BKE_cachefile_make_local(bmain, (CacheFile *)id, lib_local);
|
||||||
|
return true;
|
||||||
case ID_SCR:
|
case ID_SCR:
|
||||||
case ID_LI:
|
case ID_LI:
|
||||||
case ID_KE:
|
case ID_KE:
|
||||||
@ -529,6 +535,9 @@ bool id_copy(Main *bmain, ID *id, ID **newid, bool test)
|
|||||||
case ID_PC:
|
case ID_PC:
|
||||||
if (!test) *newid = (ID *)BKE_paint_curve_copy(bmain, (PaintCurve *)id);
|
if (!test) *newid = (ID *)BKE_paint_curve_copy(bmain, (PaintCurve *)id);
|
||||||
return true;
|
return true;
|
||||||
|
case ID_CF:
|
||||||
|
if (!test) *newid = (ID *)BKE_cachefile_copy(bmain, (CacheFile *)id);
|
||||||
|
return true;
|
||||||
case ID_SCE:
|
case ID_SCE:
|
||||||
case ID_LI:
|
case ID_LI:
|
||||||
case ID_SCR:
|
case ID_SCR:
|
||||||
@ -641,6 +650,8 @@ ListBase *which_libbase(Main *mainlib, short type)
|
|||||||
return &(mainlib->palettes);
|
return &(mainlib->palettes);
|
||||||
case ID_PC:
|
case ID_PC:
|
||||||
return &(mainlib->paintcurves);
|
return &(mainlib->paintcurves);
|
||||||
|
case ID_CF:
|
||||||
|
return &(mainlib->cachefiles);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -764,6 +775,7 @@ int set_listbasepointers(Main *main, ListBase **lb)
|
|||||||
|
|
||||||
lb[a++] = &(main->armature);
|
lb[a++] = &(main->armature);
|
||||||
|
|
||||||
|
lb[a++] = &(main->cachefiles);
|
||||||
lb[a++] = &(main->mesh);
|
lb[a++] = &(main->mesh);
|
||||||
lb[a++] = &(main->curve);
|
lb[a++] = &(main->curve);
|
||||||
lb[a++] = &(main->mball);
|
lb[a++] = &(main->mball);
|
||||||
@ -915,6 +927,9 @@ void *BKE_libblock_alloc_notest(short type)
|
|||||||
case ID_PC:
|
case ID_PC:
|
||||||
id = MEM_callocN(sizeof(PaintCurve), "Paint Curve");
|
id = MEM_callocN(sizeof(PaintCurve), "Paint Curve");
|
||||||
break;
|
break;
|
||||||
|
case ID_CF:
|
||||||
|
id = MEM_callocN(sizeof(CacheFile), "Cache File");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@ -1041,6 +1056,9 @@ void BKE_libblock_init_empty(ID *id)
|
|||||||
case ID_LS:
|
case ID_LS:
|
||||||
BKE_linestyle_init((FreestyleLineStyle *)id);
|
BKE_linestyle_init((FreestyleLineStyle *)id);
|
||||||
break;
|
break;
|
||||||
|
case ID_CF:
|
||||||
|
BKE_cachefile_init((CacheFile *)id);
|
||||||
|
break;
|
||||||
case ID_KE:
|
case ID_KE:
|
||||||
/* Shapekeys are a complex topic too - they depend on their 'user' data type...
|
/* Shapekeys are a complex topic too - they depend on their 'user' data type...
|
||||||
* They are not linkable, though, so it should never reach here anyway. */
|
* They are not linkable, though, so it should never reach here anyway. */
|
||||||
@ -1228,6 +1246,7 @@ void BKE_main_free(Main *mainvar)
|
|||||||
case 31: BKE_libblock_free_ex(mainvar, id, false); break;
|
case 31: BKE_libblock_free_ex(mainvar, id, false); break;
|
||||||
case 32: BKE_libblock_free_ex(mainvar, id, false); break;
|
case 32: BKE_libblock_free_ex(mainvar, id, false); break;
|
||||||
case 33: BKE_libblock_free_ex(mainvar, id, false); break;
|
case 33: BKE_libblock_free_ex(mainvar, id, false); break;
|
||||||
|
case 34: BKE_libblock_free_ex(mainvar, id, false); break;
|
||||||
default:
|
default:
|
||||||
BLI_assert(0);
|
BLI_assert(0);
|
||||||
break;
|
break;
|
||||||
|
@ -854,6 +854,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
|
|||||||
case ID_WM:
|
case ID_WM:
|
||||||
case ID_PAL:
|
case ID_PAL:
|
||||||
case ID_PC:
|
case ID_PC:
|
||||||
|
case ID_CF:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Deprecated. */
|
/* Deprecated. */
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include "DNA_armature_types.h"
|
#include "DNA_armature_types.h"
|
||||||
#include "DNA_brush_types.h"
|
#include "DNA_brush_types.h"
|
||||||
#include "DNA_camera_types.h"
|
#include "DNA_camera_types.h"
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
#include "DNA_group_types.h"
|
#include "DNA_group_types.h"
|
||||||
#include "DNA_gpencil_types.h"
|
#include "DNA_gpencil_types.h"
|
||||||
#include "DNA_ipo_types.h"
|
#include "DNA_ipo_types.h"
|
||||||
@ -69,6 +70,7 @@
|
|||||||
#include "BKE_armature.h"
|
#include "BKE_armature.h"
|
||||||
#include "BKE_brush.h"
|
#include "BKE_brush.h"
|
||||||
#include "BKE_camera.h"
|
#include "BKE_camera.h"
|
||||||
|
#include "BKE_cachefile.h"
|
||||||
#include "BKE_curve.h"
|
#include "BKE_curve.h"
|
||||||
#include "BKE_depsgraph.h"
|
#include "BKE_depsgraph.h"
|
||||||
#include "BKE_fcurve.h"
|
#include "BKE_fcurve.h"
|
||||||
@ -812,6 +814,9 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user)
|
|||||||
case ID_PC:
|
case ID_PC:
|
||||||
BKE_paint_curve_free((PaintCurve *)id);
|
BKE_paint_curve_free((PaintCurve *)id);
|
||||||
break;
|
break;
|
||||||
|
case ID_CF:
|
||||||
|
BKE_cachefile_free((CacheFile *)id);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* avoid notifying on removed data */
|
/* avoid notifying on removed data */
|
||||||
|
@ -65,6 +65,7 @@
|
|||||||
#include "BKE_animsys.h"
|
#include "BKE_animsys.h"
|
||||||
#include "BKE_action.h"
|
#include "BKE_action.h"
|
||||||
#include "BKE_armature.h"
|
#include "BKE_armature.h"
|
||||||
|
#include "BKE_cachefile.h"
|
||||||
#include "BKE_colortools.h"
|
#include "BKE_colortools.h"
|
||||||
#include "BKE_depsgraph.h"
|
#include "BKE_depsgraph.h"
|
||||||
#include "BKE_editmesh.h"
|
#include "BKE_editmesh.h"
|
||||||
@ -1926,6 +1927,9 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain,
|
|||||||
|
|
||||||
BKE_mask_evaluate_all_masks(bmain, ctime, true);
|
BKE_mask_evaluate_all_masks(bmain, ctime, true);
|
||||||
|
|
||||||
|
/* Update animated cache files for modifiers. */
|
||||||
|
BKE_cachefile_update_frame(bmain, sce, ctime, (((double)sce->r.frs_sec) / (double)sce->r.frs_sec_base));
|
||||||
|
|
||||||
#ifdef POSE_ANIMATION_WORKAROUND
|
#ifdef POSE_ANIMATION_WORKAROUND
|
||||||
scene_armature_depsgraph_workaround(bmain);
|
scene_armature_depsgraph_workaround(bmain);
|
||||||
#endif
|
#endif
|
||||||
|
@ -77,6 +77,13 @@ if(WITH_CODEC_FFMPEG)
|
|||||||
add_definitions(-DWITH_FFMPEG)
|
add_definitions(-DWITH_FFMPEG)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_ALEMBIC)
|
||||||
|
list(APPEND INC
|
||||||
|
../alembic
|
||||||
|
)
|
||||||
|
add_definitions(-DWITH_ALEMBIC)
|
||||||
|
endif()
|
||||||
|
|
||||||
blender_add_lib(bf_blenloader "${SRC}" "${INC}" "${INC_SYS}")
|
blender_add_lib(bf_blenloader "${SRC}" "${INC}" "${INC_SYS}")
|
||||||
|
|
||||||
# needed so writefile.c can use dna_type_offsets.h
|
# needed so writefile.c can use dna_type_offsets.h
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
#include "DNA_actuator_types.h"
|
#include "DNA_actuator_types.h"
|
||||||
#include "DNA_brush_types.h"
|
#include "DNA_brush_types.h"
|
||||||
#include "DNA_camera_types.h"
|
#include "DNA_camera_types.h"
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
#include "DNA_cloth_types.h"
|
#include "DNA_cloth_types.h"
|
||||||
#include "DNA_controller_types.h"
|
#include "DNA_controller_types.h"
|
||||||
#include "DNA_constraint_types.h"
|
#include "DNA_constraint_types.h"
|
||||||
@ -114,6 +115,7 @@
|
|||||||
#include "BKE_action.h"
|
#include "BKE_action.h"
|
||||||
#include "BKE_armature.h"
|
#include "BKE_armature.h"
|
||||||
#include "BKE_brush.h"
|
#include "BKE_brush.h"
|
||||||
|
#include "BKE_cachefile.h"
|
||||||
#include "BKE_cloth.h"
|
#include "BKE_cloth.h"
|
||||||
#include "BKE_constraint.h"
|
#include "BKE_constraint.h"
|
||||||
#include "BKE_context.h"
|
#include "BKE_context.h"
|
||||||
@ -2691,6 +2693,36 @@ static void direct_link_animdata(FileData *fd, AnimData *adt)
|
|||||||
adt->actstrip = newdataadr(fd, adt->actstrip);
|
adt->actstrip = newdataadr(fd, adt->actstrip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************ READ CACHEFILES *************** */
|
||||||
|
|
||||||
|
static void lib_link_cachefiles(FileData *fd, Main *bmain)
|
||||||
|
{
|
||||||
|
CacheFile *cache_file;
|
||||||
|
|
||||||
|
/* only link ID pointers */
|
||||||
|
for (cache_file = bmain->cachefiles.first; cache_file; cache_file = cache_file->id.next) {
|
||||||
|
if (cache_file->id.tag & LIB_TAG_NEED_LINK) {
|
||||||
|
cache_file->id.tag &= ~LIB_TAG_NEED_LINK;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLI_listbase_clear(&cache_file->object_paths);
|
||||||
|
cache_file->handle = NULL;
|
||||||
|
|
||||||
|
if (cache_file->adt) {
|
||||||
|
lib_link_animdata(fd, &cache_file->id, cache_file->adt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void direct_link_cachefile(FileData *fd, CacheFile *cache_file)
|
||||||
|
{
|
||||||
|
cache_file->handle = NULL;
|
||||||
|
|
||||||
|
/* relink animdata */
|
||||||
|
cache_file->adt = newdataadr(fd, cache_file->adt);
|
||||||
|
direct_link_animdata(fd, cache_file->adt);
|
||||||
|
}
|
||||||
|
|
||||||
/* ************ READ MOTION PATHS *************** */
|
/* ************ READ MOTION PATHS *************** */
|
||||||
|
|
||||||
/* direct data for cache */
|
/* direct data for cache */
|
||||||
@ -7912,6 +7944,7 @@ static const char *dataname(short id_code)
|
|||||||
case ID_MC: return "Data from MC";
|
case ID_MC: return "Data from MC";
|
||||||
case ID_MSK: return "Data from MSK";
|
case ID_MSK: return "Data from MSK";
|
||||||
case ID_LS: return "Data from LS";
|
case ID_LS: return "Data from LS";
|
||||||
|
case ID_CF: return "Data from CF";
|
||||||
}
|
}
|
||||||
return "Data from Lib Block";
|
return "Data from Lib Block";
|
||||||
|
|
||||||
@ -8163,6 +8196,9 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short
|
|||||||
case ID_PC:
|
case ID_PC:
|
||||||
direct_link_paint_curve(fd, (PaintCurve *)id);
|
direct_link_paint_curve(fd, (PaintCurve *)id);
|
||||||
break;
|
break;
|
||||||
|
case ID_CF:
|
||||||
|
direct_link_cachefile(fd, (CacheFile *)id);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
oldnewmap_free_unused(fd->datamap);
|
oldnewmap_free_unused(fd->datamap);
|
||||||
@ -8356,6 +8392,7 @@ static void lib_link_all(FileData *fd, Main *main)
|
|||||||
lib_link_mask(fd, main);
|
lib_link_mask(fd, main);
|
||||||
lib_link_linestyle(fd, main);
|
lib_link_linestyle(fd, main);
|
||||||
lib_link_gpencil(fd, main);
|
lib_link_gpencil(fd, main);
|
||||||
|
lib_link_cachefiles(fd, main);
|
||||||
|
|
||||||
lib_link_mesh(fd, main); /* as last: tpage images with users at zero */
|
lib_link_mesh(fd, main); /* as last: tpage images with users at zero */
|
||||||
|
|
||||||
@ -9462,6 +9499,13 @@ static void expand_camera(FileData *fd, Main *mainvar, Camera *ca)
|
|||||||
expand_animdata(fd, mainvar, ca->adt);
|
expand_animdata(fd, mainvar, ca->adt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void expand_cachefile(FileData *fd, Main *mainvar, CacheFile *cache_file)
|
||||||
|
{
|
||||||
|
if (cache_file->adt) {
|
||||||
|
expand_animdata(fd, mainvar, cache_file->adt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void expand_speaker(FileData *fd, Main *mainvar, Speaker *spk)
|
static void expand_speaker(FileData *fd, Main *mainvar, Speaker *spk)
|
||||||
{
|
{
|
||||||
expand_doit(fd, mainvar, spk->sound);
|
expand_doit(fd, mainvar, spk->sound);
|
||||||
@ -9657,6 +9701,9 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
|
|||||||
case ID_GD:
|
case ID_GD:
|
||||||
expand_gpencil(fd, mainvar, (bGPdata *)id);
|
expand_gpencil(fd, mainvar, (bGPdata *)id);
|
||||||
break;
|
break;
|
||||||
|
case ID_CF:
|
||||||
|
expand_cachefile(fd, mainvar, (CacheFile *)id);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
do_it = true;
|
do_it = true;
|
||||||
|
@ -107,6 +107,7 @@
|
|||||||
#include "DNA_armature_types.h"
|
#include "DNA_armature_types.h"
|
||||||
#include "DNA_actuator_types.h"
|
#include "DNA_actuator_types.h"
|
||||||
#include "DNA_brush_types.h"
|
#include "DNA_brush_types.h"
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
#include "DNA_camera_types.h"
|
#include "DNA_camera_types.h"
|
||||||
#include "DNA_cloth_types.h"
|
#include "DNA_cloth_types.h"
|
||||||
#include "DNA_constraint_types.h"
|
#include "DNA_constraint_types.h"
|
||||||
@ -3882,6 +3883,21 @@ static void write_linestyles(WriteData *wd, ListBase *idbase)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void write_cachefiles(WriteData *wd, ListBase *idbase)
|
||||||
|
{
|
||||||
|
CacheFile *cache_file;
|
||||||
|
|
||||||
|
for (cache_file = idbase->first; cache_file; cache_file = cache_file->id.next) {
|
||||||
|
if (cache_file->id.us > 0 || wd->current) {
|
||||||
|
writestruct(wd, ID_CF, CacheFile, 1, cache_file);
|
||||||
|
|
||||||
|
if (cache_file->adt) {
|
||||||
|
write_animdata(wd, cache_file->adt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Keep it last of write_foodata functions. */
|
/* Keep it last of write_foodata functions. */
|
||||||
static void write_libraries(WriteData *wd, Main *main)
|
static void write_libraries(WriteData *wd, Main *main)
|
||||||
{
|
{
|
||||||
@ -4079,6 +4095,7 @@ static bool write_file_handle(
|
|||||||
write_paintcurves(wd, &mainvar->paintcurves);
|
write_paintcurves(wd, &mainvar->paintcurves);
|
||||||
write_gpencils(wd, &mainvar->gpencil);
|
write_gpencils(wd, &mainvar->gpencil);
|
||||||
write_linestyles(wd, &mainvar->linestyle);
|
write_linestyles(wd, &mainvar->linestyle);
|
||||||
|
write_cachefiles(wd, &mainvar->cachefiles);
|
||||||
write_libraries(wd, mainvar->next);
|
write_libraries(wd, mainvar->next);
|
||||||
|
|
||||||
/* So changes above don't cause a 'DNA1' to be detected as changed on undo. */
|
/* So changes above don't cause a 'DNA1' to be detected as changed on undo. */
|
||||||
|
@ -120,6 +120,7 @@ bool BLT_lang_is_ime_supported(void);
|
|||||||
#define BLT_I18NCONTEXT_ID_ARMATURE "Armature"
|
#define BLT_I18NCONTEXT_ID_ARMATURE "Armature"
|
||||||
#define BLT_I18NCONTEXT_ID_BRUSH "Brush"
|
#define BLT_I18NCONTEXT_ID_BRUSH "Brush"
|
||||||
#define BLT_I18NCONTEXT_ID_CAMERA "Camera"
|
#define BLT_I18NCONTEXT_ID_CAMERA "Camera"
|
||||||
|
#define BLT_I18NCONTEXT_ID_CACHEFILE "CacheFile"
|
||||||
#define BLT_I18NCONTEXT_ID_CURVE "Curve"
|
#define BLT_I18NCONTEXT_ID_CURVE "Curve"
|
||||||
#define BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE "FreestyleLineStyle"
|
#define BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE "FreestyleLineStyle"
|
||||||
#define BLT_I18NCONTEXT_ID_GPENCIL "GPencil"
|
#define BLT_I18NCONTEXT_ID_GPENCIL "GPencil"
|
||||||
@ -171,6 +172,7 @@ typedef struct {
|
|||||||
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_ARMATURE, "id_armature"), \
|
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_ARMATURE, "id_armature"), \
|
||||||
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_BRUSH, "id_brush"), \
|
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_BRUSH, "id_brush"), \
|
||||||
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_CAMERA, "id_camera"), \
|
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_CAMERA, "id_camera"), \
|
||||||
|
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_CACHEFILE, "id_cachefile"), \
|
||||||
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_CURVE, "id_curve"), \
|
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_CURVE, "id_curve"), \
|
||||||
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE, "id_fs_linestyle"), \
|
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE, "id_fs_linestyle"), \
|
||||||
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_GPENCIL, "id_gpencil"), \
|
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_GPENCIL, "id_gpencil"), \
|
||||||
|
@ -79,6 +79,7 @@ void DEG_scene_graph_free(struct Scene *scene);
|
|||||||
*/
|
*/
|
||||||
struct DepsNodeHandle;
|
struct DepsNodeHandle;
|
||||||
|
|
||||||
|
struct CacheFile;
|
||||||
struct Object;
|
struct Object;
|
||||||
|
|
||||||
typedef enum eDepsSceneComponentType {
|
typedef enum eDepsSceneComponentType {
|
||||||
@ -100,11 +101,13 @@ typedef enum eDepsObjectComponentType {
|
|||||||
|
|
||||||
DEG_OB_COMP_EVAL_PARTICLES, /* Particle Systems Component */
|
DEG_OB_COMP_EVAL_PARTICLES, /* Particle Systems Component */
|
||||||
DEG_OB_COMP_SHADING, /* Material Shading Component */
|
DEG_OB_COMP_SHADING, /* Material Shading Component */
|
||||||
|
DEG_OB_COMP_CACHE, /* Cache Component */
|
||||||
} eDepsObjectComponentType;
|
} eDepsObjectComponentType;
|
||||||
|
|
||||||
void DEG_add_scene_relation(struct DepsNodeHandle *node, struct Scene *scene, eDepsSceneComponentType component, const char *description);
|
void DEG_add_scene_relation(struct DepsNodeHandle *node, struct Scene *scene, eDepsSceneComponentType component, const char *description);
|
||||||
void DEG_add_object_relation(struct DepsNodeHandle *node, struct Object *ob, eDepsObjectComponentType component, const char *description);
|
void DEG_add_object_relation(struct DepsNodeHandle *node, struct Object *ob, eDepsObjectComponentType component, const char *description);
|
||||||
void DEG_add_bone_relation(struct DepsNodeHandle *handle, struct Object *ob, const char *bone_name, eDepsObjectComponentType component, const char *description);
|
void DEG_add_bone_relation(struct DepsNodeHandle *handle, struct Object *ob, const char *bone_name, eDepsObjectComponentType component, const char *description);
|
||||||
|
void DEG_add_object_cache_relation(struct DepsNodeHandle *handle, struct CacheFile *cache_file, eDepsObjectComponentType component, const char *description);
|
||||||
|
|
||||||
/* TODO(sergey): Remove once all geometry update is granular. */
|
/* TODO(sergey): Remove once all geometry update is granular. */
|
||||||
void DEG_add_special_eval_flag(struct Depsgraph *graph, struct ID *id, short flag);
|
void DEG_add_special_eval_flag(struct Depsgraph *graph, struct ID *id, short flag);
|
||||||
|
@ -46,6 +46,7 @@ extern "C" {
|
|||||||
#include "DNA_action_types.h"
|
#include "DNA_action_types.h"
|
||||||
#include "DNA_anim_types.h"
|
#include "DNA_anim_types.h"
|
||||||
#include "DNA_armature_types.h"
|
#include "DNA_armature_types.h"
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
#include "DNA_camera_types.h"
|
#include "DNA_camera_types.h"
|
||||||
#include "DNA_constraint_types.h"
|
#include "DNA_constraint_types.h"
|
||||||
#include "DNA_curve_types.h"
|
#include "DNA_curve_types.h"
|
||||||
@ -339,6 +340,14 @@ void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene)
|
|||||||
if (scene->gpd) {
|
if (scene->gpd) {
|
||||||
build_gpencil(scene->gpd);
|
build_gpencil(scene->gpd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* cache files */
|
||||||
|
for (CacheFile *cachefile = static_cast<CacheFile *>(bmain->cachefiles.first);
|
||||||
|
cachefile;
|
||||||
|
cachefile = static_cast<CacheFile *>(cachefile->id.next))
|
||||||
|
{
|
||||||
|
build_cachefile(cachefile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DepsgraphNodeBuilder::build_group(Scene *scene,
|
void DepsgraphNodeBuilder::build_group(Scene *scene,
|
||||||
@ -1259,4 +1268,18 @@ void DepsgraphNodeBuilder::build_gpencil(bGPdata *gpd)
|
|||||||
build_animdata(gpd_id);
|
build_animdata(gpd_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DepsgraphNodeBuilder::build_cachefile(CacheFile *cache_file)
|
||||||
|
{
|
||||||
|
ID *cache_file_id = &cache_file->id;
|
||||||
|
|
||||||
|
add_component_node(cache_file_id, DEPSNODE_TYPE_CACHE);
|
||||||
|
|
||||||
|
add_operation_node(cache_file_id, DEPSNODE_TYPE_CACHE,
|
||||||
|
DEPSOP_TYPE_EXEC, NULL,
|
||||||
|
DEG_OPCODE_PLACEHOLDER, "Cache File Update");
|
||||||
|
|
||||||
|
add_id_node(cache_file_id);
|
||||||
|
build_animdata(cache_file_id);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace DEG
|
} // namespace DEG
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "intern/depsgraph_types.h"
|
#include "intern/depsgraph_types.h"
|
||||||
|
|
||||||
struct Base;
|
struct Base;
|
||||||
|
struct CacheFile;
|
||||||
struct bGPdata;
|
struct bGPdata;
|
||||||
struct ListBase;
|
struct ListBase;
|
||||||
struct GHash;
|
struct GHash;
|
||||||
@ -144,6 +145,7 @@ struct DepsgraphNodeBuilder {
|
|||||||
void build_world(World *world);
|
void build_world(World *world);
|
||||||
void build_compositor(Scene *scene);
|
void build_compositor(Scene *scene);
|
||||||
void build_gpencil(bGPdata *gpd);
|
void build_gpencil(bGPdata *gpd);
|
||||||
|
void build_cachefile(CacheFile *cache_file);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Main *m_bmain;
|
Main *m_bmain;
|
||||||
|
@ -47,6 +47,7 @@ extern "C" {
|
|||||||
#include "DNA_anim_types.h"
|
#include "DNA_anim_types.h"
|
||||||
#include "DNA_armature_types.h"
|
#include "DNA_armature_types.h"
|
||||||
#include "DNA_camera_types.h"
|
#include "DNA_camera_types.h"
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
#include "DNA_constraint_types.h"
|
#include "DNA_constraint_types.h"
|
||||||
#include "DNA_curve_types.h"
|
#include "DNA_curve_types.h"
|
||||||
#include "DNA_effect_types.h"
|
#include "DNA_effect_types.h"
|
||||||
@ -599,6 +600,18 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode
|
|||||||
TimeSourceKey time_src_key;
|
TimeSourceKey time_src_key;
|
||||||
add_relation(time_src_key, constraint_op_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Animation]");
|
add_relation(time_src_key, constraint_op_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Animation]");
|
||||||
}
|
}
|
||||||
|
else if (cti->type == CONSTRAINT_TYPE_TRANSFORM_CACHE) {
|
||||||
|
/* TODO(kevin): This is more a TimeSource -> CacheFile -> Constraint dependency chain. */
|
||||||
|
TimeSourceKey time_src_key;
|
||||||
|
add_relation(time_src_key, constraint_op_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Animation]");
|
||||||
|
|
||||||
|
bTransformCacheConstraint *data = (bTransformCacheConstraint *)con->data;
|
||||||
|
|
||||||
|
if (data->cache_file) {
|
||||||
|
ComponentKey cache_key(&data->cache_file->id, DEPSNODE_TYPE_CACHE);
|
||||||
|
add_relation(cache_key, constraint_op_key, DEPSREL_TYPE_CACHE, cti->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (cti->get_constraint_targets) {
|
else if (cti->get_constraint_targets) {
|
||||||
ListBase targets = {NULL, NULL};
|
ListBase targets = {NULL, NULL};
|
||||||
cti->get_constraint_targets(con, &targets);
|
cti->get_constraint_targets(con, &targets);
|
||||||
|
@ -90,6 +90,7 @@ static const int deg_debug_node_type_color_map[][2] = {
|
|||||||
{DEPSNODE_TYPE_GEOMETRY, 8},
|
{DEPSNODE_TYPE_GEOMETRY, 8},
|
||||||
{DEPSNODE_TYPE_SEQUENCER, 9},
|
{DEPSNODE_TYPE_SEQUENCER, 9},
|
||||||
{DEPSNODE_TYPE_SHADING, 10},
|
{DEPSNODE_TYPE_SHADING, 10},
|
||||||
|
{DEPSNODE_TYPE_CACHE, 11},
|
||||||
{-1, 0}
|
{-1, 0}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@ -401,6 +402,7 @@ static void deg_debug_graphviz_node(const DebugContext &ctx,
|
|||||||
case DEPSNODE_TYPE_EVAL_POSE:
|
case DEPSNODE_TYPE_EVAL_POSE:
|
||||||
case DEPSNODE_TYPE_BONE:
|
case DEPSNODE_TYPE_BONE:
|
||||||
case DEPSNODE_TYPE_SHADING:
|
case DEPSNODE_TYPE_SHADING:
|
||||||
|
case DEPSNODE_TYPE_CACHE:
|
||||||
case DEPSNODE_TYPE_EVAL_PARTICLES:
|
case DEPSNODE_TYPE_EVAL_PARTICLES:
|
||||||
{
|
{
|
||||||
ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
|
ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
#include "DNA_object_types.h"
|
#include "DNA_object_types.h"
|
||||||
#include "DNA_scene_types.h"
|
#include "DNA_scene_types.h"
|
||||||
|
|
||||||
@ -89,6 +90,7 @@ static DEG::eDepsNode_Type deg_build_object_component_type(
|
|||||||
case DEG_OB_COMP_BONE: return DEG::DEPSNODE_TYPE_BONE;
|
case DEG_OB_COMP_BONE: return DEG::DEPSNODE_TYPE_BONE;
|
||||||
case DEG_OB_COMP_EVAL_PARTICLES: return DEG::DEPSNODE_TYPE_EVAL_PARTICLES;
|
case DEG_OB_COMP_EVAL_PARTICLES: return DEG::DEPSNODE_TYPE_EVAL_PARTICLES;
|
||||||
case DEG_OB_COMP_SHADING: return DEG::DEPSNODE_TYPE_SHADING;
|
case DEG_OB_COMP_SHADING: return DEG::DEPSNODE_TYPE_SHADING;
|
||||||
|
case DEG_OB_COMP_CACHE: return DEG::DEPSNODE_TYPE_CACHE;
|
||||||
}
|
}
|
||||||
return DEG::DEPSNODE_TYPE_UNDEFINED;
|
return DEG::DEPSNODE_TYPE_UNDEFINED;
|
||||||
}
|
}
|
||||||
@ -126,6 +128,20 @@ void DEG_add_object_relation(DepsNodeHandle *handle,
|
|||||||
description);
|
description);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DEG_add_object_cache_relation(DepsNodeHandle *handle,
|
||||||
|
CacheFile *cache_file,
|
||||||
|
eDepsObjectComponentType component,
|
||||||
|
const char *description)
|
||||||
|
{
|
||||||
|
DEG::eDepsNode_Type type = deg_build_object_component_type(component);
|
||||||
|
DEG::ComponentKey comp_key(&cache_file->id, type);
|
||||||
|
DEG::DepsNodeHandle *deg_handle = get_handle(handle);
|
||||||
|
deg_handle->builder->add_node_handle_relation(comp_key,
|
||||||
|
deg_handle,
|
||||||
|
DEG::DEPSREL_TYPE_CACHE,
|
||||||
|
description);
|
||||||
|
}
|
||||||
|
|
||||||
void DEG_add_bone_relation(DepsNodeHandle *handle,
|
void DEG_add_bone_relation(DepsNodeHandle *handle,
|
||||||
Object *ob,
|
Object *ob,
|
||||||
const char *bone_name,
|
const char *bone_name,
|
||||||
|
@ -133,6 +133,8 @@ typedef enum eDepsNode_Type {
|
|||||||
DEPSNODE_TYPE_EVAL_PARTICLES = 23,
|
DEPSNODE_TYPE_EVAL_PARTICLES = 23,
|
||||||
/* Material Shading Component */
|
/* Material Shading Component */
|
||||||
DEPSNODE_TYPE_SHADING = 24,
|
DEPSNODE_TYPE_SHADING = 24,
|
||||||
|
/* Cache Component */
|
||||||
|
DEPSNODE_TYPE_CACHE = 25,
|
||||||
} eDepsNode_Type;
|
} eDepsNode_Type;
|
||||||
|
|
||||||
/* Identifiers for common operations (as an enum). */
|
/* Identifiers for common operations (as an enum). */
|
||||||
@ -330,6 +332,9 @@ typedef enum eDepsRelation_Type {
|
|||||||
|
|
||||||
/* relationship is used to trigger editor/screen updates */
|
/* relationship is used to trigger editor/screen updates */
|
||||||
DEPSREL_TYPE_UPDATE_UI,
|
DEPSREL_TYPE_UPDATE_UI,
|
||||||
|
|
||||||
|
/* cache dependency */
|
||||||
|
DEPSREL_TYPE_CACHE,
|
||||||
} eDepsRelation_Type;
|
} eDepsRelation_Type;
|
||||||
|
|
||||||
} // namespace DEG
|
} // namespace DEG
|
||||||
|
@ -366,6 +366,11 @@ static DepsNodeFactoryImpl<ParticlesComponentDepsNode> DNTI_EVAL_PARTICLES;
|
|||||||
DEG_DEPSNODE_DEFINE(ShadingComponentDepsNode, DEPSNODE_TYPE_SHADING, "Shading Component");
|
DEG_DEPSNODE_DEFINE(ShadingComponentDepsNode, DEPSNODE_TYPE_SHADING, "Shading Component");
|
||||||
static DepsNodeFactoryImpl<ShadingComponentDepsNode> DNTI_SHADING;
|
static DepsNodeFactoryImpl<ShadingComponentDepsNode> DNTI_SHADING;
|
||||||
|
|
||||||
|
/* Cache Component Defines ============================ */
|
||||||
|
|
||||||
|
DEG_DEPSNODE_DEFINE(CacheComponentDepsNode, DEPSNODE_TYPE_CACHE, "Cache Component");
|
||||||
|
static DepsNodeFactoryImpl<CacheComponentDepsNode> DNTI_CACHE;
|
||||||
|
|
||||||
|
|
||||||
/* Node Types Register =================================== */
|
/* Node Types Register =================================== */
|
||||||
|
|
||||||
@ -383,6 +388,8 @@ void deg_register_component_depsnodes()
|
|||||||
|
|
||||||
deg_register_node_typeinfo(&DNTI_EVAL_PARTICLES);
|
deg_register_node_typeinfo(&DNTI_EVAL_PARTICLES);
|
||||||
deg_register_node_typeinfo(&DNTI_SHADING);
|
deg_register_node_typeinfo(&DNTI_SHADING);
|
||||||
|
|
||||||
|
deg_register_node_typeinfo(&DNTI_CACHE);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace DEG
|
} // namespace DEG
|
||||||
|
@ -209,6 +209,10 @@ struct ShadingComponentDepsNode : public ComponentDepsNode {
|
|||||||
DEG_DEPSNODE_DECLARE;
|
DEG_DEPSNODE_DECLARE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CacheComponentDepsNode : public ComponentDepsNode {
|
||||||
|
DEG_DEPSNODE_DECLARE;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
void deg_register_component_depsnodes();
|
void deg_register_component_depsnodes();
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
|
|
||||||
#include "DNA_anim_types.h"
|
#include "DNA_anim_types.h"
|
||||||
#include "DNA_armature_types.h"
|
#include "DNA_armature_types.h"
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
#include "DNA_camera_types.h"
|
#include "DNA_camera_types.h"
|
||||||
#include "DNA_object_types.h"
|
#include "DNA_object_types.h"
|
||||||
#include "DNA_particle_types.h"
|
#include "DNA_particle_types.h"
|
||||||
@ -1577,6 +1578,88 @@ static bAnimChannelType ACF_DSTEX =
|
|||||||
|
|
||||||
/* Camera Expander ------------------------------------------- */
|
/* Camera Expander ------------------------------------------- */
|
||||||
|
|
||||||
|
// TODO: just get this from RNA?
|
||||||
|
static int acf_dscachefile_icon(bAnimListElem *ale)
|
||||||
|
{
|
||||||
|
UNUSED_VARS(ale);
|
||||||
|
return ICON_FILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the appropriate flag(s) for the setting when it is valid */
|
||||||
|
static int acf_dscachefile_setting_flag(bAnimContext *ac, eAnimChannel_Settings setting, bool *neg)
|
||||||
|
{
|
||||||
|
/* clear extra return data first */
|
||||||
|
*neg = false;
|
||||||
|
|
||||||
|
switch (setting) {
|
||||||
|
case ACHANNEL_SETTING_EXPAND: /* expanded */
|
||||||
|
return CACHEFILE_DS_EXPAND;
|
||||||
|
|
||||||
|
case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
|
||||||
|
return ADT_NLA_EVAL_OFF;
|
||||||
|
|
||||||
|
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
|
||||||
|
*neg = true;
|
||||||
|
return ADT_CURVES_NOT_VISIBLE;
|
||||||
|
|
||||||
|
case ACHANNEL_SETTING_SELECT: /* selected */
|
||||||
|
return ADT_UI_SELECTED;
|
||||||
|
|
||||||
|
default: /* unsupported */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
UNUSED_VARS(ac);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get pointer to the setting */
|
||||||
|
static void *acf_dscachefile_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
|
||||||
|
{
|
||||||
|
CacheFile *cache_file = (CacheFile *)ale->data;
|
||||||
|
|
||||||
|
/* clear extra return data first */
|
||||||
|
*type = 0;
|
||||||
|
|
||||||
|
switch (setting) {
|
||||||
|
case ACHANNEL_SETTING_EXPAND: /* expanded */
|
||||||
|
return GET_ACF_FLAG_PTR(cache_file->flag, type);
|
||||||
|
|
||||||
|
case ACHANNEL_SETTING_SELECT: /* selected */
|
||||||
|
case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
|
||||||
|
case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
|
||||||
|
if (cache_file->adt) {
|
||||||
|
return GET_ACF_FLAG_PTR(cache_file->adt->flag, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
default: /* unsupported */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CacheFile expander type define. */
|
||||||
|
static bAnimChannelType ACF_DSCACHEFILE =
|
||||||
|
{
|
||||||
|
"Cache File Expander", /* type name */
|
||||||
|
ACHANNEL_ROLE_EXPANDER, /* role */
|
||||||
|
|
||||||
|
acf_generic_dataexpand_color, /* backdrop color */
|
||||||
|
acf_generic_dataexpand_backdrop, /* backdrop */
|
||||||
|
acf_generic_indention_1, /* indent level */
|
||||||
|
acf_generic_basic_offset, /* offset */
|
||||||
|
|
||||||
|
acf_generic_idblock_name, /* name */
|
||||||
|
acf_generic_idfill_name_prop, /* name prop */
|
||||||
|
acf_dscachefile_icon, /* icon */
|
||||||
|
|
||||||
|
acf_generic_dataexpand_setting_valid, /* has setting */
|
||||||
|
acf_dscachefile_setting_flag, /* flag for setting */
|
||||||
|
acf_dscachefile_setting_ptr /* pointer for setting */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Camera Expander ------------------------------------------- */
|
||||||
|
|
||||||
// TODO: just get this from RNA?
|
// TODO: just get this from RNA?
|
||||||
static int acf_dscam_icon(bAnimListElem *UNUSED(ale))
|
static int acf_dscam_icon(bAnimListElem *UNUSED(ale))
|
||||||
{
|
{
|
||||||
@ -3388,6 +3471,7 @@ static void ANIM_init_channel_typeinfo_data(void)
|
|||||||
animchannelTypeInfo[type++] = &ACF_DSMAT; /* Material Channel */
|
animchannelTypeInfo[type++] = &ACF_DSMAT; /* Material Channel */
|
||||||
animchannelTypeInfo[type++] = &ACF_DSLAM; /* Lamp Channel */
|
animchannelTypeInfo[type++] = &ACF_DSLAM; /* Lamp Channel */
|
||||||
animchannelTypeInfo[type++] = &ACF_DSCAM; /* Camera Channel */
|
animchannelTypeInfo[type++] = &ACF_DSCAM; /* Camera Channel */
|
||||||
|
animchannelTypeInfo[type++] = &ACF_DSCACHEFILE; /* CacheFile Channel */
|
||||||
animchannelTypeInfo[type++] = &ACF_DSCUR; /* Curve Channel */
|
animchannelTypeInfo[type++] = &ACF_DSCUR; /* Curve Channel */
|
||||||
animchannelTypeInfo[type++] = &ACF_DSSKEY; /* ShapeKey Channel */
|
animchannelTypeInfo[type++] = &ACF_DSSKEY; /* ShapeKey Channel */
|
||||||
animchannelTypeInfo[type++] = &ACF_DSWOR; /* World Channel */
|
animchannelTypeInfo[type++] = &ACF_DSWOR; /* World Channel */
|
||||||
|
@ -120,6 +120,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
|
|||||||
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
||||||
case ANIMTYPE_DSLAM:
|
case ANIMTYPE_DSLAM:
|
||||||
case ANIMTYPE_DSCAM:
|
case ANIMTYPE_DSCAM:
|
||||||
|
case ANIMTYPE_DSCACHEFILE:
|
||||||
case ANIMTYPE_DSCUR:
|
case ANIMTYPE_DSCUR:
|
||||||
case ANIMTYPE_DSSKEY:
|
case ANIMTYPE_DSSKEY:
|
||||||
case ANIMTYPE_DSWOR:
|
case ANIMTYPE_DSWOR:
|
||||||
@ -175,6 +176,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
|
|||||||
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
||||||
case ANIMTYPE_DSLAM:
|
case ANIMTYPE_DSLAM:
|
||||||
case ANIMTYPE_DSCAM:
|
case ANIMTYPE_DSCAM:
|
||||||
|
case ANIMTYPE_DSCACHEFILE:
|
||||||
case ANIMTYPE_DSCUR:
|
case ANIMTYPE_DSCUR:
|
||||||
case ANIMTYPE_DSSKEY:
|
case ANIMTYPE_DSSKEY:
|
||||||
case ANIMTYPE_DSWOR:
|
case ANIMTYPE_DSWOR:
|
||||||
@ -275,6 +277,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
|
|||||||
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
||||||
case ANIMTYPE_DSLAM:
|
case ANIMTYPE_DSLAM:
|
||||||
case ANIMTYPE_DSCAM:
|
case ANIMTYPE_DSCAM:
|
||||||
|
case ANIMTYPE_DSCACHEFILE:
|
||||||
case ANIMTYPE_DSCUR:
|
case ANIMTYPE_DSCUR:
|
||||||
case ANIMTYPE_DSSKEY:
|
case ANIMTYPE_DSSKEY:
|
||||||
case ANIMTYPE_DSWOR:
|
case ANIMTYPE_DSWOR:
|
||||||
@ -370,6 +373,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
|
|||||||
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
||||||
case ANIMTYPE_DSLAM:
|
case ANIMTYPE_DSLAM:
|
||||||
case ANIMTYPE_DSCAM:
|
case ANIMTYPE_DSCAM:
|
||||||
|
case ANIMTYPE_DSCACHEFILE:
|
||||||
case ANIMTYPE_DSCUR:
|
case ANIMTYPE_DSCUR:
|
||||||
case ANIMTYPE_DSSKEY:
|
case ANIMTYPE_DSSKEY:
|
||||||
case ANIMTYPE_DSWOR:
|
case ANIMTYPE_DSWOR:
|
||||||
@ -2716,6 +2720,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
|
|||||||
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
||||||
case ANIMTYPE_DSLAM:
|
case ANIMTYPE_DSLAM:
|
||||||
case ANIMTYPE_DSCAM:
|
case ANIMTYPE_DSCAM:
|
||||||
|
case ANIMTYPE_DSCACHEFILE:
|
||||||
case ANIMTYPE_DSCUR:
|
case ANIMTYPE_DSCUR:
|
||||||
case ANIMTYPE_DSSKEY:
|
case ANIMTYPE_DSSKEY:
|
||||||
case ANIMTYPE_DSWOR:
|
case ANIMTYPE_DSWOR:
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
#include "DNA_anim_types.h"
|
#include "DNA_anim_types.h"
|
||||||
#include "DNA_armature_types.h"
|
#include "DNA_armature_types.h"
|
||||||
#include "DNA_camera_types.h"
|
#include "DNA_camera_types.h"
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
#include "DNA_lamp_types.h"
|
#include "DNA_lamp_types.h"
|
||||||
#include "DNA_lattice_types.h"
|
#include "DNA_lattice_types.h"
|
||||||
#include "DNA_linestyle_types.h"
|
#include "DNA_linestyle_types.h"
|
||||||
@ -199,6 +200,16 @@ static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction)
|
|||||||
|
|
||||||
ac->mode = saction->mode;
|
ac->mode = saction->mode;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case SACTCONT_CACHEFILE: /* Cache File */ /* XXX review how this mode is handled... */
|
||||||
|
/* update scene-pointer (no need to check for pinning yet, as not implemented) */
|
||||||
|
saction->ads.source = (ID *)ac->scene;
|
||||||
|
|
||||||
|
ac->datatype = ANIMCONT_CHANNEL;
|
||||||
|
ac->data = &saction->ads;
|
||||||
|
|
||||||
|
ac->mode = saction->mode;
|
||||||
|
return true;
|
||||||
|
|
||||||
case SACTCONT_MASK: /* Mask */ /* XXX review how this mode is handled... */
|
case SACTCONT_MASK: /* Mask */ /* XXX review how this mode is handled... */
|
||||||
{
|
{
|
||||||
@ -660,6 +671,19 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
|
|||||||
ale->adt = BKE_animdata_from_id(data);
|
ale->adt = BKE_animdata_from_id(data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ANIMTYPE_DSCACHEFILE:
|
||||||
|
{
|
||||||
|
CacheFile *cache_file = (CacheFile *)data;
|
||||||
|
AnimData *adt = cache_file->adt;
|
||||||
|
|
||||||
|
ale->flag = FILTER_CACHEFILE_OBJD(cache_file);
|
||||||
|
|
||||||
|
ale->key_data = (adt) ? adt->action : NULL;
|
||||||
|
ale->datatype = ALE_ACT;
|
||||||
|
|
||||||
|
ale->adt = BKE_animdata_from_id(data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ANIMTYPE_DSCUR:
|
case ANIMTYPE_DSCUR:
|
||||||
{
|
{
|
||||||
Curve *cu = (Curve *)data;
|
Curve *cu = (Curve *)data;
|
||||||
@ -1751,6 +1775,42 @@ static size_t animdata_filter_ds_gpencil(bAnimContext *ac, ListBase *anim_data,
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper for Cache File data integrated with main DopeSheet */
|
||||||
|
static size_t animdata_filter_ds_cachefile(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, CacheFile *cache_file, int filter_mode)
|
||||||
|
{
|
||||||
|
ListBase tmp_data = {NULL, NULL};
|
||||||
|
size_t tmp_items = 0;
|
||||||
|
size_t items = 0;
|
||||||
|
|
||||||
|
/* add relevant animation channels for Cache File */
|
||||||
|
BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_CACHEFILE_OBJD(cache_file))
|
||||||
|
{
|
||||||
|
/* add animation channels */
|
||||||
|
tmp_items += animfilter_block_data(ac, &tmp_data, ads, &cache_file->id, filter_mode);
|
||||||
|
}
|
||||||
|
END_ANIMFILTER_SUBCHANNELS;
|
||||||
|
|
||||||
|
/* did we find anything? */
|
||||||
|
if (tmp_items) {
|
||||||
|
/* include data-expand widget first */
|
||||||
|
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
|
||||||
|
/* check if filtering by active status */
|
||||||
|
// XXX: active check here needs checking
|
||||||
|
if (ANIMCHANNEL_ACTIVEOK(cache_file)) {
|
||||||
|
ANIMCHANNEL_NEW_CHANNEL(cache_file, ANIMTYPE_DSCACHEFILE, cache_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now add the list of collected channels */
|
||||||
|
BLI_movelisttolist(anim_data, &tmp_data);
|
||||||
|
BLI_assert(BLI_listbase_is_empty(&tmp_data));
|
||||||
|
items += tmp_items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return the number of items added to the list */
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
/* Helper for Mask Editing - mask layers */
|
/* Helper for Mask Editing - mask layers */
|
||||||
static size_t animdata_filter_mask_data(ListBase *anim_data, Mask *mask, const int filter_mode)
|
static size_t animdata_filter_mask_data(ListBase *anim_data, Mask *mask, const int filter_mode)
|
||||||
{
|
{
|
||||||
@ -2839,6 +2899,12 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b
|
|||||||
filter_mode |= ANIMFILTER_SELEDIT;
|
filter_mode |= ANIMFILTER_SELEDIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Cache files level animations (frame duration and such). */
|
||||||
|
CacheFile *cache_file = G.main->cachefiles.first;
|
||||||
|
for (; cache_file; cache_file = cache_file->id.next) {
|
||||||
|
items += animdata_filter_ds_cachefile(ac, anim_data, ads, cache_file, filter_mode);
|
||||||
|
}
|
||||||
|
|
||||||
/* scene-linked animation - e.g. world, compositing nodes, scene anim (including sequencer currently) */
|
/* scene-linked animation - e.g. world, compositing nodes, scene anim (including sequencer currently) */
|
||||||
items += animdata_filter_dopesheet_scene(ac, anim_data, ads, scene, filter_mode);
|
items += animdata_filter_dopesheet_scene(ac, anim_data, ads, scene, filter_mode);
|
||||||
|
|
||||||
@ -2950,7 +3016,11 @@ static size_t animdata_filter_animchan(bAnimContext *ac, ListBase *anim_data, bD
|
|||||||
case ANIMTYPE_OBJECT:
|
case ANIMTYPE_OBJECT:
|
||||||
items += animdata_filter_dopesheet_ob(ac, anim_data, ads, channel->data, filter_mode);
|
items += animdata_filter_dopesheet_ob(ac, anim_data, ads, channel->data, filter_mode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ANIMTYPE_DSCACHEFILE:
|
||||||
|
items += animdata_filter_ds_cachefile(ac, anim_data, ads, channel->data, filter_mode);
|
||||||
|
break;
|
||||||
|
|
||||||
case ANIMTYPE_ANIMDATA:
|
case ANIMTYPE_ANIMDATA:
|
||||||
items += animfilter_block_data(ac, anim_data, ads, channel->id, filter_mode);
|
items += animfilter_block_data(ac, anim_data, ads, channel->id, filter_mode);
|
||||||
break;
|
break;
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
|
|
||||||
#include "DNA_anim_types.h"
|
#include "DNA_anim_types.h"
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
#include "DNA_object_types.h"
|
#include "DNA_object_types.h"
|
||||||
#include "DNA_scene_types.h"
|
#include "DNA_scene_types.h"
|
||||||
#include "DNA_gpencil_types.h"
|
#include "DNA_gpencil_types.h"
|
||||||
@ -965,6 +966,37 @@ void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, DLRBT_Tree *bl
|
|||||||
ANIM_animdata_freelist(&anim_data);
|
ANIM_animdata_freelist(&anim_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cachefile_to_keylist(bDopeSheet *ads, CacheFile *cache_file, DLRBT_Tree *keys, DLRBT_Tree *blocks)
|
||||||
|
{
|
||||||
|
if (cache_file == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create a dummy wrapper data to work with */
|
||||||
|
bAnimListElem dummychan = {NULL};
|
||||||
|
dummychan.type = ANIMTYPE_DSCACHEFILE;
|
||||||
|
dummychan.data = cache_file;
|
||||||
|
dummychan.id = &cache_file->id;
|
||||||
|
dummychan.adt = cache_file->adt;
|
||||||
|
|
||||||
|
bAnimContext ac = {NULL};
|
||||||
|
ac.ads = ads;
|
||||||
|
ac.data = &dummychan;
|
||||||
|
ac.datatype = ANIMCONT_CHANNEL;
|
||||||
|
|
||||||
|
/* get F-Curves to take keyframes from */
|
||||||
|
ListBase anim_data = { NULL, NULL };
|
||||||
|
int filter = ANIMFILTER_DATA_VISIBLE; // curves only
|
||||||
|
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||||
|
|
||||||
|
/* loop through each F-Curve, grabbing the keyframes */
|
||||||
|
for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) {
|
||||||
|
fcurve_to_keylist(ale->adt, ale->data, keys, blocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
ANIM_animdata_freelist(&anim_data);
|
||||||
|
}
|
||||||
|
|
||||||
void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, DLRBT_Tree *blocks)
|
void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, DLRBT_Tree *blocks)
|
||||||
{
|
{
|
||||||
BezTriple *bezt;
|
BezTriple *bezt;
|
||||||
|
@ -156,6 +156,7 @@ typedef enum eAnim_ChannelType {
|
|||||||
ANIMTYPE_DSMAT,
|
ANIMTYPE_DSMAT,
|
||||||
ANIMTYPE_DSLAM,
|
ANIMTYPE_DSLAM,
|
||||||
ANIMTYPE_DSCAM,
|
ANIMTYPE_DSCAM,
|
||||||
|
ANIMTYPE_DSCACHEFILE,
|
||||||
ANIMTYPE_DSCUR,
|
ANIMTYPE_DSCUR,
|
||||||
ANIMTYPE_DSSKEY,
|
ANIMTYPE_DSSKEY,
|
||||||
ANIMTYPE_DSWOR,
|
ANIMTYPE_DSWOR,
|
||||||
@ -275,6 +276,7 @@ typedef enum eAnimFilter_Flags {
|
|||||||
#define FILTER_MAT_OBJD(ma) (CHECK_TYPE_INLINE(ma, Material *), ((ma->flag & MA_DS_EXPAND)))
|
#define FILTER_MAT_OBJD(ma) (CHECK_TYPE_INLINE(ma, Material *), ((ma->flag & MA_DS_EXPAND)))
|
||||||
#define FILTER_LAM_OBJD(la) (CHECK_TYPE_INLINE(la, Lamp *), ((la->flag & LA_DS_EXPAND)))
|
#define FILTER_LAM_OBJD(la) (CHECK_TYPE_INLINE(la, Lamp *), ((la->flag & LA_DS_EXPAND)))
|
||||||
#define FILTER_CAM_OBJD(ca) (CHECK_TYPE_INLINE(ca, Camera *), ((ca->flag & CAM_DS_EXPAND)))
|
#define FILTER_CAM_OBJD(ca) (CHECK_TYPE_INLINE(ca, Camera *), ((ca->flag & CAM_DS_EXPAND)))
|
||||||
|
#define FILTER_CACHEFILE_OBJD(cf) (CHECK_TYPE_INLINE(cf, CacheFile *), ((cf->flag & CACHEFILE_DS_EXPAND)))
|
||||||
#define FILTER_CUR_OBJD(cu) (CHECK_TYPE_INLINE(cu, Curve *), ((cu->flag & CU_DS_EXPAND)))
|
#define FILTER_CUR_OBJD(cu) (CHECK_TYPE_INLINE(cu, Curve *), ((cu->flag & CU_DS_EXPAND)))
|
||||||
#define FILTER_PART_OBJD(part) (CHECK_TYPE_INLINE(part, ParticleSettings *), ((part->flag & PART_DS_EXPAND)))
|
#define FILTER_PART_OBJD(part) (CHECK_TYPE_INLINE(part, ParticleSettings *), ((part->flag & PART_DS_EXPAND)))
|
||||||
#define FILTER_MBALL_OBJD(mb) (CHECK_TYPE_INLINE(mb, MetaBall *), ((mb->flag2 & MB_DS_EXPAND)))
|
#define FILTER_MBALL_OBJD(mb) (CHECK_TYPE_INLINE(mb, MetaBall *), ((mb->flag2 & MB_DS_EXPAND)))
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
struct bAnimContext;
|
struct bAnimContext;
|
||||||
struct AnimData;
|
struct AnimData;
|
||||||
|
struct CacheFile;
|
||||||
struct FCurve;
|
struct FCurve;
|
||||||
struct bDopeSheet;
|
struct bDopeSheet;
|
||||||
struct bAction;
|
struct bAction;
|
||||||
@ -141,6 +142,8 @@ void agroup_to_keylist(struct AnimData *adt, struct bActionGroup *agrp, struct D
|
|||||||
void action_to_keylist(struct AnimData *adt, struct bAction *act, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
|
void action_to_keylist(struct AnimData *adt, struct bAction *act, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
|
||||||
/* Object */
|
/* Object */
|
||||||
void ob_to_keylist(struct bDopeSheet *ads, struct Object *ob, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
|
void ob_to_keylist(struct bDopeSheet *ads, struct Object *ob, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
|
||||||
|
/* Cache File */
|
||||||
|
void cachefile_to_keylist(struct bDopeSheet *ads, struct CacheFile *cache_file, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
|
||||||
/* Scene */
|
/* Scene */
|
||||||
void scene_to_keylist(struct bDopeSheet *ads, struct Scene *sce, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
|
void scene_to_keylist(struct bDopeSheet *ads, struct Scene *sce, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
|
||||||
/* DopeSheet Summary */
|
/* DopeSheet Summary */
|
||||||
|
@ -945,6 +945,7 @@ void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C);
|
|||||||
void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr);
|
void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr);
|
||||||
void uiTemplateComponentMenu(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name);
|
void uiTemplateComponentMenu(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name);
|
||||||
void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color);
|
void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color);
|
||||||
|
void uiTemplateCacheFile(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname);
|
||||||
|
|
||||||
/* Default UIList class name, keep in sync with its declaration in bl_ui/__init__.py */
|
/* Default UIList class name, keep in sync with its declaration in bl_ui/__init__.py */
|
||||||
#define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list"
|
#define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list"
|
||||||
|
@ -1541,6 +1541,8 @@ int UI_idcode_icon_get(const int idcode)
|
|||||||
return ICON_BRUSH_DATA;
|
return ICON_BRUSH_DATA;
|
||||||
case ID_CA:
|
case ID_CA:
|
||||||
return ICON_CAMERA_DATA;
|
return ICON_CAMERA_DATA;
|
||||||
|
case ID_CF:
|
||||||
|
return ICON_FILE;
|
||||||
case ID_CU:
|
case ID_CU:
|
||||||
return ICON_CURVE_DATA;
|
return ICON_CURVE_DATA;
|
||||||
case ID_GD:
|
case ID_GD:
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
#include "DNA_node_types.h"
|
#include "DNA_node_types.h"
|
||||||
#include "DNA_scene_types.h"
|
#include "DNA_scene_types.h"
|
||||||
#include "DNA_object_types.h"
|
#include "DNA_object_types.h"
|
||||||
@ -368,6 +369,7 @@ static const char *template_id_browse_tip(StructRNA *type)
|
|||||||
case ID_MSK: return N_("Browse Mask to be linked");
|
case ID_MSK: return N_("Browse Mask to be linked");
|
||||||
case ID_PAL: return N_("Browse Palette Data to be linked");
|
case ID_PAL: return N_("Browse Palette Data to be linked");
|
||||||
case ID_PC: return N_("Browse Paint Curve Data to be linked");
|
case ID_PC: return N_("Browse Paint Curve Data to be linked");
|
||||||
|
case ID_CF: return N_("Browse Cache Files to be linked");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return N_("Browse ID data to be linked");
|
return N_("Browse ID data to be linked");
|
||||||
@ -3848,3 +3850,73 @@ void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float *color)
|
|||||||
|
|
||||||
UI_block_align_end(block);
|
UI_block_align_end(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************* Cache File *********************************/
|
||||||
|
|
||||||
|
void uiTemplateCacheFile(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname)
|
||||||
|
{
|
||||||
|
if (!ptr->data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
|
||||||
|
|
||||||
|
if (!prop) {
|
||||||
|
printf("%s: property not found: %s.%s\n",
|
||||||
|
__func__, RNA_struct_identifier(ptr->type), propname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RNA_property_type(prop) != PROP_POINTER) {
|
||||||
|
printf("%s: expected pointer property for %s.%s\n",
|
||||||
|
__func__, RNA_struct_identifier(ptr->type), propname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PointerRNA fileptr = RNA_property_pointer_get(ptr, prop);
|
||||||
|
CacheFile *file = fileptr.data;
|
||||||
|
|
||||||
|
uiLayoutSetContextPointer(layout, "edit_cachefile", &fileptr);
|
||||||
|
|
||||||
|
uiTemplateID(layout, C, ptr, propname, NULL, "CACHEFILE_OT_open", NULL);
|
||||||
|
|
||||||
|
if (!file) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uiLayout *row = uiLayoutRow(layout, false);
|
||||||
|
uiBlock *block = uiLayoutGetBlock(row);
|
||||||
|
uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("File Path:"), 0, 19, 145, 19, NULL, 0, 0, 0, 0, "");
|
||||||
|
|
||||||
|
row = uiLayoutRow(layout, false);
|
||||||
|
uiLayout *split = uiLayoutSplit(row, 0.0f, false);
|
||||||
|
row = uiLayoutRow(split, true);
|
||||||
|
|
||||||
|
uiItemR(row, &fileptr, "filepath", 0, "", ICON_NONE);
|
||||||
|
uiItemO(row, "", ICON_FILE_REFRESH, "cachefile.reload");
|
||||||
|
|
||||||
|
row = uiLayoutRow(layout, false);
|
||||||
|
uiItemR(row, &fileptr, "is_sequence", 0, "Is Sequence", ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(layout, false);
|
||||||
|
uiItemR(row, &fileptr, "override_frame", 0, "Override Frame", ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(layout, false);
|
||||||
|
uiLayoutSetEnabled(row, RNA_boolean_get(&fileptr, "override_frame"));
|
||||||
|
uiItemR(row, &fileptr, "frame", 0, "Frame", ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(layout, false);
|
||||||
|
uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(layout, false);
|
||||||
|
uiItemR(row, &fileptr, "scale", 0, "Scale", ICON_NONE);
|
||||||
|
|
||||||
|
/* TODO: unused for now, so no need to expose. */
|
||||||
|
#if 0
|
||||||
|
row = uiLayoutRow(layout, false);
|
||||||
|
uiItemR(row, &fileptr, "forward_axis", 0, "Forward Axis", ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(layout, false);
|
||||||
|
uiItemR(row, &fileptr, "up_axis", 0, "Up Axis", ICON_NONE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
@ -28,6 +28,8 @@ set(INC
|
|||||||
../../makesrna
|
../../makesrna
|
||||||
../../windowmanager
|
../../windowmanager
|
||||||
../../collada
|
../../collada
|
||||||
|
../../alembic
|
||||||
|
../../../../intern/guardedalloc
|
||||||
)
|
)
|
||||||
|
|
||||||
set(INC_SYS
|
set(INC_SYS
|
||||||
@ -35,9 +37,13 @@ set(INC_SYS
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(SRC
|
set(SRC
|
||||||
|
io_alembic.c
|
||||||
|
io_cache.c
|
||||||
io_collada.c
|
io_collada.c
|
||||||
io_ops.c
|
io_ops.c
|
||||||
|
|
||||||
|
io_alembic.h
|
||||||
|
io_cache.h
|
||||||
io_collada.h
|
io_collada.h
|
||||||
io_ops.h
|
io_ops.h
|
||||||
)
|
)
|
||||||
@ -46,6 +52,14 @@ if(WITH_OPENCOLLADA)
|
|||||||
add_definitions(-DWITH_COLLADA)
|
add_definitions(-DWITH_COLLADA)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_ALEMBIC)
|
||||||
|
add_definitions(-DWITH_ALEMBIC)
|
||||||
|
|
||||||
|
if(WITH_ALEMBIC_HDF5)
|
||||||
|
add_definitions(-DWITH_ALEMBIC_HDF5)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WITH_INTERNATIONAL)
|
if(WITH_INTERNATIONAL)
|
||||||
add_definitions(-DWITH_INTERNATIONAL)
|
add_definitions(-DWITH_INTERNATIONAL)
|
||||||
endif()
|
endif()
|
||||||
|
458
source/blender/editors/io/io_alembic.c
Normal file
458
source/blender/editors/io/io_alembic.c
Normal file
@ -0,0 +1,458 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2016 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef WITH_ALEMBIC
|
||||||
|
|
||||||
|
/* needed for directory lookup */
|
||||||
|
#ifndef WIN32
|
||||||
|
# include <dirent.h>
|
||||||
|
#else
|
||||||
|
# include "BLI_winstuff.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
#include "DNA_mesh_types.h"
|
||||||
|
#include "DNA_object_types.h"
|
||||||
|
#include "DNA_scene_types.h"
|
||||||
|
#include "DNA_space_types.h"
|
||||||
|
|
||||||
|
#include "BKE_context.h"
|
||||||
|
#include "BKE_global.h"
|
||||||
|
#include "BKE_main.h"
|
||||||
|
#include "BKE_report.h"
|
||||||
|
|
||||||
|
#include "BLI_listbase.h"
|
||||||
|
#include "BLI_math_vector.h"
|
||||||
|
#include "BLI_path_util.h"
|
||||||
|
#include "BLI_string.h"
|
||||||
|
#include "BLI_utildefines.h"
|
||||||
|
|
||||||
|
#include "BLT_translation.h"
|
||||||
|
|
||||||
|
#include "RNA_access.h"
|
||||||
|
#include "RNA_define.h"
|
||||||
|
#include "RNA_enum_types.h"
|
||||||
|
|
||||||
|
#include "UI_interface.h"
|
||||||
|
#include "UI_resources.h"
|
||||||
|
|
||||||
|
#include "WM_api.h"
|
||||||
|
#include "WM_types.h"
|
||||||
|
|
||||||
|
#include "io_alembic.h"
|
||||||
|
|
||||||
|
#include "ABC_alembic.h"
|
||||||
|
|
||||||
|
static int wm_alembic_export_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
|
{
|
||||||
|
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
|
||||||
|
char filepath[FILE_MAX];
|
||||||
|
BLI_strncpy(filepath, G.main->name, sizeof(filepath));
|
||||||
|
BLI_replace_extension(filepath, sizeof(filepath), ".abc");
|
||||||
|
RNA_string_set(op->ptr, "filepath", filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
WM_event_add_fileselect(C, op);
|
||||||
|
|
||||||
|
return OPERATOR_RUNNING_MODAL;
|
||||||
|
|
||||||
|
UNUSED_VARS(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wm_alembic_export_exec(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
|
||||||
|
BKE_report(op->reports, RPT_ERROR, "No filename given");
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
char filename[FILE_MAX];
|
||||||
|
RNA_string_get(op->ptr, "filepath", filename);
|
||||||
|
|
||||||
|
const struct AlembicExportParams params = {
|
||||||
|
.frame_start = RNA_int_get(op->ptr, "start"),
|
||||||
|
.frame_end = RNA_int_get(op->ptr, "end"),
|
||||||
|
|
||||||
|
.frame_step_xform = 1.0 / (double)RNA_int_get(op->ptr, "xsamples"),
|
||||||
|
.frame_step_shape = 1.0 / (double)RNA_int_get(op->ptr, "gsamples"),
|
||||||
|
|
||||||
|
.shutter_open = RNA_float_get(op->ptr, "sh_open"),
|
||||||
|
.shutter_close = RNA_float_get(op->ptr, "sh_close"),
|
||||||
|
|
||||||
|
.selected_only = RNA_boolean_get(op->ptr, "selected"),
|
||||||
|
.uvs = RNA_boolean_get(op->ptr, "uvs"),
|
||||||
|
.normals = RNA_boolean_get(op->ptr, "normals"),
|
||||||
|
.vcolors = RNA_boolean_get(op->ptr, "vcolors"),
|
||||||
|
.apply_subdiv = RNA_boolean_get(op->ptr, "apply_subdiv"),
|
||||||
|
.flatten_hierarchy = RNA_boolean_get(op->ptr, "flatten"),
|
||||||
|
.visible_layers_only = RNA_boolean_get(op->ptr, "visible_layers_only"),
|
||||||
|
.renderable_only = RNA_boolean_get(op->ptr, "renderable_only"),
|
||||||
|
.face_sets = RNA_boolean_get(op->ptr, "face_sets"),
|
||||||
|
.use_subdiv_schema = RNA_boolean_get(op->ptr, "subdiv_schema"),
|
||||||
|
.compression_type = RNA_enum_get(op->ptr, "compression_type"),
|
||||||
|
.packuv = RNA_boolean_get(op->ptr, "packuv"),
|
||||||
|
|
||||||
|
.global_scale = RNA_float_get(op->ptr, "global_scale"),
|
||||||
|
};
|
||||||
|
|
||||||
|
ABC_export(CTX_data_scene(C), C, filename, ¶ms);
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr)
|
||||||
|
{
|
||||||
|
uiLayout *box = uiLayoutBox(layout);
|
||||||
|
uiLayout *row;
|
||||||
|
|
||||||
|
#ifdef WITH_ALEMBIC_HDF5
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemL(row, IFACE_("Archive Options:"), ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "compression_type", 0, NULL, ICON_NONE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
box = uiLayoutBox(layout);
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "global_scale", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
/* Scene Options */
|
||||||
|
box = uiLayoutBox(layout);
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemL(row, IFACE_("Scene Options:"), ICON_SCENE_DATA);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "start", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "end", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "xsamples", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "gsamples", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "sh_open", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "sh_close", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "selected", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "renderable_only", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "visible_layers_only", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "flatten", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
/* Object Data */
|
||||||
|
box = uiLayoutBox(layout);
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemL(row, IFACE_("Object Options:"), ICON_OBJECT_DATA);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "uvs", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "packuv", 0, NULL, ICON_NONE);
|
||||||
|
uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "uvs"));
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "normals", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "vcolors", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "face_sets", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "subdiv_schema", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "apply_subdiv", 0, NULL, ICON_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wm_alembic_export_draw(bContext *UNUSED(C), wmOperator *op)
|
||||||
|
{
|
||||||
|
PointerRNA ptr;
|
||||||
|
|
||||||
|
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
|
||||||
|
ui_alembic_export_settings(op->layout, &ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WM_OT_alembic_export(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
ot->name = "Export Alembic Archive";
|
||||||
|
ot->idname = "WM_OT_alembic_export";
|
||||||
|
|
||||||
|
ot->invoke = wm_alembic_export_invoke;
|
||||||
|
ot->exec = wm_alembic_export_exec;
|
||||||
|
ot->poll = WM_operator_winactive;
|
||||||
|
ot->ui = wm_alembic_export_draw;
|
||||||
|
|
||||||
|
WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_ALEMBIC,
|
||||||
|
FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH,
|
||||||
|
FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
|
||||||
|
|
||||||
|
RNA_def_int(ot->srna, "start", 1, INT_MIN, INT_MAX,
|
||||||
|
"Start Frame", "Start Frame", INT_MIN, INT_MAX);
|
||||||
|
|
||||||
|
RNA_def_int(ot->srna, "end", 1, INT_MIN, INT_MAX,
|
||||||
|
"End Frame", "End Frame", INT_MIN, INT_MAX);
|
||||||
|
|
||||||
|
RNA_def_int(ot->srna, "xsamples", 1, 1, 128,
|
||||||
|
"Transform Samples", "Number of times per frame transformations are sampled", 1, 128);
|
||||||
|
|
||||||
|
RNA_def_int(ot->srna, "gsamples", 1, 1, 128,
|
||||||
|
"Geometry Samples", "Number of times per frame object datas are sampled", 1, 128);
|
||||||
|
|
||||||
|
RNA_def_float(ot->srna, "sh_open", 0.0f, -1.0f, 1.0f,
|
||||||
|
"Shutter Open", "Time at which the shutter is open", -1.0f, 1.0f);
|
||||||
|
|
||||||
|
RNA_def_float(ot->srna, "sh_close", 1.0f, -1.0f, 1.0f,
|
||||||
|
"Shutter Close", "Time at which the shutter is closed", -1.0f, 1.0f);
|
||||||
|
|
||||||
|
RNA_def_boolean(ot->srna, "selected", 0,
|
||||||
|
"Selected Objects Only", "Export only selected objects");
|
||||||
|
|
||||||
|
RNA_def_boolean(ot->srna, "renderable_only", 1,
|
||||||
|
"Renderable Objects Only",
|
||||||
|
"Export only objects marked renderable in the outliner");
|
||||||
|
|
||||||
|
RNA_def_boolean(ot->srna, "visible_layers_only", 0,
|
||||||
|
"Visible Layers Only", "Export only objects in visible layers");
|
||||||
|
|
||||||
|
RNA_def_boolean(ot->srna, "flatten", 0,
|
||||||
|
"Flatten Hierarchy",
|
||||||
|
"Do not preserve objects' parent/children relationship");
|
||||||
|
|
||||||
|
RNA_def_boolean(ot->srna, "uvs", 1, "UVs", "Export UVs");
|
||||||
|
|
||||||
|
RNA_def_boolean(ot->srna, "packuv", 1, "Pack UV Islands",
|
||||||
|
"Export UVs with packed island");
|
||||||
|
|
||||||
|
RNA_def_boolean(ot->srna, "normals", 1, "Normals", "Export normals");
|
||||||
|
|
||||||
|
RNA_def_boolean(ot->srna, "vcolors", 0, "Vertex colors", "Export vertex colors");
|
||||||
|
|
||||||
|
RNA_def_boolean(ot->srna, "face_sets", 0, "Face Sets", "Export per face shading group assignments");
|
||||||
|
|
||||||
|
RNA_def_boolean(ot->srna, "subdiv_schema", 0,
|
||||||
|
"Use Subdivision Schema",
|
||||||
|
"Export meshes using Alembic's subdivision schema");
|
||||||
|
|
||||||
|
RNA_def_boolean(ot->srna, "apply_subdiv", 0,
|
||||||
|
"Apply Subsurf", "Export subdivision surfaces as meshes");
|
||||||
|
|
||||||
|
RNA_def_enum(ot->srna, "compression_type", rna_enum_abc_compression_items,
|
||||||
|
ABC_ARCHIVE_OGAWA, "Compression", "");
|
||||||
|
|
||||||
|
RNA_def_float(ot->srna, "global_scale", 1.0f, 0.0001f, 1000.0f, "Scale",
|
||||||
|
"Value by which to enlarge or shrink the objects with respect to the world's origin",
|
||||||
|
0.0001f, 1000.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
/* TODO(kevin): check on de-duplicating all this with code in image_ops.c */
|
||||||
|
|
||||||
|
typedef struct CacheFrame {
|
||||||
|
struct CacheFrame *next, *prev;
|
||||||
|
int framenr;
|
||||||
|
} CacheFrame;
|
||||||
|
|
||||||
|
static int cmp_frame(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const CacheFrame *frame_a = a;
|
||||||
|
const CacheFrame *frame_b = b;
|
||||||
|
|
||||||
|
if (frame_a->framenr < frame_b->framenr) return -1;
|
||||||
|
if (frame_a->framenr > frame_b->framenr) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_sequence_len(char *filename, int *ofs)
|
||||||
|
{
|
||||||
|
int frame;
|
||||||
|
int numdigit;
|
||||||
|
|
||||||
|
if (!BLI_path_frame_get(filename, &frame, &numdigit)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char path[FILE_MAX];
|
||||||
|
BLI_split_dir_part(filename, path, FILE_MAX);
|
||||||
|
|
||||||
|
DIR *dir = opendir(path);
|
||||||
|
|
||||||
|
const char *ext = ".abc";
|
||||||
|
const char *basename = BLI_path_basename(filename);
|
||||||
|
const int len = strlen(basename) - (numdigit + strlen(ext));
|
||||||
|
|
||||||
|
ListBase frames;
|
||||||
|
BLI_listbase_clear(&frames);
|
||||||
|
|
||||||
|
struct dirent *fname;
|
||||||
|
while ((fname = readdir(dir)) != NULL) {
|
||||||
|
/* do we have the right extension? */
|
||||||
|
if (!strstr(fname->d_name, ext)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!STREQLEN(basename, fname->d_name, len)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CacheFrame *cache_frame = MEM_callocN(sizeof(CacheFrame), "abc_frame");
|
||||||
|
|
||||||
|
BLI_path_frame_get(fname->d_name, &cache_frame->framenr, &numdigit);
|
||||||
|
|
||||||
|
BLI_addtail(&frames, cache_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
BLI_listbase_sort(&frames, cmp_frame);
|
||||||
|
|
||||||
|
CacheFrame *cache_frame = frames.first;
|
||||||
|
|
||||||
|
if (cache_frame) {
|
||||||
|
int frame_curr = cache_frame->framenr;
|
||||||
|
(*ofs) = frame_curr;
|
||||||
|
|
||||||
|
while (cache_frame && (cache_frame->framenr == frame_curr)) {
|
||||||
|
++frame_curr;
|
||||||
|
cache_frame = cache_frame->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLI_freelistN(&frames);
|
||||||
|
|
||||||
|
return frame_curr - (*ofs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
static void ui_alembic_import_settings(uiLayout *layout, PointerRNA *imfptr)
|
||||||
|
{
|
||||||
|
uiLayout *box = uiLayoutBox(layout);
|
||||||
|
uiLayout *row = uiLayoutRow(box, false);
|
||||||
|
uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "scale", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
box = uiLayoutBox(layout);
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemL(row, IFACE_("Options:"), ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "set_frame_range", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "is_sequence", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemR(row, imfptr, "validate_meshes", 0, NULL, ICON_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wm_alembic_import_draw(bContext *UNUSED(C), wmOperator *op)
|
||||||
|
{
|
||||||
|
PointerRNA ptr;
|
||||||
|
|
||||||
|
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
|
||||||
|
ui_alembic_import_settings(op->layout, &ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wm_alembic_import_exec(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
|
||||||
|
BKE_report(op->reports, RPT_ERROR, "No filename given");
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
char filename[FILE_MAX];
|
||||||
|
RNA_string_get(op->ptr, "filepath", filename);
|
||||||
|
|
||||||
|
const float scale = RNA_float_get(op->ptr, "scale");
|
||||||
|
const bool is_sequence = RNA_boolean_get(op->ptr, "is_sequence");
|
||||||
|
const bool set_frame_range = RNA_boolean_get(op->ptr, "set_frame_range");
|
||||||
|
const bool validate_meshes = RNA_boolean_get(op->ptr, "validate_meshes");
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
int sequence_len = 1;
|
||||||
|
|
||||||
|
if (is_sequence) {
|
||||||
|
sequence_len = get_sequence_len(filename, &offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
ABC_import(C, filename, scale, is_sequence, set_frame_range, sequence_len, offset, validate_meshes);
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WM_OT_alembic_import(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
ot->name = "Import Alembic Archive";
|
||||||
|
ot->idname = "WM_OT_alembic_import";
|
||||||
|
|
||||||
|
ot->invoke = WM_operator_filesel;
|
||||||
|
ot->exec = wm_alembic_import_exec;
|
||||||
|
ot->poll = WM_operator_winactive;
|
||||||
|
ot->ui = wm_alembic_import_draw;
|
||||||
|
|
||||||
|
WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_ALEMBIC,
|
||||||
|
FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH,
|
||||||
|
FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
|
||||||
|
|
||||||
|
RNA_def_float(ot->srna, "scale", 1.0f, 0.0001f, 1000.0f, "Scale",
|
||||||
|
"Value by which to enlarge or shrink the objects with respect to the world's origin",
|
||||||
|
0.0001f, 1000.0f);
|
||||||
|
|
||||||
|
RNA_def_boolean(ot->srna, "set_frame_range", true,
|
||||||
|
"Set Frame Range",
|
||||||
|
"If checked, update scene's start and end frame to match those of the Alembic archive");
|
||||||
|
|
||||||
|
RNA_def_boolean(ot->srna, "validate_meshes", 0,
|
||||||
|
"Validate Meshes", "Check imported mesh objects for invalid data (slow)");
|
||||||
|
|
||||||
|
RNA_def_boolean(ot->srna, "is_sequence", false, "Is Sequence",
|
||||||
|
"Set to true if the cache is split into separate files");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
37
source/blender/editors/io/io_alembic.h
Normal file
37
source/blender/editors/io/io_alembic.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2016 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __IO_ALEMBIC_H__
|
||||||
|
#define __IO_ALEMBIC_H__
|
||||||
|
|
||||||
|
/** \file blender/editors/io/io_alembic.h
|
||||||
|
* \ingroup editor/io
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct wmOperatorType;
|
||||||
|
|
||||||
|
void WM_OT_alembic_export(struct wmOperatorType *ot);
|
||||||
|
void WM_OT_alembic_import(struct wmOperatorType *ot);
|
||||||
|
|
||||||
|
#endif /* __IO_ALEMBIC_H__ */
|
162
source/blender/editors/io/io_cache.c
Normal file
162
source/blender/editors/io/io_cache.c
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2016 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
|
#include "DNA_space_types.h"
|
||||||
|
|
||||||
|
#include "BLI_listbase.h"
|
||||||
|
#include "BLI_path_util.h"
|
||||||
|
#include "BLI_string.h"
|
||||||
|
|
||||||
|
#include "BKE_cachefile.h"
|
||||||
|
#include "BKE_context.h"
|
||||||
|
#include "BKE_global.h"
|
||||||
|
#include "BKE_library.h"
|
||||||
|
#include "BKE_main.h"
|
||||||
|
#include "BKE_report.h"
|
||||||
|
|
||||||
|
#include "RNA_access.h"
|
||||||
|
|
||||||
|
#include "UI_interface.h"
|
||||||
|
|
||||||
|
#include "WM_api.h"
|
||||||
|
#include "WM_types.h"
|
||||||
|
|
||||||
|
#include "io_cache.h"
|
||||||
|
|
||||||
|
static void cachefile_init(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
PropertyPointerRNA *pprop;
|
||||||
|
|
||||||
|
op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
|
||||||
|
UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cachefile_open_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
|
{
|
||||||
|
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
|
||||||
|
char filepath[FILE_MAX];
|
||||||
|
BLI_strncpy(filepath, G.main->name, sizeof(filepath));
|
||||||
|
BLI_replace_extension(filepath, sizeof(filepath), ".abc");
|
||||||
|
RNA_string_set(op->ptr, "filepath", filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
cachefile_init(C, op);
|
||||||
|
|
||||||
|
WM_event_add_fileselect(C, op);
|
||||||
|
|
||||||
|
return OPERATOR_RUNNING_MODAL;
|
||||||
|
|
||||||
|
UNUSED_VARS(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void open_cancel(bContext *UNUSED(C), wmOperator *op)
|
||||||
|
{
|
||||||
|
MEM_freeN(op->customdata);
|
||||||
|
op->customdata = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cachefile_open_exec(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
|
||||||
|
BKE_report(op->reports, RPT_ERROR, "No filename given");
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
char filename[FILE_MAX];
|
||||||
|
RNA_string_get(op->ptr, "filepath", filename);
|
||||||
|
|
||||||
|
Main *bmain = CTX_data_main(C);
|
||||||
|
|
||||||
|
CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, BLI_path_basename(filename));
|
||||||
|
BLI_strncpy(cache_file->filepath, filename, FILE_MAX);
|
||||||
|
BKE_cachefile_reload(bmain, cache_file);
|
||||||
|
|
||||||
|
/* hook into UI */
|
||||||
|
PropertyPointerRNA *pprop = op->customdata;
|
||||||
|
|
||||||
|
if (pprop->prop) {
|
||||||
|
/* when creating new ID blocks, use is already 1, but RNA
|
||||||
|
* pointer se also increases user, so this compensates it */
|
||||||
|
id_us_min(&cache_file->id);
|
||||||
|
|
||||||
|
PointerRNA idptr;
|
||||||
|
RNA_id_pointer_create(&cache_file->id, &idptr);
|
||||||
|
RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
|
||||||
|
RNA_property_update(C, &pprop->ptr, pprop->prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_freeN(op->customdata);
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CACHEFILE_OT_open(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
ot->name = "Open Cache File";
|
||||||
|
ot->idname = "CACHEFILE_OT_open";
|
||||||
|
|
||||||
|
ot->invoke = cachefile_open_invoke;
|
||||||
|
ot->exec = cachefile_open_exec;
|
||||||
|
ot->cancel = open_cancel;
|
||||||
|
|
||||||
|
WM_operator_properties_filesel(ot, FILE_TYPE_ALEMBIC | FILE_TYPE_FOLDER,
|
||||||
|
FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH,
|
||||||
|
FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ***************************** Reload Operator **************************** */
|
||||||
|
|
||||||
|
static int cachefile_reload_exec(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
CacheFile *cache_file = CTX_data_edit_cachefile(C);
|
||||||
|
|
||||||
|
if (!cache_file) {
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Main *bmain = CTX_data_main(C);
|
||||||
|
|
||||||
|
BLI_listbase_clear(&cache_file->object_paths);
|
||||||
|
BKE_cachefile_reload(bmain, cache_file);
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
|
||||||
|
UNUSED_VARS(op);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CACHEFILE_OT_reload(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
ot->name = "Refresh Archive";
|
||||||
|
ot->description = "Update objects paths list with new data from the archive";
|
||||||
|
ot->idname = "CACHEFILE_OT_reload";
|
||||||
|
|
||||||
|
/* api callbacks */
|
||||||
|
ot->exec = cachefile_reload_exec;
|
||||||
|
|
||||||
|
/* flags */
|
||||||
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||||
|
}
|
37
source/blender/editors/io/io_cache.h
Normal file
37
source/blender/editors/io/io_cache.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2016 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __IO_CACHE_H__
|
||||||
|
#define __IO_CACHE_H__
|
||||||
|
|
||||||
|
/** \file blender/editors/io/io_cache.h
|
||||||
|
* \ingroup editor/io
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct wmOperatorType;
|
||||||
|
|
||||||
|
void CACHEFILE_OT_open(struct wmOperatorType *ot);
|
||||||
|
void CACHEFILE_OT_reload(struct wmOperatorType *ot);
|
||||||
|
|
||||||
|
#endif /* __IO_CACHE_H__ */
|
@ -30,11 +30,18 @@
|
|||||||
|
|
||||||
#include "io_ops.h" /* own include */
|
#include "io_ops.h" /* own include */
|
||||||
|
|
||||||
|
#include "WM_api.h"
|
||||||
|
|
||||||
#ifdef WITH_COLLADA
|
#ifdef WITH_COLLADA
|
||||||
# include "io_collada.h"
|
# include "io_collada.h"
|
||||||
# include "WM_api.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_ALEMBIC
|
||||||
|
# include "io_alembic.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "io_cache.h"
|
||||||
|
|
||||||
void ED_operatortypes_io(void)
|
void ED_operatortypes_io(void)
|
||||||
{
|
{
|
||||||
#ifdef WITH_COLLADA
|
#ifdef WITH_COLLADA
|
||||||
@ -42,4 +49,11 @@ void ED_operatortypes_io(void)
|
|||||||
WM_operatortype_append(WM_OT_collada_export);
|
WM_operatortype_append(WM_OT_collada_export);
|
||||||
WM_operatortype_append(WM_OT_collada_import);
|
WM_operatortype_append(WM_OT_collada_import);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef WITH_ALEMBIC
|
||||||
|
WM_operatortype_append(WM_OT_alembic_import);
|
||||||
|
WM_operatortype_append(WM_OT_alembic_export);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WM_operatortype_append(CACHEFILE_OT_open);
|
||||||
|
WM_operatortype_append(CACHEFILE_OT_reload);
|
||||||
}
|
}
|
||||||
|
@ -416,6 +416,13 @@ static void test_constraint(Object *owner, bPoseChannel *pchan, bConstraint *con
|
|||||||
if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL))
|
if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL))
|
||||||
con->flag |= CONSTRAINT_DISABLE;
|
con->flag |= CONSTRAINT_DISABLE;
|
||||||
}
|
}
|
||||||
|
else if (con->type == CONSTRAINT_TYPE_TRANSFORM_CACHE) {
|
||||||
|
bTransformCacheConstraint *data = con->data;
|
||||||
|
|
||||||
|
if ((data->cache_file == NULL) || (data->object_path[0] == '\0')) {
|
||||||
|
con->flag |= CONSTRAINT_DISABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Check targets for constraints */
|
/* Check targets for constraints */
|
||||||
if (check_targets && cti && cti->get_constraint_targets) {
|
if (check_targets && cti && cti->get_constraint_targets) {
|
||||||
|
@ -920,6 +920,8 @@ static int filelist_geticon_ex(
|
|||||||
return ICON_FILE_BLANK;
|
return ICON_FILE_BLANK;
|
||||||
else if (typeflag & FILE_TYPE_COLLADA)
|
else if (typeflag & FILE_TYPE_COLLADA)
|
||||||
return ICON_FILE_BLANK;
|
return ICON_FILE_BLANK;
|
||||||
|
else if (typeflag & FILE_TYPE_ALEMBIC)
|
||||||
|
return ICON_FILE_BLANK;
|
||||||
else if (typeflag & FILE_TYPE_TEXT)
|
else if (typeflag & FILE_TYPE_TEXT)
|
||||||
return ICON_FILE_TEXT;
|
return ICON_FILE_TEXT;
|
||||||
else if (typeflag & FILE_TYPE_BLENDERLIB) {
|
else if (typeflag & FILE_TYPE_BLENDERLIB) {
|
||||||
@ -1952,6 +1954,9 @@ int ED_path_extension_type(const char *path)
|
|||||||
else if (BLI_testextensie(path, ".dae")) {
|
else if (BLI_testextensie(path, ".dae")) {
|
||||||
return FILE_TYPE_COLLADA;
|
return FILE_TYPE_COLLADA;
|
||||||
}
|
}
|
||||||
|
else if (BLI_testextensie(path, ".abc")) {
|
||||||
|
return FILE_TYPE_ALEMBIC;
|
||||||
|
}
|
||||||
else if (BLI_testextensie_array(path, imb_ext_image) ||
|
else if (BLI_testextensie_array(path, imb_ext_image) ||
|
||||||
(G.have_quicktime && BLI_testextensie_array(path, imb_ext_image_qt)))
|
(G.have_quicktime && BLI_testextensie_array(path, imb_ext_image_qt)))
|
||||||
{
|
{
|
||||||
@ -2004,6 +2009,8 @@ int ED_file_extension_icon(const char *path)
|
|||||||
return ICON_FILE_BLANK;
|
return ICON_FILE_BLANK;
|
||||||
case FILE_TYPE_COLLADA:
|
case FILE_TYPE_COLLADA:
|
||||||
return ICON_FILE_BLANK;
|
return ICON_FILE_BLANK;
|
||||||
|
case FILE_TYPE_ALEMBIC:
|
||||||
|
return ICON_FILE_BLANK;
|
||||||
case FILE_TYPE_TEXT:
|
case FILE_TYPE_TEXT:
|
||||||
return ICON_FILE_TEXT;
|
return ICON_FILE_TEXT;
|
||||||
default:
|
default:
|
||||||
|
@ -185,6 +185,8 @@ short ED_fileselect_set_params(SpaceFile *sfile)
|
|||||||
params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BTX : 0;
|
params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BTX : 0;
|
||||||
if ((prop = RNA_struct_find_property(op->ptr, "filter_collada")))
|
if ((prop = RNA_struct_find_property(op->ptr, "filter_collada")))
|
||||||
params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_COLLADA : 0;
|
params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_COLLADA : 0;
|
||||||
|
if ((prop = RNA_struct_find_property(op->ptr, "filter_alembic")))
|
||||||
|
params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_ALEMBIC : 0;
|
||||||
if ((prop = RNA_struct_find_property(op->ptr, "filter_glob"))) {
|
if ((prop = RNA_struct_find_property(op->ptr, "filter_glob"))) {
|
||||||
/* Protection against pyscripts not setting proper size limit... */
|
/* Protection against pyscripts not setting proper size limit... */
|
||||||
char *tmp = RNA_property_string_get_alloc(
|
char *tmp = RNA_property_string_get_alloc(
|
||||||
@ -213,7 +215,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
|
|||||||
FILTER_ID_GR | FILTER_ID_IM | FILTER_ID_LA | FILTER_ID_LS | FILTER_ID_LT | FILTER_ID_MA |
|
FILTER_ID_GR | FILTER_ID_IM | FILTER_ID_LA | FILTER_ID_LS | FILTER_ID_LT | FILTER_ID_MA |
|
||||||
FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME | FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB |
|
FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME | FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB |
|
||||||
FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_SCE | FILTER_ID_SPK | FILTER_ID_SO |
|
FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_SCE | FILTER_ID_SPK | FILTER_ID_SO |
|
||||||
FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO;
|
FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | FILTER_ID_CF;
|
||||||
|
|
||||||
if (U.uiflag & USER_HIDE_DOT) {
|
if (U.uiflag & USER_HIDE_DOT) {
|
||||||
params->flag |= FILE_HIDE_DOT;
|
params->flag |= FILE_HIDE_DOT;
|
||||||
|
@ -131,6 +131,7 @@ bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_p
|
|||||||
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
||||||
case ANIMTYPE_DSLAM:
|
case ANIMTYPE_DSLAM:
|
||||||
case ANIMTYPE_DSCAM:
|
case ANIMTYPE_DSCAM:
|
||||||
|
case ANIMTYPE_DSCACHEFILE:
|
||||||
case ANIMTYPE_DSCUR:
|
case ANIMTYPE_DSCUR:
|
||||||
case ANIMTYPE_DSSKEY:
|
case ANIMTYPE_DSSKEY:
|
||||||
case ANIMTYPE_DSWOR:
|
case ANIMTYPE_DSWOR:
|
||||||
|
@ -170,6 +170,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
|
|||||||
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
||||||
case ANIMTYPE_DSLAM:
|
case ANIMTYPE_DSLAM:
|
||||||
case ANIMTYPE_DSCAM:
|
case ANIMTYPE_DSCAM:
|
||||||
|
case ANIMTYPE_DSCACHEFILE:
|
||||||
case ANIMTYPE_DSCUR:
|
case ANIMTYPE_DSCUR:
|
||||||
case ANIMTYPE_DSSKEY:
|
case ANIMTYPE_DSSKEY:
|
||||||
case ANIMTYPE_DSWOR:
|
case ANIMTYPE_DSWOR:
|
||||||
|
@ -1173,6 +1173,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
|
|||||||
UI_icon_draw(x, y, ICON_MOD_TRIANGULATE); break;
|
UI_icon_draw(x, y, ICON_MOD_TRIANGULATE); break;
|
||||||
case eModifierType_MeshCache:
|
case eModifierType_MeshCache:
|
||||||
UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */
|
UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */
|
||||||
|
case eModifierType_MeshSequenceCache:
|
||||||
|
UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */
|
||||||
case eModifierType_Wireframe:
|
case eModifierType_Wireframe:
|
||||||
UI_icon_draw(x, y, ICON_MOD_WIREFRAME); break;
|
UI_icon_draw(x, y, ICON_MOD_WIREFRAME); break;
|
||||||
case eModifierType_LaplacianDeform:
|
case eModifierType_LaplacianDeform:
|
||||||
|
@ -62,7 +62,7 @@ typedef struct TreeElement {
|
|||||||
#define TREESTORE_ID_TYPE(_id) \
|
#define TREESTORE_ID_TYPE(_id) \
|
||||||
(ELEM(GS((_id)->name), ID_SCE, ID_LI, ID_OB, ID_ME, ID_CU, ID_MB, ID_NT, ID_MA, ID_TE, ID_IM, ID_LT, ID_LA, ID_CA) || \
|
(ELEM(GS((_id)->name), ID_SCE, ID_LI, ID_OB, ID_ME, ID_CU, ID_MB, ID_NT, ID_MA, ID_TE, ID_IM, ID_LT, ID_LA, ID_CA) || \
|
||||||
ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_PA, ID_GD, ID_LS) || \
|
ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_PA, ID_GD, ID_LS) || \
|
||||||
ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT, ID_VF, ID_SO)) /* Only in 'blendfile' mode ... :/ */
|
ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT, ID_VF, ID_SO, ID_CF)) /* Only in 'blendfile' mode ... :/ */
|
||||||
|
|
||||||
/* TreeElement->flag */
|
/* TreeElement->flag */
|
||||||
#define TE_ACTIVE 1
|
#define TE_ACTIVE 1
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include "DNA_armature_types.h"
|
#include "DNA_armature_types.h"
|
||||||
#include "DNA_constraint_types.h"
|
#include "DNA_constraint_types.h"
|
||||||
#include "DNA_camera_types.h"
|
#include "DNA_camera_types.h"
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
#include "DNA_gpencil_types.h"
|
#include "DNA_gpencil_types.h"
|
||||||
#include "DNA_group_types.h"
|
#include "DNA_group_types.h"
|
||||||
#include "DNA_key_types.h"
|
#include "DNA_key_types.h"
|
||||||
@ -746,6 +747,16 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
|
|||||||
outliner_add_element(soops, &te->subtree, ca, te, TSE_ANIM_DATA, 0);
|
outliner_add_element(soops, &te->subtree, ca, te, TSE_ANIM_DATA, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ID_CF:
|
||||||
|
{
|
||||||
|
CacheFile *cache_file = (CacheFile *)id;
|
||||||
|
|
||||||
|
if (outliner_animdata_test(cache_file->adt)) {
|
||||||
|
outliner_add_element(soops, &te->subtree, cache_file, te, TSE_ANIM_DATA, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ID_LA:
|
case ID_LA:
|
||||||
{
|
{
|
||||||
Lamp *la = (Lamp *)id;
|
Lamp *la = (Lamp *)id;
|
||||||
|
@ -32,7 +32,10 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
|
#include "DNA_constraint_types.h"
|
||||||
#include "DNA_gpencil_types.h"
|
#include "DNA_gpencil_types.h"
|
||||||
|
#include "DNA_modifier_types.h"
|
||||||
#include "DNA_object_types.h"
|
#include "DNA_object_types.h"
|
||||||
#include "DNA_scene_types.h"
|
#include "DNA_scene_types.h"
|
||||||
|
|
||||||
@ -42,7 +45,10 @@
|
|||||||
#include "BLI_dlrbTree.h"
|
#include "BLI_dlrbTree.h"
|
||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
|
|
||||||
|
#include "BKE_constraint.h"
|
||||||
#include "BKE_context.h"
|
#include "BKE_context.h"
|
||||||
|
#include "BKE_main.h"
|
||||||
|
#include "BKE_modifier.h"
|
||||||
#include "BKE_screen.h"
|
#include "BKE_screen.h"
|
||||||
#include "BKE_pointcache.h"
|
#include "BKE_pointcache.h"
|
||||||
|
|
||||||
@ -320,6 +326,9 @@ static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel)
|
|||||||
case ID_GD:
|
case ID_GD:
|
||||||
gpencil_to_keylist(&ads, (bGPdata *)id, &keys);
|
gpencil_to_keylist(&ads, (bGPdata *)id, &keys);
|
||||||
break;
|
break;
|
||||||
|
case ID_CF:
|
||||||
|
cachefile_to_keylist(&ads, (CacheFile *)id, &keys, NULL);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* build linked-list for searching */
|
/* build linked-list for searching */
|
||||||
@ -344,6 +353,56 @@ static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel)
|
|||||||
BLI_dlrbTree_free(&keys);
|
BLI_dlrbTree_free(&keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, bool onlysel)
|
||||||
|
{
|
||||||
|
CacheFile *cache_file;
|
||||||
|
|
||||||
|
for (cache_file = bmain->cachefiles.first;
|
||||||
|
cache_file;
|
||||||
|
cache_file = cache_file->id.next)
|
||||||
|
{
|
||||||
|
cache_file->draw_flag &= ~CACHEFILE_KEYFRAME_DRAWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Base *base = scene->base.first; base; base = base->next) {
|
||||||
|
Object *ob = base->object;
|
||||||
|
|
||||||
|
ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache);
|
||||||
|
|
||||||
|
if (md) {
|
||||||
|
MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md;
|
||||||
|
|
||||||
|
cache_file = mcmd->cache_file;
|
||||||
|
|
||||||
|
if (!cache_file || (cache_file->draw_flag & CACHEFILE_KEYFRAME_DRAWN) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache_file->draw_flag |= CACHEFILE_KEYFRAME_DRAWN;
|
||||||
|
|
||||||
|
time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (bConstraint *con = ob->constraints.first; con; con = con->next) {
|
||||||
|
if (con->type != CONSTRAINT_TYPE_TRANSFORM_CACHE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bTransformCacheConstraint *data = con->data;
|
||||||
|
|
||||||
|
cache_file = data->cache_file;
|
||||||
|
|
||||||
|
if (!cache_file || (cache_file->draw_flag & CACHEFILE_KEYFRAME_DRAWN) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache_file->draw_flag |= CACHEFILE_KEYFRAME_DRAWN;
|
||||||
|
|
||||||
|
time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* draw keyframe lines for timeline */
|
/* draw keyframe lines for timeline */
|
||||||
static void time_draw_keyframes(const bContext *C, ARegion *ar)
|
static void time_draw_keyframes(const bContext *C, ARegion *ar)
|
||||||
{
|
{
|
||||||
@ -354,7 +413,11 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar)
|
|||||||
|
|
||||||
/* set this for all keyframe lines once and for all */
|
/* set this for all keyframe lines once and for all */
|
||||||
glLineWidth(1.0);
|
glLineWidth(1.0);
|
||||||
|
|
||||||
|
/* draw cache files keyframes (if available) */
|
||||||
|
UI_ThemeColor(TH_TIME_KEYFRAME);
|
||||||
|
time_draw_caches_keyframes(CTX_data_main(C), scene, v2d, onlysel);
|
||||||
|
|
||||||
/* draw grease pencil keyframes (if available) */
|
/* draw grease pencil keyframes (if available) */
|
||||||
UI_ThemeColor(TH_TIME_GP_KEYFRAME);
|
UI_ThemeColor(TH_TIME_GP_KEYFRAME);
|
||||||
if (scene->gpd) {
|
if (scene->gpd) {
|
||||||
|
@ -247,6 +247,7 @@ typedef enum ID_Type {
|
|||||||
ID_LS = MAKE_ID2('L', 'S'), /* FreestyleLineStyle */
|
ID_LS = MAKE_ID2('L', 'S'), /* FreestyleLineStyle */
|
||||||
ID_PAL = MAKE_ID2('P', 'L'), /* Palette */
|
ID_PAL = MAKE_ID2('P', 'L'), /* Palette */
|
||||||
ID_PC = MAKE_ID2('P', 'C'), /* PaintCurve */
|
ID_PC = MAKE_ID2('P', 'C'), /* PaintCurve */
|
||||||
|
ID_CF = MAKE_ID2('C', 'F'), /* CacheFile */
|
||||||
} ID_Type;
|
} ID_Type;
|
||||||
|
|
||||||
/* Only used as 'placeholder' in .blend files for directly linked datablocks. */
|
/* Only used as 'placeholder' in .blend files for directly linked datablocks. */
|
||||||
@ -377,6 +378,7 @@ enum {
|
|||||||
FILTER_ID_VF = (1 << 25),
|
FILTER_ID_VF = (1 << 25),
|
||||||
FILTER_ID_WO = (1 << 26),
|
FILTER_ID_WO = (1 << 26),
|
||||||
FILTER_ID_PA = (1 << 27),
|
FILTER_ID_PA = (1 << 27),
|
||||||
|
FILTER_ID_CF = (1 << 28),
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -694,7 +694,9 @@ typedef enum eAnimEdit_Context {
|
|||||||
/* dopesheet (default) */
|
/* dopesheet (default) */
|
||||||
SACTCONT_DOPESHEET = 3,
|
SACTCONT_DOPESHEET = 3,
|
||||||
/* mask */
|
/* mask */
|
||||||
SACTCONT_MASK = 4
|
SACTCONT_MASK = 4,
|
||||||
|
/* cache file */
|
||||||
|
SACTCONT_CACHEFILE = 5,
|
||||||
} eAnimEdit_Context;
|
} eAnimEdit_Context;
|
||||||
|
|
||||||
/* SpaceAction AutoSnap Settings (also used by other Animation Editors) */
|
/* SpaceAction AutoSnap Settings (also used by other Animation Editors) */
|
||||||
|
84
source/blender/makesdna/DNA_cachefile_types.h
Normal file
84
source/blender/makesdna/DNA_cachefile_types.h
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2016 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s): Kevin Dietrich.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file DNA_cachefile_types.h
|
||||||
|
* \ingroup DNA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DNA_CACHEFILE_TYPES_H__
|
||||||
|
#define __DNA_CACHEFILE_TYPES_H__
|
||||||
|
|
||||||
|
#include "DNA_ID.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* CacheFile::flag */
|
||||||
|
enum {
|
||||||
|
CACHEFILE_DS_EXPAND = (1 << 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
/* CacheFile::draw_flag */
|
||||||
|
enum {
|
||||||
|
CACHEFILE_KEYFRAME_DRAWN = (1 << 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct AlembicObjectPath {
|
||||||
|
struct AlembicObjectPath *next, *prev;
|
||||||
|
|
||||||
|
char path[1024]; /* 1024 = FILE_MAX, might use PATH_MAX in the future. */
|
||||||
|
} AlembicObjectPath;
|
||||||
|
|
||||||
|
typedef struct CacheFile {
|
||||||
|
ID id;
|
||||||
|
struct AnimData *adt;
|
||||||
|
|
||||||
|
struct AbcArchiveHandle *handle;
|
||||||
|
|
||||||
|
/* Paths of the objects inside of the Alembic archive referenced by this
|
||||||
|
* CacheFile. */
|
||||||
|
ListBase object_paths;
|
||||||
|
|
||||||
|
char filepath[1024]; /* 1024 = FILE_MAX */
|
||||||
|
|
||||||
|
char is_sequence;
|
||||||
|
char forward_axis;
|
||||||
|
char up_axis;
|
||||||
|
char override_frame;
|
||||||
|
|
||||||
|
float scale;
|
||||||
|
float frame; /* The frame/time to lookup in the cache file. */
|
||||||
|
|
||||||
|
short flag; /* Animation flag. */
|
||||||
|
short draw_flag;
|
||||||
|
} CacheFile;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __DNA_CACHEFILE_TYPES_H__ */
|
@ -458,6 +458,12 @@ typedef struct bObjectSolverConstraint {
|
|||||||
struct Object *camera;
|
struct Object *camera;
|
||||||
} bObjectSolverConstraint;
|
} bObjectSolverConstraint;
|
||||||
|
|
||||||
|
/* Transform matrix cache constraint */
|
||||||
|
typedef struct bTransformCacheConstraint {
|
||||||
|
struct CacheFile *cache_file;
|
||||||
|
char object_path[1024]; /* FILE_MAX */
|
||||||
|
} bTransformCacheConstraint;
|
||||||
|
|
||||||
/* ------------------------------------------ */
|
/* ------------------------------------------ */
|
||||||
|
|
||||||
/* bConstraint->type
|
/* bConstraint->type
|
||||||
@ -494,6 +500,7 @@ typedef enum eBConstraint_Types {
|
|||||||
CONSTRAINT_TYPE_FOLLOWTRACK = 26, /* Follow Track Constraint */
|
CONSTRAINT_TYPE_FOLLOWTRACK = 26, /* Follow Track Constraint */
|
||||||
CONSTRAINT_TYPE_CAMERASOLVER = 27, /* Camera Solver Constraint */
|
CONSTRAINT_TYPE_CAMERASOLVER = 27, /* Camera Solver Constraint */
|
||||||
CONSTRAINT_TYPE_OBJECTSOLVER = 28, /* Object Solver Constraint */
|
CONSTRAINT_TYPE_OBJECTSOLVER = 28, /* Object Solver Constraint */
|
||||||
|
CONSTRAINT_TYPE_TRANSFORM_CACHE = 29, /* Transform Cache Constraint */
|
||||||
|
|
||||||
/* NOTE: no constraints are allowed to be added after this */
|
/* NOTE: no constraints are allowed to be added after this */
|
||||||
NUM_CONSTRAINT_TYPES
|
NUM_CONSTRAINT_TYPES
|
||||||
|
@ -85,6 +85,7 @@ typedef enum ModifierType {
|
|||||||
eModifierType_DataTransfer = 49,
|
eModifierType_DataTransfer = 49,
|
||||||
eModifierType_NormalEdit = 50,
|
eModifierType_NormalEdit = 50,
|
||||||
eModifierType_CorrectiveSmooth = 51,
|
eModifierType_CorrectiveSmooth = 51,
|
||||||
|
eModifierType_MeshSequenceCache = 52,
|
||||||
NUM_MODIFIER_TYPES
|
NUM_MODIFIER_TYPES
|
||||||
} ModifierType;
|
} ModifierType;
|
||||||
|
|
||||||
@ -1541,4 +1542,25 @@ enum {
|
|||||||
MOD_NORMALEDIT_MIX_MUL = 3,
|
MOD_NORMALEDIT_MIX_MUL = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct MeshSeqCacheModifierData {
|
||||||
|
ModifierData modifier;
|
||||||
|
|
||||||
|
struct CacheFile *cache_file;
|
||||||
|
char object_path[1024]; /* 1024 = FILE_MAX */
|
||||||
|
|
||||||
|
char read_flag;
|
||||||
|
char pad[7];
|
||||||
|
} MeshSeqCacheModifierData;
|
||||||
|
|
||||||
|
/* MeshSeqCacheModifierData.read_flag */
|
||||||
|
enum {
|
||||||
|
MOD_MESHSEQ_READ_VERT = (1 << 0),
|
||||||
|
MOD_MESHSEQ_READ_POLY = (1 << 1),
|
||||||
|
MOD_MESHSEQ_READ_UV = (1 << 2),
|
||||||
|
MOD_MESHSEQ_READ_COLOR = (1 << 3),
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MOD_MESHSEQ_READ_ALL \
|
||||||
|
(MOD_MESHSEQ_READ_VERT | MOD_MESHSEQ_READ_POLY | MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)
|
||||||
|
|
||||||
#endif /* __DNA_MODIFIER_TYPES_H__ */
|
#endif /* __DNA_MODIFIER_TYPES_H__ */
|
||||||
|
@ -738,6 +738,7 @@ typedef enum eFileSel_File_Types {
|
|||||||
FILE_TYPE_COLLADA = (1 << 13),
|
FILE_TYPE_COLLADA = (1 << 13),
|
||||||
FILE_TYPE_OPERATOR = (1 << 14), /* from filter_glob operator property */
|
FILE_TYPE_OPERATOR = (1 << 14), /* from filter_glob operator property */
|
||||||
FILE_TYPE_APPLICATIONBUNDLE = (1 << 15),
|
FILE_TYPE_APPLICATIONBUNDLE = (1 << 15),
|
||||||
|
FILE_TYPE_ALEMBIC = (1 << 16),
|
||||||
|
|
||||||
FILE_TYPE_DIR = (1 << 30), /* An FS directory (i.e. S_ISDIR on its path is true). */
|
FILE_TYPE_DIR = (1 << 30), /* An FS directory (i.e. S_ISDIR on its path is true). */
|
||||||
FILE_TYPE_BLENDERLIB = (1 << 31),
|
FILE_TYPE_BLENDERLIB = (1 << 31),
|
||||||
|
@ -129,6 +129,7 @@ static const char *includefiles[] = {
|
|||||||
"DNA_rigidbody_types.h",
|
"DNA_rigidbody_types.h",
|
||||||
"DNA_freestyle_types.h",
|
"DNA_freestyle_types.h",
|
||||||
"DNA_linestyle_types.h",
|
"DNA_linestyle_types.h",
|
||||||
|
"DNA_cachefile_types.h",
|
||||||
/* see comment above before editing! */
|
/* see comment above before editing! */
|
||||||
|
|
||||||
/* empty string to indicate end of includefiles */
|
/* empty string to indicate end of includefiles */
|
||||||
@ -1340,4 +1341,5 @@ int main(int argc, char **argv)
|
|||||||
#include "DNA_rigidbody_types.h"
|
#include "DNA_rigidbody_types.h"
|
||||||
#include "DNA_freestyle_types.h"
|
#include "DNA_freestyle_types.h"
|
||||||
#include "DNA_linestyle_types.h"
|
#include "DNA_linestyle_types.h"
|
||||||
|
#include "DNA_cachefile_types.h"
|
||||||
/* end of list */
|
/* end of list */
|
||||||
|
@ -95,6 +95,8 @@ extern StructRNA RNA_Brush;
|
|||||||
extern StructRNA RNA_BrushTextureSlot;
|
extern StructRNA RNA_BrushTextureSlot;
|
||||||
extern StructRNA RNA_BuildModifier;
|
extern StructRNA RNA_BuildModifier;
|
||||||
extern StructRNA RNA_MeshCacheModifier;
|
extern StructRNA RNA_MeshCacheModifier;
|
||||||
|
extern StructRNA RNA_MeshSequenceCacheModifier;
|
||||||
|
extern StructRNA RNA_CacheFile;
|
||||||
extern StructRNA RNA_Camera;
|
extern StructRNA RNA_Camera;
|
||||||
extern StructRNA RNA_CastModifier;
|
extern StructRNA RNA_CastModifier;
|
||||||
extern StructRNA RNA_ChildOfConstraint;
|
extern StructRNA RNA_ChildOfConstraint;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user