Compare commits
321 Commits
temp-geome
...
alembic_po
Author | SHA1 | Date | |
---|---|---|---|
9ad96b2689 | |||
0919a3d56d | |||
8c142af0b0 | |||
4b451838ed | |||
c27ef5692c | |||
045350c3b1 | |||
1d2aa62366 | |||
4ce017b4c8 | |||
6db876bef6 | |||
3e44712895 | |||
b01037b81d | |||
e84b0d456f | |||
5950b48328 | |||
229befd147 | |||
f77d75ed65 | |||
481ef9704d | |||
9ceb29d3cb | |||
65c1e00fb5 | |||
0a7a4d504b | |||
08017eef62 | |||
f3eb33c476 | |||
20a678f240 | |||
29b46e4ef2 | |||
bdae7f4aaa | |||
40d3784dc3 | |||
babaf408c4 | |||
21fa96a72b | |||
97410d71b3 | |||
5d04ddea64 | |||
279dfe6a18 | |||
b5fb274f43 | |||
878d09e65b | |||
238f3ac972 | |||
a0a3c29ae4 | |||
cf2c1a9062 | |||
2392ee9505 | |||
7c7d5645ca | |||
3079019ec1 | |||
8a021a7d1f | |||
59ed1d0a67 | |||
56acbcaa0e | |||
16258ddd03 | |||
aad1c616ca | |||
bafa8da0ca | |||
6f7b613715 | |||
67b7263d37 | |||
9772bae88e | |||
92598a6e22 | |||
e3a0736716 | |||
be4c8e6645 | |||
7677f393b4 | |||
b6b1eb5cbf | |||
ae87d1f50d | |||
06ebb145ae | |||
ed75af586e | |||
dfdb657427 | |||
3910ff3a50 | |||
b26ca84a82 | |||
2f1429a648 | |||
d71489b095 | |||
7945354567 | |||
d75dcf88d2 | |||
36be233e27 | |||
91c263f492 | |||
2b02c0b650 | |||
26b788e9bd | |||
a45805ed2f | |||
a7706b3642 | |||
e46dd19911 | |||
511d8a98c5 | |||
0a71eea5f1 | |||
a48d2e605c | |||
91f6635e09 | |||
b1bb3f8c82 | |||
3e16951ec6 | |||
3bd45d384b | |||
1a9706ceae | |||
5f62c931d1 | |||
16d259c842 | |||
4f5f03115b | |||
38342e444a | |||
6d67e67022 | |||
5bd80e9d2c | |||
752e396fcc | |||
4e0b7d2f18 | |||
fe840e6365 | |||
8cc679b8d6 | |||
a4f853ed6e | |||
f555bb8c61 | |||
ea601a4814 | |||
367278e1b5 | |||
ca4735a485 | |||
8cc176c14d | |||
9edeff8a04 | |||
47afa53913 | |||
5a86b97991 | |||
5dc9f664d0 | |||
a7e2ab42df | |||
bb2e8ee262 | |||
dd1cbab715 | |||
5c15fc8021 | |||
0798382397 | |||
4e0c2b4e4e | |||
806a276f30 | |||
a597d07011 | |||
56d2ad98b4 | |||
24c6137d46 | |||
33060f829a | |||
1a9c74a3a8 | |||
800299008a | |||
b3f4814a56 | |||
489a7cb7b7 | |||
814624ced9 | |||
26119375cc | |||
a83a61b03b | |||
901eae21d0 | |||
91aaf8df00 | |||
a26eecf2a1 | |||
7c991a601a | |||
4e5ee121af | |||
08b3ba5ecf | |||
9e2e24a1d0 | |||
97a4905d37 | |||
15d3314611 | |||
cce6123911 | |||
7f442aa4b1 | |||
5fa7283f86 | |||
8a2e1b5c16 | |||
a7178954bf | |||
4b7500353a | |||
58375c6f38 | |||
29c0a6b435 | |||
48c1a8a1d1 | |||
928aab7b4e | |||
4d8c66ddc1 | |||
1c20be94bc | |||
240768ec7c | |||
05e93c0b7f | |||
424bc7f3eb | |||
034b281f96 | |||
7a89dd778b | |||
205879263a | |||
0de4284c33 | |||
79b7817af3 | |||
b2a8b366eb | |||
43a89c3e93 | |||
b29d9de7ad | |||
517c95e723 | |||
2dc88a3715 | |||
5f4bde826b | |||
fca2eddf22 | |||
a2006f37b2 | |||
59727c736a | |||
d0a9f20257 | |||
386415509e | |||
4f2ab75bd4 | |||
212210b7ee | |||
d88cd0765c | |||
4716a87636 | |||
7a462c3e35 | |||
06338dbefd | |||
861e553f1d | |||
a7f5d1d662 | |||
7b16850073 | |||
0e2ae9007b | |||
ba2a3efddb | |||
1be812f426 | |||
90ce1a3e8f | |||
a7747a3e0c | |||
940c17af81 | |||
39a39a1474 | |||
b66c1f538e | |||
fe04d8b176 | |||
31d41d9b20 | |||
c3459108a3 | |||
b8b9788158 | |||
eae8bb4c8d | |||
7d89274d14 | |||
dc882a008c | |||
2366663ebb | |||
617ce27ffc | |||
3fb8d5a99a | |||
deeb09a5cb | |||
1309ca51fa | |||
12d4db406d | |||
f464829daf | |||
ca94528d71 | |||
8072c476b4 | |||
f4f7ab735b | |||
cee1ea5533 | |||
e7bdd29192 | |||
7d6779f88e | |||
567b10dc16 | |||
304e5a440a | |||
40a8ef5ef0 | |||
4edbd9586f | |||
5d9db8192d | |||
d3ef995912 | |||
743ee837b0 | |||
036d4fc3e0 | |||
a4644c3605 | |||
e89fd502d7 | |||
6cd3ebfc9f | |||
97a50e78ca | |||
8f4d98283d | |||
a920b652f9 | |||
e2e0a529d9 | |||
943691814c | |||
534760173b | |||
cdfe06bf51 | |||
74afc56120 | |||
6fac43eb87 | |||
f9b3d1c900 | |||
f306805ba2 | |||
721806fa76 | |||
8d2b7e552f | |||
501aae3aef | |||
66689345f0 | |||
8c6ca4499e | |||
9df9ee568a | |||
4b2fbebc27 | |||
e6f9f593f6 | |||
5a48a83663 | |||
c334b2862d | |||
c1343ab498 | |||
8e97a13d3d | |||
dd1f70ffb5 | |||
45e4ef57dc | |||
21577a64f6 | |||
e45e593c35 | |||
6ac889f2b3 | |||
c118d3d739 | |||
aa8e249136 | |||
a281b69bd2 | |||
a5b549bc63 | |||
f3b9f0c619 | |||
f065d25653 | |||
0da2707387 | |||
c5dc9b60ca | |||
9ba99ebd95 | |||
f237f67a99 | |||
ba90765050 | |||
df5cfbdc47 | |||
cb82ec10bd | |||
775a1287f5 | |||
2f5ef128b9 | |||
44057bdffb | |||
de604e1b6e | |||
8aa35aa014 | |||
6789e32e1d | |||
bea5cec25e | |||
b69a448531 | |||
47e2f7cf99 | |||
13f3b8ebdb | |||
a12f3d1e86 | |||
6ac4add2cc | |||
642b27fed1 | |||
af02fe2d2f | |||
001930bda0 | |||
2a66bf8acb | |||
c5d3303faf | |||
17bbbf1843 | |||
74aec79e0a | |||
117f4c7d0e | |||
dfc42af50b | |||
4acd9ac0a4 | |||
9c247486aa | |||
acb4e9fe2f | |||
3497e27bb2 | |||
67655f2a7f | |||
f4cf45dd0b | |||
9061ac3d99 | |||
a148ec6191 | |||
9e10e191c8 | |||
011b6e5b18 | |||
8cc7969925 | |||
5852d77fe7 | |||
75c6a496e9 | |||
aae656f9a3 | |||
72c6fe9b8c | |||
b2d6e736ea | |||
b633ea4854 | |||
ff0296184c | |||
a91f8543c7 | |||
9c05df76ad | |||
761248fa05 | |||
7c732da27b | |||
523ff63a82 | |||
290fe64048 | |||
42c0fdc276 | |||
039a1e76ee | |||
fe303b7294 | |||
527e8ce74d | |||
3d01d027a0 | |||
2f1554c176 | |||
98b67f1d97 | |||
db237d837a | |||
a33c9d2a24 | |||
1ffe06d066 | |||
704ec0da44 | |||
1d7bd0c5b2 | |||
4774c1f076 | |||
156a5f15b2 | |||
c1411359a9 | |||
7859dde7fe | |||
7b0b538a78 | |||
684ad4f91e | |||
34f8a87ca5 | |||
f956ff1fab | |||
453eccc1c8 | |||
66bfa1e35c | |||
e60715b9f1 | |||
201f43e2ff | |||
715a9b9ee3 | |||
5f6d8f2bc0 | |||
e223de3f37 | |||
5a014df0fc | |||
f038524278 | |||
d95d8b0928 | |||
1fe78b1378 | |||
fe781f7e4d |
@@ -275,6 +275,10 @@ option(WITH_MOD_REMESH "Enable Remesh Modifier" ON)
|
||||
# mark_as_advanced(WITH_MOD_CLOTH_ELTOPO)
|
||||
option(WITH_MOD_OCEANSIM "Enable Ocean Modifier" OFF)
|
||||
|
||||
# Alembic
|
||||
option(WITH_ALEMBIC "Enable Alembic Support" OFF)
|
||||
option(WITH_HDF5 "Enable HDF5 Support for Alembic" OFF)
|
||||
|
||||
# Image format support
|
||||
option(WITH_OPENIMAGEIO "Enable OpenImageIO Support (http://www.openimageio.org)" ON)
|
||||
option(WITH_IMAGE_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" ${_init_IMAGE_OPENEXR})
|
||||
@@ -637,17 +641,23 @@ if(NOT WITH_BOOST)
|
||||
|
||||
set_and_warn(WITH_CYCLES OFF)
|
||||
set_and_warn(WITH_AUDASPACE OFF)
|
||||
set_and_warn(WITH_ALEMBIC OFF)
|
||||
set_and_warn(WITH_INTERNATIONAL OFF)
|
||||
|
||||
set_and_warn(WITH_OPENAL OFF) # depends on AUDASPACE
|
||||
set_and_warn(WITH_GAMEENGINE OFF) # depends on AUDASPACE
|
||||
elseif(WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_AUDASPACE OR WITH_INTERNATIONAL)
|
||||
elseif(WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_AUDASPACE OR WITH_ALEMBIC OR WITH_INTERNATIONAL)
|
||||
# Keep enabled
|
||||
else()
|
||||
# Enabled but we don't need it
|
||||
set(WITH_BOOST OFF)
|
||||
endif()
|
||||
|
||||
# disable hdf5 if Alembic is disabled
|
||||
if(NOT WITH_ALEMBIC)
|
||||
set(WITH_HDF5 OFF)
|
||||
endif()
|
||||
|
||||
# auto enable openimageio for cycles
|
||||
if(WITH_CYCLES)
|
||||
set(WITH_OPENIMAGEIO ON)
|
||||
@@ -1129,6 +1139,15 @@ if(UNIX AND NOT APPLE)
|
||||
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -Wl,--version-script=${CMAKE_SOURCE_DIR}/source/creator/blender.map")
|
||||
endif()
|
||||
|
||||
if(WITH_ALEMBIC)
|
||||
find_package_wrapper(Alembic)
|
||||
set(ALEMBIC_LIBRARIES ${ALEMBIC_LIBRARIES} ${BOOST_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(WITH_HDF5)
|
||||
find_package_wrapper(HDF5)
|
||||
endif()
|
||||
|
||||
# OpenSuse needs lutil, ArchLinux not, for now keep, can avoid by using --as-needed
|
||||
list(APPEND PLATFORM_LINKLIBS -lutil -lc -lm)
|
||||
|
||||
@@ -2196,6 +2215,12 @@ if(WITH_CYCLES)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_ALEMBIC)
|
||||
if(NOT WITH_BOOST)
|
||||
message(FATAL_ERROR "Alembic requires WITH_BOOST, the library may not have been found. Configure BOOST or disable WITH_ALEMBIC")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_INTERNATIONAL)
|
||||
if(NOT WITH_BOOST)
|
||||
message(FATAL_ERROR "Internationalization requires WITH_BOOST, the library may not have been found. Configure BOOST or disable WITH_INTERNATIONAL")
|
||||
|
@@ -95,6 +95,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
|
||||
--with-opencollada
|
||||
Build and install the OpenCOLLADA libraries.
|
||||
|
||||
--with-alembic
|
||||
Build and install the Alembic library.
|
||||
|
||||
--ver-ocio=<ver>
|
||||
Force version of OCIO library.
|
||||
|
||||
@@ -144,6 +147,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
|
||||
--force-ffmpeg
|
||||
Force the rebuild of FFMpeg.
|
||||
|
||||
--force-alembic
|
||||
Force the rebuild of Alembic.
|
||||
|
||||
Note about the --force-foo options:
|
||||
* They obviously only have an effect if those libraries are built by this script
|
||||
(i.e. if there is no available and satisfactory package)!
|
||||
@@ -180,6 +186,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
|
||||
--skip-ffmpeg
|
||||
Unconditionally skip FFMpeg installation/building.
|
||||
|
||||
--skip-alembic
|
||||
Unconditionally skip Alembic installation/building.
|
||||
|
||||
--required-numpy
|
||||
Use this in case your distro features a valid python package, but no matching Numpy one.
|
||||
It will force compilation of both python and numpy\""
|
||||
@@ -264,6 +273,11 @@ MP3LAME_DEV=""
|
||||
OPENJPEG_USE=false
|
||||
OPENJPEG_DEV=""
|
||||
|
||||
ALEMBIC_VERSION="1.5.5"
|
||||
ALEMBIC_VERSION_MIN="1.5.5"
|
||||
ALEMBIC_FORCE_REBUILD=false
|
||||
ALEMBIC_SKIP=false
|
||||
|
||||
# Switch to english language, else some things (like check_package_DEB()) won't work!
|
||||
LANG_BACK=$LANG
|
||||
LANG=""
|
||||
@@ -423,6 +437,9 @@ while true; do
|
||||
--force-ffmpeg)
|
||||
FFMPEG_FORCE_REBUILD=true; shift; continue
|
||||
;;
|
||||
--force-alembic)
|
||||
ALEMBIC_FORCE_REBUILD=true; shift; continue
|
||||
;;
|
||||
--skip-python)
|
||||
PYTHON_SKIP=true; shift; continue
|
||||
;;
|
||||
@@ -453,6 +470,9 @@ while true; do
|
||||
--skip-ffmpeg)
|
||||
FFMPEG_SKIP=true; shift; continue
|
||||
;;
|
||||
--skip-alembic)
|
||||
ALEMBIC_SKIP=true; shift; continue
|
||||
;;
|
||||
--required-numpy)
|
||||
NUMPY_REQUIRED=true; shift; continue
|
||||
;;
|
||||
@@ -513,6 +533,9 @@ OPENCOLLADA_SOURCE=( "https://github.com/KhronosGroup/OpenCOLLADA.git" )
|
||||
OPENCOLLADA_REPO_UID="18da7f4109a8eafaa290a33f5550501cc4c8bae8"
|
||||
FFMPEG_SOURCE=( "http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2" )
|
||||
|
||||
ALEMBIC_SOURCE=( "https://code.google.com/p/alembic/" )
|
||||
ALEMBIC_REPO_UID=( "1_05_05" )
|
||||
|
||||
|
||||
##### Generic Helpers #####
|
||||
|
||||
@@ -839,6 +862,7 @@ compile_Boost() {
|
||||
# Rebuild dependecies as well!
|
||||
OIIO_FORCE_REBUILD=true
|
||||
OSL_FORCE_REBUILD=true
|
||||
ALEMBIC_FORCE_REBUILD=true
|
||||
|
||||
prepare_opt
|
||||
|
||||
@@ -1706,6 +1730,165 @@ compile_FFmpeg() {
|
||||
fi
|
||||
}
|
||||
|
||||
#### Build ALEMBIC ####
|
||||
_init_alembic() {
|
||||
_src=$SRC/Alembic-$ALEMBIC_VERSION
|
||||
_hg=false
|
||||
_inst=$INST/alembic-$ALEMBIC_VERSION
|
||||
_inst_shortcut=$INST/alembic
|
||||
}
|
||||
|
||||
clean_alembic() {
|
||||
_init_alembic
|
||||
_clean
|
||||
}
|
||||
|
||||
compile_alembic() {
|
||||
# To be changed each time we make edits that would modify the compiled result!
|
||||
alembic_magic=1
|
||||
_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 ]; then
|
||||
mkdir -p $SRC
|
||||
hg clone -u $ALEMBIC_REPO_UID $ALEMBIC_SOURCE $_src
|
||||
fi
|
||||
|
||||
cd $_src
|
||||
|
||||
# XXX Ugly patching hack!
|
||||
# Alembice cmake files are erratic, to say the least
|
||||
# have to manually disable a bunch of crap here
|
||||
cat << EOF | patch -p1
|
||||
--- a/CMakeLists.txt Mon Jul 28 10:09:21 2014 -0700
|
||||
+++ b/CMakeLists.txt Thu Oct 16 15:03:27 2014 +0200
|
||||
@@ -57,9 +57,9 @@
|
||||
${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} )
|
||||
SET( VERSION ${PROJECT_VERSION} )
|
||||
|
||||
-SET( ALEMBIC_NO_TESTS FALSE )
|
||||
-SET( ALEMBIC_NO_BOOTSTRAP FALSE )
|
||||
-SET( ALEMBIC_NO_OPENGL FALSE )
|
||||
+SET( ALEMBIC_NO_TESTS TRUE )
|
||||
+SET( ALEMBIC_NO_BOOTSTRAP TRUE )
|
||||
+SET( ALEMBIC_NO_OPENGL TRUE )
|
||||
|
||||
MESSAGE(STATUS "CMAKE SYSTEM NAME = ${CMAKE_SYSTEM_NAME}" )
|
||||
|
||||
@@ -306,15 +306,15 @@
|
||||
ENDIF()
|
||||
|
||||
# Include PyAlembic stuff
|
||||
-IF(DEFINED USE_PYALEMBIC AND NOT USE_PYALEMBIC)
|
||||
- MESSAGE(STATUS "Skipping Alembic Python bindings")
|
||||
-ELSE()
|
||||
- MESSAGE(STATUS "About to include Python cmake files")
|
||||
- ADD_SUBDIRECTORY( python )
|
||||
-ENDIF()
|
||||
+#IF(DEFINED USE_PYALEMBIC AND NOT USE_PYALEMBIC)
|
||||
+# MESSAGE(STATUS "Skipping Alembic Python bindings")
|
||||
+#ELSE()
|
||||
+# MESSAGE(STATUS "About to include Python cmake files")
|
||||
+# ADD_SUBDIRECTORY( python )
|
||||
+#ENDIF()
|
||||
|
||||
# Example code not supported
|
||||
-ADD_SUBDIRECTORY( examples )
|
||||
+#ADD_SUBDIRECTORY( examples )
|
||||
|
||||
# Uncomment to build python docs Makefile (requires Sphinx)
|
||||
# Run `make docs` from build root
|
||||
|
||||
EOF
|
||||
|
||||
cat << EOF | patch -p1
|
||||
--- a/lib/Alembic/Util/CMakeLists.txt Mon Jul 28 10:09:21 2014 -0700
|
||||
+++ b/lib/Alembic/Util/CMakeLists.txt Thu Oct 16 15:03:27 2014 +0200
|
||||
@@ -65,7 +65,7 @@
|
||||
DESTINATION include/Alembic/Util
|
||||
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ )
|
||||
|
||||
-IF( NOT ALEMBIC_NO_TESTS )
|
||||
- ADD_SUBDIRECTORY( Tests )
|
||||
-ENDIF()
|
||||
+#IF( NOT ALEMBIC_NO_TESTS )
|
||||
+# ADD_SUBDIRECTORY( Tests )
|
||||
+#ENDIF()
|
||||
|
||||
EOF
|
||||
|
||||
cat << EOF | patch -p1
|
||||
--- a/python/CMakeLists.txt Mon Jul 28 10:09:21 2014 -0700
|
||||
+++ b/python/CMakeLists.txt Thu Oct 16 14:20:25 2014 +0200
|
||||
@@ -35,4 +35,4 @@
|
||||
|
||||
ADD_SUBDIRECTORY( PyAlembic )
|
||||
ADD_SUBDIRECTORY( PyAbcOpenGL )
|
||||
-ADD_SUBDIRECTORY( examples )
|
||||
+#ADD_SUBDIRECTORY( examples )
|
||||
|
||||
EOF
|
||||
|
||||
# Always refresh the whole build!
|
||||
# XXX 'build' directory is included in Alembic sources, don't touch that
|
||||
if [ -d blender_build ]; then
|
||||
rm -rf blender_build
|
||||
fi
|
||||
mkdir blender_build
|
||||
cd blender_build
|
||||
|
||||
# XXX Alembic cmake doesn't take these as options
|
||||
# XXX Alembic creates a subfolder itself ... rather than fix their
|
||||
# stupid build files, just expect this here by using $INST as prefix
|
||||
export ALEMBIC_INSTALL_PREFIX=$INST
|
||||
|
||||
cmake_d="-D CMAKE_BUILD_TYPE=Release"
|
||||
cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$INST"
|
||||
cmake_d="$cmake_d -D BUILD_SHARED_LIBS=ON"
|
||||
cmake_d="$cmake_d -D BUILD_STATIC_LIBS=ON"
|
||||
cmake_d="$cmake_d -D USE_PYTHON=OFF"
|
||||
cmake_d="$cmake_d -D USE_PYALEMBIC=OFF"
|
||||
cmake_d="$cmakd_d -D ALEMBIC_PYTHON_INCLUDE_DIR=/use/include/python2.7" # XXX BAD
|
||||
cmake_d="$cmakd_d -D ALEMBIC_PYTHON_LIBRARY=/use/lib/python2.7" # XXX BAD
|
||||
cmake_d="$cmake_d -D USE_PYILMBASE=OFF"
|
||||
cmake_d="$cmake_d -D ILMBASE_ROOT=$INST/openexr"
|
||||
cmake_d="$cmake_d -D ALEMBIC_ILMBASE_HALF_LIB=$INST/openexr/lib/libHalf.la"
|
||||
cmake_d="$cmake_d -D ALEMBIC_ILMBASE_IEX_LIB=$INST/openexr/lib/libIex-2_1.la"
|
||||
cmake_d="$cmake_d -D ALEMBIC_ILMBASE_ILMTHREAD_LIB=$INST/openexr/lib/libIlmThread-2_1.la"
|
||||
cmake_d="$cmake_d -D ALEMBIC_ILMBASE_IMATH_LIB=$INST/openexr/lib/libImath-2_1.la"
|
||||
|
||||
cmake $cmake_d ../
|
||||
|
||||
make -j$THREADS && make 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
|
||||
}
|
||||
|
||||
|
||||
#### Install on DEB-like ####
|
||||
get_package_version_DEB() {
|
||||
@@ -1992,7 +2175,8 @@ install_DEB() {
|
||||
if [ $? -eq 0 ]; then
|
||||
install_packages_DEB libboost-locale$boost_version-dev libboost-filesystem$boost_version-dev \
|
||||
libboost-regex$boost_version-dev libboost-system$boost_version-dev \
|
||||
libboost-thread$boost_version-dev libboost-wave$boost_version-dev
|
||||
libboost-thread$boost_version-dev libboost-python$boost_version-dev \
|
||||
libboost-program-options$boost_version-dev libboost-wave$boost_version-dev
|
||||
clean_Boost
|
||||
else
|
||||
compile_Boost
|
||||
@@ -2125,6 +2309,14 @@ install_DEB() {
|
||||
# fi
|
||||
compile_FFmpeg
|
||||
fi
|
||||
|
||||
if $ALEMBIC_SKIP; then
|
||||
WARNING "Skipping Alembic installation, as requested..."
|
||||
else
|
||||
install_packages_DEB libhdf5-dev
|
||||
install_packages_DEB libpython2.7-dev # XXX nasty hack, should be done better ...
|
||||
compile_alembic
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -3030,6 +3222,12 @@ print_info() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -d $INST/alembic ]; then
|
||||
_1="-D ALEMBIC_ROOT_DIR=$INST/alembic"
|
||||
PRINT " $_1"
|
||||
_buildargs="$_buildargs $_1"
|
||||
fi
|
||||
|
||||
PRINT ""
|
||||
PRINT "Or even simpler, just run (in your blender-source dir):"
|
||||
PRINT " make -j$THREADS BUILD_CMAKE_ARGS=\"$_buildargs\""
|
||||
@@ -3099,6 +3297,13 @@ print_info() {
|
||||
PRINT "BF_FFMPEG_LIB = 'avformat avcodec swscale avutil avdevice `print_info_ffmpeglink`'"
|
||||
fi
|
||||
|
||||
if [ "$ALEMBIC_SKIP" = false ]; then
|
||||
PRINT "WITH_BF_ALEMBIC = True"
|
||||
if [ -d $INST/alembic ]; then
|
||||
PRINT "BF_ALEMBIC = '$INST/alembic'"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$WITH_ALL" = false ]; then
|
||||
PRINT "WITH_BF_3DMOUSE = False"
|
||||
# No libspacenav in official arch repos...
|
||||
|
@@ -166,6 +166,19 @@ BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
|
||||
# Ocean Simulation
|
||||
WITH_BF_OCEANSIM = True
|
||||
|
||||
# Alembic
|
||||
WITH_BF_HDF5 = False
|
||||
WITH_BF_ALEMBIC = True
|
||||
WITH_BF_STATICALEMBIC = True
|
||||
BF_ALEMBIC = '/opt/lib/alembic'
|
||||
BF_ALEMBIC_INC = '${BF_ALEMBIC}/include'
|
||||
BF_ALEMBIC_LIBPATH = '${BF_ALEMBIC}/lib/static'
|
||||
BF_ALEMBIC_LIB_STATIC = '${BF_ALEMBIC_LIBPATH}/libAlembicAbcGeom.a ${BF_ALEMBIC_LIBPATH}/libAlembicAbc.a ' + \
|
||||
'${BF_ALEMBIC_LIBPATH}/libAlembicAbcCollection.a ${BF_ALEMBIC_LIBPATH}/libAlembicAbcCoreFactory.a ' + \
|
||||
'${BF_ALEMBIC_LIBPATH}/libAlembicAbcCoreOgawa.a ${BF_ALEMBIC_LIBPATH}/libAlembicAbcMaterial.a ' + \
|
||||
'${BF_ALEMBIC_LIBPATH}/libAlembicOgawa.a ${BF_ALEMBIC_LIBPATH}/libAlembicAbcCoreAbstract.a ' + \
|
||||
'${BF_ALEMBIC_LIBPATH}/libAlembicUtil.a'
|
||||
|
||||
# Compilation and optimization
|
||||
BF_DEBUG = False
|
||||
REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++
|
||||
|
@@ -166,6 +166,19 @@ BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
|
||||
# Ocean Simulation
|
||||
WITH_BF_OCEANSIM = True
|
||||
|
||||
# Alembic
|
||||
WITH_BF_HDF5 = False
|
||||
WITH_BF_ALEMBIC = True
|
||||
WITH_BF_STATICALEMBIC = True
|
||||
BF_ALEMBIC = '/opt/lib/alembic'
|
||||
BF_ALEMBIC_INC = '${BF_ALEMBIC}/include'
|
||||
BF_ALEMBIC_LIBPATH = '${BF_ALEMBIC}/lib/static'
|
||||
BF_ALEMBIC_LIB_STATIC = '${BF_ALEMBIC_LIBPATH}/libAlembicAbcGeom.a ${BF_ALEMBIC_LIBPATH}/libAlembicAbc.a ' + \
|
||||
'${BF_ALEMBIC_LIBPATH}/libAlembicAbcCollection.a ${BF_ALEMBIC_LIBPATH}/libAlembicAbcCoreFactory.a ' + \
|
||||
'${BF_ALEMBIC_LIBPATH}/libAlembicAbcCoreOgawa.a ${BF_ALEMBIC_LIBPATH}/libAlembicAbcMaterial.a ' + \
|
||||
'${BF_ALEMBIC_LIBPATH}/libAlembicOgawa.a ${BF_ALEMBIC_LIBPATH}/libAlembicAbcCoreAbstract.a ' + \
|
||||
'${BF_ALEMBIC_LIBPATH}/libAlembicUtil.a'
|
||||
|
||||
# Compilation and optimization
|
||||
BF_DEBUG = False
|
||||
REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++
|
||||
|
84
build_files/cmake/Modules/FindAlembic.cmake
Normal file
84
build_files/cmake/Modules/FindAlembic.cmake
Normal file
@@ -0,0 +1,84 @@
|
||||
# - Find Alembic library
|
||||
# Find the native Alembic includes and library
|
||||
# This module defines
|
||||
# ALEMBIC_INCLUDE_DIRS, where to find Alembic headers.
|
||||
# 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 2013 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
|
||||
)
|
||||
|
||||
SET(_alembic_FIND_COMPONENTS
|
||||
AlembicAbc
|
||||
AlembicAbcCoreAbstract
|
||||
AlembicAbcGeom
|
||||
AlembicAbcCoreHDF5
|
||||
AlembicAbcCoreOgawa
|
||||
AlembicOgawa
|
||||
AlembicUtil
|
||||
)
|
||||
|
||||
FIND_PATH(_alembic_INCLUDE_DIRS
|
||||
NAMES
|
||||
Alembic/Abc/All.h
|
||||
HINTS
|
||||
${_alembic_SEARCH_DIRS}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
)
|
||||
|
||||
SET(_alembic_LIBRARIES)
|
||||
FOREACH(COMPONENT ${_alembic_FIND_COMPONENTS})
|
||||
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
|
||||
|
||||
FIND_LIBRARY(ALEMBIC_${UPPERCOMPONENT}_LIBRARY
|
||||
NAMES
|
||||
${COMPONENT}
|
||||
HINTS
|
||||
${_alembic_SEARCH_DIRS}
|
||||
PATH_SUFFIXES
|
||||
lib/static
|
||||
)
|
||||
MARK_AS_ADVANCED(ALEMBIC_${UPPERCOMPONENT}_LIBRARY)
|
||||
LIST(APPEND _alembic_LIBRARIES "${ALEMBIC_${UPPERCOMPONENT}_LIBRARY}")
|
||||
ENDFOREACH()
|
||||
|
||||
# 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_LIBRARIES _alembic_INCLUDE_DIRS)
|
||||
|
||||
IF(ALEMBIC_FOUND)
|
||||
SET(ALEMBIC_LIBRARIES ${_alembic_LIBRARIES})
|
||||
SET(ALEMBIC_INCLUDE_DIRS ${_alembic_INCLUDE_DIRS})
|
||||
ENDIF(ALEMBIC_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
ALEMBIC_INCLUDE_DIRS
|
||||
ALEMBIC_LIBRARIES
|
||||
)
|
75
build_files/cmake/Modules/FindHDF5.cmake
Normal file
75
build_files/cmake/Modules/FindHDF5.cmake
Normal file
@@ -0,0 +1,75 @@
|
||||
# - Find HDF5 library
|
||||
# Find the native hdf5 includes and library
|
||||
# This module defines
|
||||
# HDF5_INCLUDE_DIRS, where to find hdf5 headers.
|
||||
# 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 2013 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
|
||||
)
|
||||
|
||||
SET(_hdf5_FIND_COMPONENTS
|
||||
hdf5
|
||||
hdf5_hl
|
||||
)
|
||||
|
||||
FIND_PATH(_hdf5_INCLUDE_DIRS
|
||||
NAMES
|
||||
hdf5.h
|
||||
HINTS
|
||||
${_hdf5_SEARCH_DIRS}
|
||||
)
|
||||
|
||||
SET(_hdf5_LIBRARIES)
|
||||
FOREACH(COMPONENT ${_hdf5_FIND_COMPONENTS})
|
||||
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
|
||||
|
||||
FIND_LIBRARY(HDF5_${UPPERCOMPONENT}_LIBRARY
|
||||
NAMES
|
||||
${COMPONENT}
|
||||
HINTS
|
||||
${_hdf5_SEARCH_DIRS}
|
||||
)
|
||||
MARK_AS_ADVANCED(HDF5_${UPPERCOMPONENT}_LIBRARY)
|
||||
LIST(APPEND _hdf5_LIBRARIES "${HDF5_${UPPERCOMPONENT}_LIBRARY}")
|
||||
ENDFOREACH()
|
||||
|
||||
# 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_LIBRARIES _hdf5_INCLUDE_DIRS)
|
||||
|
||||
IF(HDF5_FOUND)
|
||||
SET(HDF5_LIBRARIES ${_hdf5_LIBRARIES})
|
||||
SET(HDF5_INCLUDE_DIRS ${_hdf5_INCLUDE_DIRS})
|
||||
ENDIF(HDF5_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
HDF5_INCLUDE_DIRS
|
||||
HDF5_LIBRARIES
|
||||
)
|
@@ -421,6 +421,12 @@ macro(setup_liblinks
|
||||
if(WITH_LLVM)
|
||||
target_link_libraries(${target} ${LLVM_LIBRARY})
|
||||
endif()
|
||||
if(WITH_ALEMBIC)
|
||||
target_link_libraries(${target} ${ALEMBIC_LIBRARIES})
|
||||
endif()
|
||||
if(WITH_HDF5)
|
||||
target_link_libraries(${target} ${HDF5_LIBRARIES})
|
||||
endif()
|
||||
if(WIN32 AND NOT UNIX)
|
||||
target_link_libraries(${target} ${PTHREADS_LIBRARIES})
|
||||
endif()
|
||||
@@ -560,6 +566,8 @@ macro(SETUP_BLENDER_SORTED_LIBS)
|
||||
ge_videotex
|
||||
bf_dna
|
||||
bf_blenfont
|
||||
bf_pointcache_alembic
|
||||
bf_pointcache
|
||||
bf_intern_audaspace
|
||||
bf_intern_mikktspace
|
||||
bf_intern_dualcon
|
||||
|
@@ -52,9 +52,9 @@ BF_OPENEXR = '/usr'
|
||||
# BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR ${BF_OPENEXR}/include'
|
||||
|
||||
BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR'
|
||||
BF_OPENEXR_LIB = 'Half IlmImf Iex Imath '
|
||||
BF_OPENEXR_LIB = 'Half IlmImf-2_1 Iex-2_1 Imath-2_1 '
|
||||
BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
|
||||
# BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
|
||||
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
|
||||
|
||||
|
||||
WITH_BF_DDS = True
|
||||
@@ -226,6 +226,19 @@ BF_3DMOUSE_LIB_STATIC = '${BF_3DMOUSE_LIBPATH}/libspnav.a'
|
||||
#Freestyle
|
||||
WITH_BF_FREESTYLE = True
|
||||
|
||||
# HDF5
|
||||
WITH_BF_HDF5 = True
|
||||
BF_HDF5 = '/usr'
|
||||
BF_HDF5_LIB = 'hdf5 hdf5_hl'
|
||||
BF_HDF5_LIBPATH='${BF_HDF5}/lib'
|
||||
|
||||
# Alembic
|
||||
WITH_BF_ALEMBIC = True
|
||||
BF_ALEMBIC = '/opt/lib/alembic'
|
||||
BF_ALEMBIC_LIB = 'AlembicAbcGeom AlembicAbc AlembicAbcCollection AlembicAbcCoreFactory AlembicAbcCoreHDF5 AlembicAbcCoreAbstract AlembicAbcCoreOgawa AlembicAbcMaterial AlembicOgawa AlembicUtil'
|
||||
BF_ALEMBIC_INC = '${BF_ALEMBIC}/include'
|
||||
BF_ALEMBIC_LIBPATH='${BF_ALEMBIC}/lib/static'
|
||||
|
||||
##
|
||||
CC = 'gcc'
|
||||
CXX = 'g++'
|
||||
|
@@ -204,10 +204,20 @@ def setup_staticlibs(lenv):
|
||||
libincs += Split(lenv['BF_OIIO_LIBPATH'])
|
||||
if lenv['WITH_BF_STATICOIIO']:
|
||||
statlibs += Split(lenv['BF_OIIO_LIB_STATIC'])
|
||||
|
||||
if lenv['WITH_BF_HDF5']:
|
||||
libincs += Split(lenv['BF_HDF5_LIBPATH'])
|
||||
|
||||
if lenv['WITH_BF_ALEMBIC']:
|
||||
libincs += Split(lenv['BF_ALEMBIC_LIBPATH'])
|
||||
if lenv['WITH_BF_STATICALEMBIC']:
|
||||
statlibs += Split(lenv['BF_ALEMBIC_LIB_STATIC'])
|
||||
|
||||
if lenv['WITH_BF_OPENEXR']:
|
||||
libincs += Split(lenv['BF_OPENEXR_LIBPATH'])
|
||||
if lenv['WITH_BF_STATICOPENEXR']:
|
||||
statlibs += Split(lenv['BF_OPENEXR_LIB_STATIC'])
|
||||
|
||||
if lenv['WITH_BF_ZLIB'] and lenv['WITH_BF_STATICZLIB']:
|
||||
statlibs += Split(lenv['BF_ZLIB_LIB_STATIC'])
|
||||
|
||||
@@ -283,8 +293,16 @@ def setup_syslibs(lenv):
|
||||
if not lenv['WITH_BF_STATICOCIO']:
|
||||
syslibs += Split(lenv['BF_OCIO_LIB'])
|
||||
|
||||
if lenv['WITH_BF_HDF5']:
|
||||
syslibs += Split(lenv['BF_HDF5_LIB'])
|
||||
|
||||
if lenv['WITH_BF_ALEMBIC']:
|
||||
if not lenv['WITH_BF_STATICALEMBIC']:
|
||||
syslibs += Split(lenv['BF_ALEMBIC_LIB'])
|
||||
|
||||
if lenv['WITH_BF_OPENEXR'] and not lenv['WITH_BF_STATICOPENEXR']:
|
||||
syslibs += Split(lenv['BF_OPENEXR_LIB'])
|
||||
|
||||
if lenv['WITH_BF_ZLIB'] and not lenv['WITH_BF_STATICZLIB']:
|
||||
syslibs += Split(lenv['BF_ZLIB_LIB'])
|
||||
if lenv['WITH_BF_TIFF'] and not lenv['WITH_BF_STATICTIFF']:
|
||||
@@ -372,7 +390,22 @@ def propose_priorities():
|
||||
def creator(env):
|
||||
sources = ['creator.c']# + Blender.buildinfo(env, "dynamic") + Blender.resources
|
||||
|
||||
incs = ['#/intern/guardedalloc', '#/source/blender/blenlib', '#/source/blender/blenkernel', '#/source/blender/editors/include', '#/source/blender/blenloader', '#/source/blender/imbuf', '#/source/blender/renderconverter', '#/source/blender/render/extern/include', '#/source/blender/windowmanager', '#/source/blender/makesdna', '#/source/blender/makesrna', '#/source/gameengine/BlenderRoutines', '#/extern/glew/include', '#/source/blender/gpu', env['BF_OPENGL_INC']]
|
||||
incs = ['#/intern/guardedalloc',
|
||||
'#/source/blender/blenlib',
|
||||
'#/source/blender/blenkernel',
|
||||
'#/source/blender/editors/include',
|
||||
'#/source/blender/blenloader',
|
||||
'#/source/blender/imbuf',
|
||||
'#/source/blender/renderconverter',
|
||||
'#/source/blender/render/extern/include',
|
||||
'#/source/blender/windowmanager',
|
||||
'#/source/blender/makesdna',
|
||||
'#/source/blender/makesrna',
|
||||
'#/source/blender/pointcache',
|
||||
'#/source/gameengine/BlenderRoutines',
|
||||
'#/extern/glew/include',
|
||||
'#/source/blender/gpu',
|
||||
env['BF_OPENGL_INC']]
|
||||
|
||||
defs = []
|
||||
|
||||
|
@@ -182,7 +182,8 @@ def validate_arguments(args, bc):
|
||||
'WITH_BF_BOOST', 'WITH_BF_STATICBOOST', 'BF_BOOST', 'BF_BOOST_INC', 'BF_BOOST_LIB', 'BF_BOOST_LIB_INTERNATIONAL', 'BF_BOOST_LIB_STATIC', 'BF_BOOST_LIBPATH',
|
||||
'WITH_BF_LIBMV', 'WITH_BF_LIBMV_SCHUR_SPECIALIZATIONS',
|
||||
'WITH_BF_CYCLES_OSL', 'WITH_BF_STATICOSL', 'BF_OSL', 'BF_OSL_INC', 'BF_OSL_LIB', 'BF_OSL_LIBPATH', 'BF_OSL_LIB_STATIC', 'BF_OSL_COMPILER',
|
||||
'WITH_BF_LLVM', 'WITH_BF_STATICLLVM', 'BF_LLVM', 'BF_LLVM_LIB', 'BF_LLVM_LIBPATH', 'BF_LLVM_LIB_STATIC', 'BF_PROGRAM_LINKFLAGS'
|
||||
'WITH_BF_LLVM', 'WITH_BF_STATICLLVM', 'BF_LLVM', 'BF_LLVM_LIB', 'BF_LLVM_LIBPATH', 'BF_LLVM_LIB_STATIC', 'BF_PROGRAM_LINKFLAGS',
|
||||
'WITH_BF_ALEMBIC', 'BF_ALEMBIC', 'BF_ALEMBIC_INC', 'BF_ALEMBIC_LIB', 'BF_ALEMBIC_LIBPATH',
|
||||
]
|
||||
|
||||
# Have options here that scons expects to be lists
|
||||
@@ -581,6 +582,19 @@ def read_opts(env, cfg, args):
|
||||
(BoolVariable('WITH_BF_LIBMV_SCHUR_SPECIALIZATIONS', 'Enable fixed-size schur specializations', True)),
|
||||
|
||||
(BoolVariable('WITH_BF_COMPOSITOR', 'Enable the tile based nodal compositor', True)),
|
||||
|
||||
(BoolVariable('WITH_BF_HDF5', 'Use HDF5 if true', False)),
|
||||
('BF_HDF5', 'HDF5 base path', ''),
|
||||
('BF_HDF5_LIB', 'HDF5 library', ''),
|
||||
('BF_HDF5_LIBPATH', 'HDF5 library path', ''),
|
||||
|
||||
(BoolVariable('WITH_BF_ALEMBIC', 'Use Alembic if true', False)),
|
||||
(BoolVariable('WITH_BF_STATICALEMBIC', 'Staticly link to Alembic', False)),
|
||||
('BF_ALEMBIC', 'Alembic base path', ''),
|
||||
('BF_ALEMBIC_INC', 'Alembic include path', ''),
|
||||
('BF_ALEMBIC_LIB', 'Alembic library', ''),
|
||||
('BF_ALEMBIC_LIB_STATIC', 'Alembic static libraries', ''),
|
||||
('BF_ALEMBIC_LIBPATH', 'Alembic library path', ''),
|
||||
) # end of opts.AddOptions()
|
||||
|
||||
localopts.AddVariables(
|
||||
|
@@ -96,6 +96,12 @@ macro(cycles_target_link_libraries target)
|
||||
${CMAKE_DL_LIBS}
|
||||
${PLATFORM_LINKLIBS}
|
||||
)
|
||||
if(WITH_ALEMBIC)
|
||||
target_link_libraries(
|
||||
${target}
|
||||
${ALEMBIC_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Application build targets
|
||||
@@ -106,6 +112,23 @@ if(WITH_CYCLES_STANDALONE)
|
||||
cycles_xml.cpp
|
||||
cycles_xml.h
|
||||
)
|
||||
|
||||
if(WITH_ALEMBIC)
|
||||
list(APPEND SRC
|
||||
cycles_alembic.cpp
|
||||
cycles_alembic.h
|
||||
)
|
||||
add_definitions(-DWITH_ALEMBIC)
|
||||
include_directories(
|
||||
SYSTEM
|
||||
${ALEMBIC_INCLUDE_DIRS}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_HDF5)
|
||||
add_definitions(-DWITH_HDF5)
|
||||
endif()
|
||||
|
||||
add_executable(cycles ${SRC})
|
||||
cycles_target_link_libraries(cycles)
|
||||
|
||||
|
426
intern/cycles/app/cycles_alembic.cpp
Normal file
426
intern/cycles/app/cycles_alembic.cpp
Normal file
@@ -0,0 +1,426 @@
|
||||
/*
|
||||
* Copyright 2015 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
#include <Alembic/AbcCoreOgawa/ReadWrite.h>
|
||||
#ifdef WITH_HDF5
|
||||
#include <Alembic/AbcCoreHDF5/ReadWrite.h>
|
||||
#endif
|
||||
#include <Alembic/Abc/IArchive.h>
|
||||
#include <Alembic/Abc/IObject.h>
|
||||
#include <Alembic/Abc/ISampleSelector.h>
|
||||
#include <Alembic/Abc/ICompoundProperty.h>
|
||||
#include <Alembic/Abc/IScalarProperty.h>
|
||||
#include <Alembic/Abc/IArrayProperty.h>
|
||||
#include <Alembic/Abc/ArchiveInfo.h>
|
||||
#include <Alembic/AbcGeom/IPolyMesh.h>
|
||||
|
||||
#include "camera.h"
|
||||
#include "film.h"
|
||||
#include "graph.h"
|
||||
#include "integrator.h"
|
||||
#include "light.h"
|
||||
#include "mesh.h"
|
||||
#include "nodes.h"
|
||||
#include "object.h"
|
||||
#include "shader.h"
|
||||
#include "scene.h"
|
||||
|
||||
#include "subd_mesh.h"
|
||||
#include "subd_patch.h"
|
||||
#include "subd_split.h"
|
||||
|
||||
#include "util_debug.h"
|
||||
#include "util_foreach.h"
|
||||
#include "util_path.h"
|
||||
#include "util_transform.h"
|
||||
#include "util_xml.h"
|
||||
|
||||
#include "cycles_alembic.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
using namespace Alembic;
|
||||
using namespace Abc;
|
||||
using namespace AbcGeom;
|
||||
|
||||
#define ABC_SAFE_CALL_BEGIN \
|
||||
try {
|
||||
|
||||
#define ABC_SAFE_CALL_END \
|
||||
} \
|
||||
catch (Alembic::Util::Exception e) { \
|
||||
printf("%s", e.what()); \
|
||||
}
|
||||
|
||||
|
||||
/* File */
|
||||
|
||||
static const std::string g_sep(";");
|
||||
|
||||
static void visitProperties(std::stringstream &ss, ICompoundProperty, std::string &);
|
||||
|
||||
template <class PROP>
|
||||
static void visitSimpleArrayProperty(std::stringstream &ss, PROP iProp, const std::string &iIndent)
|
||||
{
|
||||
std::string ptype = "ArrayProperty ";
|
||||
size_t asize = 0;
|
||||
|
||||
AbcA::ArraySamplePtr samp;
|
||||
index_t maxSamples = iProp.getNumSamples();
|
||||
for (index_t i = 0 ; i < maxSamples; ++i) {
|
||||
iProp.get(samp, ISampleSelector( i ));
|
||||
asize = samp->size();
|
||||
};
|
||||
|
||||
std::string mdstring = "interpretation=";
|
||||
mdstring += iProp.getMetaData().get("interpretation");
|
||||
|
||||
std::stringstream dtype;
|
||||
dtype << "datatype=";
|
||||
dtype << iProp.getDataType();
|
||||
|
||||
std::stringstream asizestr;
|
||||
asizestr << ";arraysize=";
|
||||
asizestr << asize;
|
||||
|
||||
mdstring += g_sep;
|
||||
|
||||
mdstring += dtype.str();
|
||||
|
||||
mdstring += asizestr.str();
|
||||
|
||||
ss << iIndent << " " << ptype << "name=" << iProp.getName()
|
||||
<< g_sep << mdstring << g_sep << "numsamps="
|
||||
<< iProp.getNumSamples() << std::endl;
|
||||
}
|
||||
|
||||
template <class PROP>
|
||||
static void visitSimpleScalarProperty(std::stringstream &ss, PROP iProp, const std::string &iIndent)
|
||||
{
|
||||
std::string ptype = "ScalarProperty ";
|
||||
size_t asize = 0;
|
||||
|
||||
const AbcA::DataType &dt = iProp.getDataType();
|
||||
const Alembic::Util ::uint8_t extent = dt.getExtent();
|
||||
Alembic::Util::Dimensions dims(extent);
|
||||
AbcA::ArraySamplePtr samp = AbcA::AllocateArraySample( dt, dims );
|
||||
index_t maxSamples = iProp.getNumSamples();
|
||||
for (index_t i = 0 ; i < maxSamples; ++i) {
|
||||
iProp.get(const_cast<void*>(samp->getData()), ISampleSelector( i ));
|
||||
asize = samp->size();
|
||||
};
|
||||
|
||||
std::string mdstring = "interpretation=";
|
||||
mdstring += iProp.getMetaData().get("interpretation");
|
||||
|
||||
std::stringstream dtype;
|
||||
dtype << "datatype=";
|
||||
dtype << dt;
|
||||
|
||||
std::stringstream asizestr;
|
||||
asizestr << ";arraysize=";
|
||||
asizestr << asize;
|
||||
|
||||
mdstring += g_sep;
|
||||
|
||||
mdstring += dtype.str();
|
||||
|
||||
mdstring += asizestr.str();
|
||||
|
||||
ss << iIndent << " " << ptype << "name=" << iProp.getName()
|
||||
<< g_sep << mdstring << g_sep << "numsamps="
|
||||
<< iProp.getNumSamples() << std::endl;
|
||||
}
|
||||
|
||||
static void visitCompoundProperty(std::stringstream &ss, ICompoundProperty iProp, std::string &ioIndent)
|
||||
{
|
||||
std::string oldIndent = ioIndent;
|
||||
ioIndent += " ";
|
||||
|
||||
std::string interp = "schema=";
|
||||
interp += iProp.getMetaData().get("schema");
|
||||
|
||||
ss << ioIndent << "CompoundProperty " << "name=" << iProp.getName()
|
||||
<< g_sep << interp << std::endl;
|
||||
|
||||
visitProperties(ss, iProp, ioIndent);
|
||||
|
||||
ioIndent = oldIndent;
|
||||
}
|
||||
|
||||
static void visitProperties(std::stringstream &ss, ICompoundProperty iParent, std::string &ioIndent )
|
||||
{
|
||||
std::string oldIndent = ioIndent;
|
||||
for (size_t i = 0 ; i < iParent.getNumProperties() ; i++) {
|
||||
PropertyHeader header = iParent.getPropertyHeader(i);
|
||||
|
||||
if (header.isCompound()) {
|
||||
visitCompoundProperty(ss, ICompoundProperty(iParent, header.getName()), ioIndent);
|
||||
}
|
||||
else if (header.isScalar()) {
|
||||
visitSimpleScalarProperty(ss, IScalarProperty(iParent, header.getName()), ioIndent);
|
||||
}
|
||||
else {
|
||||
assert(header.isArray());
|
||||
visitSimpleArrayProperty(ss, IArrayProperty(iParent, header.getName()), ioIndent);
|
||||
}
|
||||
}
|
||||
|
||||
ioIndent = oldIndent;
|
||||
}
|
||||
|
||||
static void visitObject(std::stringstream &ss, IObject iObj, std::string iIndent, AbcArchiveInfoLevel info_level)
|
||||
{
|
||||
// Object has a name, a full name, some meta data,
|
||||
// and then it has a compound property full of properties.
|
||||
std::string path = iObj.getFullName();
|
||||
|
||||
if (iObj.isInstanceRoot()) {
|
||||
if (path != "/") {
|
||||
ss << "Object " << "name=" << path
|
||||
<< " [Instance " << iObj.instanceSourcePath() << "]"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
else if (iObj.isInstanceDescendant()) {
|
||||
/* skip non-root instances to avoid repetition */
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (path != "/") {
|
||||
ss << "Object " << "name=" << path << std::endl;
|
||||
}
|
||||
|
||||
if (info_level >= ABC_INFO_PROPERTIES) {
|
||||
// Get the properties.
|
||||
ICompoundProperty props = iObj.getProperties();
|
||||
visitProperties(ss, props, iIndent);
|
||||
}
|
||||
|
||||
// now the child objects
|
||||
for (size_t i = 0 ; i < iObj.getNumChildren() ; i++) {
|
||||
visitObject(ss, IObject(iObj, iObj.getChildHeader(i).getName()), iIndent, info_level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::string abc_archive_info(IArchive &archive, AbcArchiveInfoLevel info_level)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "Alembic Archive Info for "
|
||||
<< Alembic::AbcCoreAbstract::GetLibraryVersion()
|
||||
<< std::endl;;
|
||||
|
||||
std::string appName;
|
||||
std::string libraryVersionString;
|
||||
Alembic::Util::uint32_t libraryVersion;
|
||||
std::string whenWritten;
|
||||
std::string userDescription;
|
||||
GetArchiveInfo(archive,
|
||||
appName,
|
||||
libraryVersionString,
|
||||
libraryVersion,
|
||||
whenWritten,
|
||||
userDescription);
|
||||
|
||||
if (appName != "") {
|
||||
ss << " file written by: " << appName << std::endl;
|
||||
ss << " using Alembic : " << libraryVersionString << std::endl;
|
||||
ss << " written on : " << whenWritten << std::endl;
|
||||
ss << " user description : " << userDescription << std::endl;
|
||||
ss << std::endl;
|
||||
}
|
||||
else {
|
||||
// ss << argv[1] << std::endl;
|
||||
ss << " (file doesn't have any ArchiveInfo)"
|
||||
<< std::endl;
|
||||
ss << std::endl;
|
||||
}
|
||||
|
||||
if (info_level >= ABC_INFO_OBJECTS)
|
||||
visitObject(ss, archive.getTop(), "", info_level);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
struct AbcReadState {
|
||||
Scene *scene; /* scene pointer */
|
||||
float time;
|
||||
Transform tfm; /* current transform state */
|
||||
bool smooth; /* smooth normal state */
|
||||
int shader; /* current shader */
|
||||
string base; /* base path to current file*/
|
||||
float dicing_rate; /* current dicing rate */
|
||||
Mesh::DisplacementMethod displacement_method;
|
||||
};
|
||||
|
||||
static ISampleSelector get_sample_selector(const AbcReadState &state)
|
||||
{
|
||||
return ISampleSelector(state.time, ISampleSelector::kFloorIndex);
|
||||
}
|
||||
|
||||
static Mesh *add_mesh(Scene *scene, const Transform& tfm)
|
||||
{
|
||||
/* create mesh */
|
||||
Mesh *mesh = new Mesh();
|
||||
scene->meshes.push_back(mesh);
|
||||
|
||||
/* create object*/
|
||||
Object *object = new Object();
|
||||
object->mesh = mesh;
|
||||
object->tfm = tfm;
|
||||
scene->objects.push_back(object);
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
static void read_mesh(const AbcReadState &state, IPolyMesh object)
|
||||
{
|
||||
/* add mesh */
|
||||
Mesh *mesh = add_mesh(state.scene, state.tfm);
|
||||
mesh->used_shaders.push_back(state.shader);
|
||||
|
||||
/* read state */
|
||||
int shader = state.shader;
|
||||
bool smooth = state.smooth;
|
||||
|
||||
mesh->displacement_method = state.displacement_method;
|
||||
|
||||
ISampleSelector ss = get_sample_selector(state);
|
||||
IPolyMeshSchema schema = object.getSchema();
|
||||
|
||||
IPolyMeshSchema::Sample sample;
|
||||
schema.get(sample, ss);
|
||||
|
||||
int totverts = sample.getPositions()->size();
|
||||
int totfaces = sample.getFaceCounts()->size();
|
||||
const V3f *P = sample.getPositions()->get();
|
||||
const int32_t *verts = sample.getFaceIndices()->get();
|
||||
const int32_t *nverts = sample.getFaceCounts()->get();
|
||||
|
||||
/* create vertices */
|
||||
mesh->verts.reserve(totverts);
|
||||
for(int i = 0; i < totverts; i++) {
|
||||
mesh->verts.push_back(make_float3(P[i].x, P[i].y, P[i].z));
|
||||
}
|
||||
|
||||
/* create triangles */
|
||||
int index_offset = 0;
|
||||
|
||||
for(int i = 0; i < totfaces; i++) {
|
||||
int n = nverts[i];
|
||||
/* XXX TODO only supports tris and quads atm,
|
||||
* need a proper tessellation algorithm in cycles.
|
||||
*/
|
||||
if (n > 4) {
|
||||
printf("%d-sided face found, only triangles and quads are supported currently", n);
|
||||
n = 4;
|
||||
}
|
||||
|
||||
for(int j = 0; j < n-2; j++) {
|
||||
int v0 = verts[index_offset];
|
||||
int v1 = verts[index_offset + j + 1];
|
||||
int v2 = verts[index_offset + j + 2];
|
||||
|
||||
assert(v0 < (int)totverts);
|
||||
assert(v1 < (int)totverts);
|
||||
assert(v2 < (int)totverts);
|
||||
|
||||
mesh->add_triangle(v0, v1, v2, shader, smooth);
|
||||
}
|
||||
|
||||
index_offset += n;
|
||||
}
|
||||
|
||||
/* temporary for test compatibility */
|
||||
mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
|
||||
}
|
||||
|
||||
static void read_object(const AbcReadState &state, IObject object)
|
||||
{
|
||||
for (int i = 0; i < object.getNumChildren(); ++i) {
|
||||
IObject child = object.getChild(i);
|
||||
const MetaData &metadata = child.getMetaData();
|
||||
|
||||
if (IPolyMeshSchema::matches(metadata)) {
|
||||
read_mesh(state, IPolyMesh(child, kWrapExisting));
|
||||
}
|
||||
else {
|
||||
read_object(state, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void read_archive(Scene *scene, IArchive archive, const char *filepath)
|
||||
{
|
||||
AbcReadState state;
|
||||
|
||||
state.scene = scene;
|
||||
state.time = 0.0f; // TODO
|
||||
state.tfm = transform_identity();
|
||||
state.shader = scene->default_surface;
|
||||
state.smooth = false;
|
||||
state.dicing_rate = 0.1f;
|
||||
state.base = path_dirname(filepath);
|
||||
|
||||
read_object(state, archive.getTop());
|
||||
|
||||
scene->params.bvh_type = SceneParams::BVH_STATIC;
|
||||
}
|
||||
|
||||
void abc_read_ogawa_file(Scene *scene, const char *filepath, AbcArchiveInfoLevel info_level)
|
||||
{
|
||||
IArchive archive;
|
||||
ABC_SAFE_CALL_BEGIN
|
||||
archive = IArchive(AbcCoreOgawa::ReadArchive(), filepath, ErrorHandler::kThrowPolicy);
|
||||
ABC_SAFE_CALL_END
|
||||
|
||||
if (archive) {
|
||||
if (info_level >= ABC_INFO_BASIC)
|
||||
printf("%s", abc_archive_info(archive, info_level).c_str());
|
||||
|
||||
read_archive(scene, archive, filepath);
|
||||
}
|
||||
}
|
||||
|
||||
void abc_read_hdf5_file(Scene *scene, const char *filepath, AbcArchiveInfoLevel info_level)
|
||||
{
|
||||
#ifdef WITH_HDF5
|
||||
IArchive archive;
|
||||
ABC_SAFE_CALL_BEGIN
|
||||
archive = IArchive(AbcCoreHDF5::ReadArchive(), filepath, ErrorHandler::kThrowPolicy);
|
||||
ABC_SAFE_CALL_END
|
||||
|
||||
if (archive) {
|
||||
if (info_level >= ABC_INFO_BASIC)
|
||||
printf("%s", abc_archive_info(archive, info_level).c_str());
|
||||
|
||||
read_archive(scene, archive, filepath);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
36
intern/cycles/app/cycles_alembic.h
Normal file
36
intern/cycles/app/cycles_alembic.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2015 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __CYCLES_ALEMBIC_H__
|
||||
#define __CYCLES_ALEMBIC_H__
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class Scene;
|
||||
|
||||
enum AbcArchiveInfoLevel {
|
||||
ABC_INFO_NONE = 0,
|
||||
ABC_INFO_BASIC,
|
||||
ABC_INFO_OBJECTS,
|
||||
ABC_INFO_PROPERTIES,
|
||||
};
|
||||
|
||||
void abc_read_ogawa_file(Scene *scene, const char *filepath, AbcArchiveInfoLevel info_level = ABC_INFO_NONE);
|
||||
void abc_read_hdf5_file(Scene *scene, const char *filepath, AbcArchiveInfoLevel info_level = ABC_INFO_NONE);
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __CYCLES_XML_H__ */
|
@@ -37,13 +37,23 @@
|
||||
#endif
|
||||
|
||||
#include "cycles_xml.h"
|
||||
#ifdef WITH_ALEMBIC
|
||||
#include "cycles_alembic.h"
|
||||
#endif
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
enum FileType {
|
||||
FILETYPE_XML = 0,
|
||||
FILETYPE_ABC_HDF5,
|
||||
FILETYPE_ABC_OGAWA,
|
||||
};
|
||||
|
||||
struct Options {
|
||||
Session *session;
|
||||
Scene *scene;
|
||||
string filepath;
|
||||
FileType filetype;
|
||||
int width, height;
|
||||
SceneParams scene_params;
|
||||
SessionParams session_params;
|
||||
@@ -120,8 +130,22 @@ static void scene_init()
|
||||
{
|
||||
options.scene = new Scene(options.scene_params, options.session_params.device);
|
||||
|
||||
/* Read XML */
|
||||
xml_read_file(options.scene, options.filepath.c_str());
|
||||
/* Read file */
|
||||
switch (options.filetype) {
|
||||
case FILETYPE_XML:
|
||||
xml_read_file(options.scene, options.filepath.c_str());
|
||||
break;
|
||||
#ifdef WITH_ALEMBIC
|
||||
case FILETYPE_ABC_OGAWA:
|
||||
abc_read_ogawa_file(options.scene, options.filepath.c_str());
|
||||
break;
|
||||
case FILETYPE_ABC_HDF5:
|
||||
abc_read_hdf5_file(options.scene, options.filepath.c_str());
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Camera width/height override? */
|
||||
if (!(options.width == 0 || options.height == 0)) {
|
||||
@@ -335,6 +359,16 @@ static void options_parse(int argc, const char **argv)
|
||||
/* shading system */
|
||||
string ssname = "svm";
|
||||
|
||||
/* input file type */
|
||||
string filetypes = "auto, xml";
|
||||
#ifdef WITH_ALEMBIC
|
||||
filetypes += ", alembic_ogawa";
|
||||
#ifdef WITH_HDF5
|
||||
filetypes += ", alembic_hdf5";
|
||||
#endif
|
||||
#endif
|
||||
string filetype = "auto";
|
||||
|
||||
/* parse options */
|
||||
ArgParse ap;
|
||||
bool help = false, debug = false;
|
||||
@@ -350,6 +384,7 @@ static void options_parse(int argc, const char **argv)
|
||||
"--quiet", &options.quiet, "In background mode, don't print progress messages",
|
||||
"--samples %d", &options.session_params.samples, "Number of samples to render",
|
||||
"--output %s", &options.session_params.output_path, "File path to write output image",
|
||||
"--filetype %s", &filetype, ("File type: " + filetypes).c_str(),
|
||||
"--threads %d", &options.session_params.threads, "CPU Rendering Threads",
|
||||
"--width %d", &options.width, "Window width in pixel",
|
||||
"--height %d", &options.height, "Window height in pixel",
|
||||
@@ -394,6 +429,21 @@ static void options_parse(int argc, const char **argv)
|
||||
else if(ssname == "svm")
|
||||
options.scene_params.shadingsystem = SHADINGSYSTEM_SVM;
|
||||
|
||||
if(filetype == "auto") {
|
||||
string extension = options.filepath.substr(options.filepath.find_last_of(".") + 1);
|
||||
|
||||
if (extension == "xml")
|
||||
options.filetype = FILETYPE_XML;
|
||||
else if (extension == "abc")
|
||||
options.filetype = FILETYPE_ABC_OGAWA;
|
||||
}
|
||||
else if(filetype == "xml")
|
||||
options.filetype = FILETYPE_XML;
|
||||
else if(filetype == "alembic_ogawa")
|
||||
options.filetype = FILETYPE_ABC_OGAWA;
|
||||
else if(filetype == "alembic_hdf5")
|
||||
options.filetype = FILETYPE_ABC_HDF5;
|
||||
|
||||
#ifndef WITH_CYCLES_STANDALONE_GUI
|
||||
options.session_params.background = true;
|
||||
#endif
|
||||
|
@@ -42,6 +42,9 @@
|
||||
#include "util_xml.h"
|
||||
|
||||
#include "cycles_xml.h"
|
||||
#ifdef WITH_ALEMBIC
|
||||
#include "cycles_alembic.h"
|
||||
#endif
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
@@ -1109,6 +1112,25 @@ static void xml_read_state(XMLReadState& state, pugi::xml_node node)
|
||||
state.displacement_method = Mesh::DISPLACE_BOTH;
|
||||
}
|
||||
|
||||
/* Alembic */
|
||||
static void xml_read_alembic(const XMLReadState& state, pugi::xml_node node)
|
||||
{
|
||||
#ifdef WITH_ALEMBIC
|
||||
string filepath;
|
||||
|
||||
if(xml_read_string(&filepath, node, "file")) {
|
||||
filepath = path_join(state.base, filepath);
|
||||
|
||||
if(xml_equal_string(node, "type", "hdf5"))
|
||||
abc_read_hdf5_file(state.scene, filepath.c_str(), ABC_INFO_BASIC);
|
||||
else if(xml_equal_string(node, "type", "ogawa"))
|
||||
abc_read_ogawa_file(state.scene, filepath.c_str(), ABC_INFO_BASIC);
|
||||
else
|
||||
abc_read_ogawa_file(state.scene, filepath.c_str(), ABC_INFO_BASIC); /* default */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Scene */
|
||||
|
||||
static void xml_read_include(const XMLReadState& state, const string& src);
|
||||
@@ -1158,6 +1180,9 @@ static void xml_read_scene(const XMLReadState& state, pugi::xml_node scene_node)
|
||||
if(xml_read_string(&src, node, "src"))
|
||||
xml_read_include(state, src);
|
||||
}
|
||||
else if(string_iequals(node.name(), "alembic")) {
|
||||
xml_read_alembic(state, node);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "Unknown node \"%s\".\n", node.name());
|
||||
}
|
||||
|
@@ -587,8 +587,10 @@ static void create_subd_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, PointerR
|
||||
|
||||
/* Sync */
|
||||
|
||||
Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tris)
|
||||
Mesh *BlenderSync::sync_mesh(BL::Object b_parent, bool object_updated, bool hide_tris, BL::DupliObject b_dupli_ob)
|
||||
{
|
||||
BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent);
|
||||
|
||||
/* When viewport display is not needed during render we can force some
|
||||
* caches to be releases from blender side in order to reduce peak memory
|
||||
* footprint during synchronization process.
|
||||
@@ -599,7 +601,6 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
|
||||
|
||||
/* test if we can instance or if the object is modified */
|
||||
BL::ID b_ob_data = b_ob.data();
|
||||
BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob_data;
|
||||
BL::Material material_override = render_layer.material_override;
|
||||
|
||||
/* find shader indices */
|
||||
@@ -624,7 +625,21 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
|
||||
bool use_mesh_geometry = render_layer.use_surfaces || render_layer.use_hair;
|
||||
Mesh *mesh;
|
||||
|
||||
if(!mesh_map.sync(&mesh, key)) {
|
||||
bool need_update;
|
||||
bool use_dupli_override = b_dupli_ob && b_parent.cache_library() && b_parent.use_dupli_cache_read();
|
||||
if (use_dupli_override) {
|
||||
/* if a dupli override (cached data) is used, identify the mesh by object and parent together,
|
||||
* so that individual per-dupli overrides are possible.
|
||||
*/
|
||||
MeshKey key = MeshKey(b_parent, b_ob);
|
||||
need_update = mesh_map.sync(&mesh, b_parent, PointerRNA_NULL, key);
|
||||
}
|
||||
else {
|
||||
BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob_data;
|
||||
need_update = mesh_map.sync(&mesh, key);
|
||||
}
|
||||
|
||||
if(!need_update) {
|
||||
/* if transform was applied to mesh, need full update */
|
||||
if(object_updated && mesh->transform_applied);
|
||||
/* test if shaders changed, these can be object level so mesh
|
||||
@@ -675,7 +690,9 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
|
||||
b_ob.update_from_editmode();
|
||||
|
||||
bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED);
|
||||
BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, b_scene, true, !preview, need_undeformed);
|
||||
BL::Mesh b_mesh = (b_dupli_ob && b_parent)?
|
||||
dupli_to_mesh(b_data, b_scene, b_parent, b_dupli_ob, !preview, need_undeformed):
|
||||
object_to_mesh(b_data, b_ob, b_scene, true, !preview, need_undeformed);
|
||||
|
||||
if(b_mesh) {
|
||||
if(render_layer.use_surfaces && !hide_tris) {
|
||||
|
@@ -280,7 +280,10 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P
|
||||
bool use_holdout = (layer_flag & render_layer.holdout_layer) != 0;
|
||||
|
||||
/* mesh sync */
|
||||
object->mesh = sync_mesh(b_ob, object_updated, hide_tris);
|
||||
if (b_dupli_ob)
|
||||
object->mesh = sync_mesh(b_parent, object_updated, hide_tris, b_dupli_ob);
|
||||
else
|
||||
object->mesh = sync_mesh(b_ob, object_updated, hide_tris);
|
||||
|
||||
/* special case not tracked by object update flags */
|
||||
|
||||
|
@@ -83,7 +83,7 @@ private:
|
||||
void sync_curve_settings();
|
||||
|
||||
void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree);
|
||||
Mesh *sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tris);
|
||||
Mesh *sync_mesh(BL::Object b_parent, bool object_updated, bool hide_tris, BL::DupliObject b_dupli_ob = PointerRNA_NULL);
|
||||
void sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool motion, int time_index = 0);
|
||||
Object *sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob,
|
||||
Transform& tfm, uint layer_flag, float motion_time, bool hide_tris);
|
||||
@@ -108,7 +108,7 @@ private:
|
||||
|
||||
id_map<void*, Shader> shader_map;
|
||||
id_map<ObjectKey, Object> object_map;
|
||||
id_map<void*, Mesh> mesh_map;
|
||||
id_map<MeshKey, Mesh> mesh_map;
|
||||
id_map<ObjectKey, Light> light_map;
|
||||
id_map<ParticleSystemKey, ParticleSystem> particle_system_map;
|
||||
set<Mesh*> mesh_synced;
|
||||
|
@@ -52,6 +52,18 @@ static inline BL::Mesh object_to_mesh(BL::BlendData data, BL::Object object, BL:
|
||||
return me;
|
||||
}
|
||||
|
||||
static inline BL::Mesh dupli_to_mesh(BL::BlendData data, BL::Scene scene, BL::Object parent, BL::DupliObject dob, bool render, bool calc_undeformed)
|
||||
{
|
||||
BL::Mesh me = data.meshes.new_from_dupli(scene, parent, dob, (render)? 2: 1, false, calc_undeformed);
|
||||
if ((bool)me) {
|
||||
if (me.use_auto_smooth()) {
|
||||
me.calc_normals_split();
|
||||
}
|
||||
me.calc_tessface(true);
|
||||
}
|
||||
return me;
|
||||
}
|
||||
|
||||
static inline void colorramp_to_array(BL::ColorRamp ramp, float4 *data, int size)
|
||||
{
|
||||
for(int i = 0; i < size; i++) {
|
||||
@@ -568,6 +580,36 @@ struct ObjectKey {
|
||||
}
|
||||
};
|
||||
|
||||
/* Mesh Key */
|
||||
|
||||
struct MeshKey {
|
||||
void *parent;
|
||||
void *mesh;
|
||||
|
||||
MeshKey(void *mesh_)
|
||||
: parent(NULL), mesh(mesh_)
|
||||
{
|
||||
}
|
||||
|
||||
MeshKey(void *parent_, void *mesh_)
|
||||
: parent(parent_), mesh(mesh_)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator<(const MeshKey& k) const
|
||||
{
|
||||
if(mesh < k.mesh) {
|
||||
return true;
|
||||
}
|
||||
else if(mesh == k.mesh) {
|
||||
return parent < k.parent;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/* Particle System Key */
|
||||
|
||||
struct ParticleSystemKey {
|
||||
|
@@ -30,7 +30,7 @@ if(NOT CYCLES_STANDALONE_REPOSITORY)
|
||||
set(GLEW_INCLUDE_DIR "${GLEW_INCLUDE_PATH}")
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
|
||||
if(WITH_CYCLES_STANDALONE)
|
||||
set(CYCLES_APP_GLEW_LIBRARY ${BLENDER_GLEW_LIBRARIES})
|
||||
endif()
|
||||
|
||||
|
@@ -18,7 +18,7 @@
|
||||
#define __UTIL_MAP_H__
|
||||
|
||||
#include <map>
|
||||
#include <boost/tr1/unordered_map.hpp>
|
||||
#include <tr1/unordered_map>
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
|
@@ -169,6 +169,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
||||
sub.active = md.use_random_order
|
||||
sub.prop(md, "seed")
|
||||
|
||||
def CACHE(self, layout, ob, md):
|
||||
pass
|
||||
|
||||
def MESH_CACHE(self, layout, ob, md):
|
||||
layout.prop(md, "cache_format")
|
||||
layout.prop(md, "filepath")
|
||||
|
@@ -259,9 +259,109 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel):
|
||||
col.prop(obj, "color", text="")
|
||||
|
||||
|
||||
# XXX temporary solution
|
||||
bpy.types.CacheLibrary.filter_string = \
|
||||
bpy.props.StringProperty(
|
||||
name="Filter Object Name",
|
||||
description="Filter cache library objects by name",
|
||||
)
|
||||
bpy.types.CacheLibrary.filter_types = \
|
||||
bpy.props.EnumProperty(
|
||||
name="Filter Item Type",
|
||||
description="Filter cache library items by type",
|
||||
options={'ENUM_FLAG'},
|
||||
items=[ (e.identifier, e.name, e.description, e.icon, 2**i) for i, e in enumerate(bpy.types.CacheItem.bl_rna.properties['type'].enum_items) ],
|
||||
default=set( e.identifier for e in bpy.types.CacheItem.bl_rna.properties['type'].enum_items ),
|
||||
)
|
||||
|
||||
def cachelib_objects(cachelib, group):
|
||||
if not cachelib or not group:
|
||||
return []
|
||||
|
||||
filter_string = cachelib.filter_string.lower()
|
||||
if filter_string:
|
||||
return filter(lambda ob: filter_string in ob.name.lower(), group.objects)
|
||||
else:
|
||||
return group.objects
|
||||
|
||||
# Yields (item, type, index, enabled)
|
||||
# Note that item can be None when not included in the cache yet
|
||||
def cachelib_object_items(cachelib, ob):
|
||||
filter_types = cachelib.filter_types
|
||||
|
||||
def items_desc():
|
||||
yield 'OBJECT', -1
|
||||
|
||||
if (ob.type == 'MESH'):
|
||||
yield 'DERIVED_MESH', -1
|
||||
|
||||
for index, psys in enumerate(ob.particle_systems):
|
||||
if psys.settings.type == 'EMITTER':
|
||||
yield 'PARTICLES', index
|
||||
if psys.settings.type == 'HAIR':
|
||||
yield 'HAIR', index
|
||||
yield 'HAIR_PATHS', index
|
||||
|
||||
for item_type, item_index in items_desc():
|
||||
item = cachelib.cache_item_find(ob, item_type, item_index)
|
||||
|
||||
show = False
|
||||
enable = False
|
||||
# always show existing items
|
||||
if item and item.enabled:
|
||||
show = True
|
||||
enable = True
|
||||
# always show selected types
|
||||
elif item_type in filter_types:
|
||||
show = True
|
||||
enable = True
|
||||
# special case: OBJECT type used as top level, show but disable
|
||||
elif item_type == 'OBJECT':
|
||||
show = True
|
||||
enable = False
|
||||
|
||||
if show:
|
||||
yield item, item_type, item_index, enable
|
||||
|
||||
class OBJECT_PT_duplication(ObjectButtonsPanel, Panel):
|
||||
bl_label = "Duplication"
|
||||
|
||||
def draw_cachelib(self, context, layout, ob, cachelib, objects):
|
||||
col = layout.column(align=True)
|
||||
colrow = col.row(align=True)
|
||||
colrow.label("Archive:")
|
||||
props = colrow.operator("cachelibrary.archive_info", text="", icon='QUESTION')
|
||||
props.use_stdout = True
|
||||
props.use_popup = True
|
||||
props.use_clipboard = True
|
||||
col.prop(cachelib, "filepath", text="")
|
||||
|
||||
row = col.row(align=True)
|
||||
row.prop(ob, "use_dupli_cache_read", text="Read", toggle=True)
|
||||
row.prop(ob, "use_dupli_cache_write", text="Write", toggle=True)
|
||||
col.operator("cachelibrary.bake")
|
||||
row = col.row(align=True)
|
||||
row.prop(cachelib, "eval_mode", toggle=True, expand=True)
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.label("Filter:")
|
||||
row.prop(cachelib, "filter_types", icon_only=True, toggle=True)
|
||||
row.prop(cachelib, "filter_string", icon='VIEWZOOM', text="")
|
||||
|
||||
first = True
|
||||
for ob in objects:
|
||||
if not any(cachelib_object_items(cachelib, ob)):
|
||||
continue
|
||||
|
||||
if first:
|
||||
layout.separator()
|
||||
first = False
|
||||
|
||||
for item, item_type, item_index, enable in cachelib_object_items(cachelib, ob):
|
||||
row = layout.row(align=True)
|
||||
row.alignment = 'LEFT'
|
||||
row.template_cache_library_item(cachelib, ob, item_type, item_index, enable)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
@@ -294,6 +394,12 @@ class OBJECT_PT_duplication(ObjectButtonsPanel, Panel):
|
||||
|
||||
elif ob.dupli_type == 'GROUP':
|
||||
layout.prop(ob, "dupli_group", text="Group")
|
||||
row = layout.row(align=True)
|
||||
row.template_ID(ob, "cache_library", new="cachelibrary.new")
|
||||
|
||||
if ob.cache_library:
|
||||
cache_objects = cachelib_objects(ob.cache_library, ob.dupli_group)
|
||||
self.draw_cachelib(context, layout, ob, ob.cache_library, cache_objects)
|
||||
|
||||
|
||||
class OBJECT_PT_relations_extras(ObjectButtonsPanel, Panel):
|
||||
|
@@ -31,6 +31,7 @@ set(SRC_DNA_INC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_armature_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_cache_library_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_color_types.h
|
||||
@@ -108,6 +109,7 @@ add_subdirectory(gpu)
|
||||
add_subdirectory(imbuf)
|
||||
add_subdirectory(nodes)
|
||||
add_subdirectory(modifiers)
|
||||
add_subdirectory(pointcache)
|
||||
add_subdirectory(makesdna)
|
||||
add_subdirectory(makesrna)
|
||||
|
||||
|
@@ -43,7 +43,8 @@ SConscript(['avi/SConscript',
|
||||
'ikplugin/SConscript',
|
||||
'physics/SConscript',
|
||||
'windowmanager/SConscript',
|
||||
'blenfont/SConscript'])
|
||||
'blenfont/SConscript',
|
||||
'pointcache/SConscript'])
|
||||
|
||||
makesrna = SConscript('makesrna/SConscript')
|
||||
|
||||
|
@@ -146,6 +146,7 @@ const char *BLF_translate_do_new_dataname(const char *msgctxt, const char *msgid
|
||||
#define BLF_I18NCONTEXT_ID_ACTION "Action"
|
||||
#define BLF_I18NCONTEXT_ID_ARMATURE "Armature"
|
||||
#define BLF_I18NCONTEXT_ID_BRUSH "Brush"
|
||||
#define BLF_I18NCONTEXT_ID_CACHELIBRARY "CacheLibrary"
|
||||
#define BLF_I18NCONTEXT_ID_CAMERA "Camera"
|
||||
#define BLF_I18NCONTEXT_ID_CURVE "Curve"
|
||||
#define BLF_I18NCONTEXT_ID_FREESTYLELINESTYLE "FreestyleLineStyle"
|
||||
|
@@ -42,6 +42,11 @@ struct bAnimVizSettings;
|
||||
struct bMotionPath;
|
||||
struct bPoseChannel;
|
||||
struct ReportList;
|
||||
struct GHash;
|
||||
struct DupliCache;
|
||||
struct DupliObject;
|
||||
struct DupliObjectData;
|
||||
struct DerivedMesh;
|
||||
|
||||
/* ---------------------------------------------------- */
|
||||
/* Animation Visualization */
|
||||
@@ -66,11 +71,26 @@ int where_on_path(struct Object *ob, float ctime, float vec[4], float dir[3], fl
|
||||
/* ---------------------------------------------------- */
|
||||
/* Dupli-Geometry */
|
||||
|
||||
struct ListBase *object_duplilist_ex(struct EvaluationContext *eval_ctx, struct Scene *sce, struct Object *ob, bool update);
|
||||
struct ListBase *object_duplilist(struct EvaluationContext *eval_ctx, struct Scene *sce, struct Object *ob);
|
||||
struct ListBase *object_duplilist_ex(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, bool update);
|
||||
struct ListBase *object_duplilist(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
|
||||
struct ListBase *group_duplilist_ex(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Group *group, bool update);
|
||||
struct ListBase *group_duplilist(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Group *group);
|
||||
void free_object_duplilist(struct ListBase *lb);
|
||||
int count_duplilist(struct Object *ob);
|
||||
|
||||
void BKE_object_dupli_cache_update(struct Scene *scene, struct Object *ob, struct EvaluationContext *eval_ctx, float frame);
|
||||
void BKE_object_dupli_cache_clear(struct Object *ob);
|
||||
void BKE_object_dupli_cache_free(struct Object *ob);
|
||||
bool BKE_object_dupli_cache_contains(struct Object *ob, struct Object *other);
|
||||
struct DupliObjectData *BKE_dupli_cache_find_data(struct DupliCache *dupcache, struct Object *ob);
|
||||
|
||||
void BKE_dupli_object_data_init(struct DupliObjectData *data, struct Object *ob, struct DerivedMesh *dm);
|
||||
/* does not free data itself */
|
||||
void BKE_dupli_object_data_clear(struct DupliObjectData *data);
|
||||
|
||||
struct DupliObjectData *BKE_dupli_cache_add_mesh(struct DupliCache *dupcache, struct Object *ob, struct DerivedMesh *dm);
|
||||
void BKE_dupli_cache_add_instance(struct DupliCache *dupcache, float obmat[4][4], struct DupliObjectData *data);
|
||||
|
||||
typedef struct DupliExtraData {
|
||||
float obmat[4][4];
|
||||
unsigned int lay;
|
||||
|
109
source/blender/blenkernel/BKE_cache_library.h
Normal file
109
source/blender/blenkernel/BKE_cache_library.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* ***** 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) 2015 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Lukas Toenne
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef __BKE_CACHE_LIBRARY_H__
|
||||
#define __BKE_CACHE_LIBRARY_H__
|
||||
|
||||
/** \file BKE_cache_library.h
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include "DNA_cache_library_types.h"
|
||||
|
||||
struct ListBase;
|
||||
struct Main;
|
||||
struct Object;
|
||||
struct Scene;
|
||||
struct EvaluationContext;
|
||||
struct ParticleSystem;
|
||||
struct DupliCache;
|
||||
struct DupliObjectData;
|
||||
|
||||
struct ClothModifierData;
|
||||
|
||||
struct CacheLibrary *BKE_cache_library_add(struct Main *bmain, const char *name);
|
||||
struct CacheLibrary *BKE_cache_library_copy(struct CacheLibrary *cachelib);
|
||||
void BKE_cache_library_free(struct CacheLibrary *cachelib);
|
||||
void BKE_cache_library_unlink(struct CacheLibrary *cachelib);
|
||||
|
||||
void BKE_cache_library_make_object_list(struct Main *bmain, struct CacheLibrary *cachelib, struct ListBase *lb);
|
||||
|
||||
typedef struct CacheLibraryObjectsIterator {
|
||||
ListBase objects;
|
||||
LinkData *cur;
|
||||
} CacheLibraryObjectsIterator;
|
||||
|
||||
void BKE_object_cache_iter_init(CacheLibraryObjectsIterator *iter, struct CacheLibrary *cachelib);
|
||||
bool BKE_object_cache_iter_valid(CacheLibraryObjectsIterator *iter);
|
||||
void BKE_object_cache_iter_next(CacheLibraryObjectsIterator *iter);
|
||||
void BKE_object_cache_iter_end(CacheLibraryObjectsIterator *iter);
|
||||
struct Object *BKE_object_cache_iter_get(CacheLibraryObjectsIterator *iter);
|
||||
|
||||
typedef struct CacheLibraryItemsIterator {
|
||||
struct Object *ob;
|
||||
struct CacheItem *items;
|
||||
int totitems;
|
||||
|
||||
struct CacheItem *cur;
|
||||
} CacheLibraryItemsIterator;
|
||||
|
||||
void BKE_cache_item_iter_init(CacheLibraryItemsIterator *iter, struct Object *ob);
|
||||
bool BKE_cache_item_iter_valid(CacheLibraryItemsIterator *iter);
|
||||
void BKE_cache_item_iter_next(CacheLibraryItemsIterator *iter);
|
||||
void BKE_cache_item_iter_end(CacheLibraryItemsIterator *iter);
|
||||
|
||||
#if 0
|
||||
typedef void (*CacheGroupWalkFunc)(void *userdata, struct CacheLibrary *cachelib, const struct CacheItemPath *path);
|
||||
void BKE_cache_library_walk(struct CacheLibrary *cachelib, CacheGroupWalkFunc walk, void *userdata);
|
||||
#endif
|
||||
|
||||
const char *BKE_cache_item_name_prefix(int type);
|
||||
void BKE_cache_item_name(struct Object *ob, int type, int index, char *name);
|
||||
int BKE_cache_item_name_length(struct Object *ob, int type, int index);
|
||||
eCacheReadSampleResult BKE_cache_read_result(int ptc_result);
|
||||
|
||||
struct CacheItem *BKE_cache_library_find_item(struct CacheLibrary *cachelib, struct Object *ob, int type, int index);
|
||||
struct CacheItem *BKE_cache_library_add_item(struct CacheLibrary *cachelib, struct Object *ob, int type, int index);
|
||||
void BKE_cache_library_remove_item(struct CacheLibrary *cachelib, struct CacheItem *item);
|
||||
void BKE_cache_library_clear(struct CacheLibrary *cachelib);
|
||||
|
||||
bool BKE_cache_library_validate_item(struct CacheLibrary *cachelib, struct Object *ob, int type, int index);
|
||||
void BKE_cache_library_group_update(struct Main *bmain, struct CacheLibrary *cachelib);
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
bool BKE_cache_archive_path_test(const char *path, ID *id, Library *lib);
|
||||
void BKE_cache_archive_path(const char *path, ID *id, Library *lib, char *result, int max);
|
||||
|
||||
void BKE_cache_library_dag_recalc_tag(struct EvaluationContext *eval_ctx, struct Main *bmain);
|
||||
|
||||
bool BKE_cache_read_dupli_cache(struct Scene *scene, float frame, eCacheLibrary_EvalMode eval_mode,
|
||||
struct Group *dupgroup, struct DupliCache *dupcache, struct CacheLibrary *cachelib);
|
||||
bool BKE_cache_read_dupli_object(struct Scene *scene, float frame, eCacheLibrary_EvalMode eval_mode,
|
||||
struct Object *ob, struct DupliObjectData *data, struct CacheLibrary *cachelib);
|
||||
|
||||
#endif
|
@@ -71,7 +71,7 @@ void id_clear_lib_data(struct Main *bmain, struct ID *id);
|
||||
|
||||
struct ListBase *which_libbase(struct Main *mainlib, short type);
|
||||
|
||||
#define MAX_LIBARRAY 35
|
||||
#define MAX_LIBARRAY 36
|
||||
int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]);
|
||||
|
||||
void BKE_libblock_free(struct Main *bmain, void *idv);
|
||||
|
@@ -94,6 +94,7 @@ typedef struct Main {
|
||||
ListBase movieclip;
|
||||
ListBase mask;
|
||||
ListBase linestyle;
|
||||
ListBase cache_library;
|
||||
|
||||
char id_tag_update[256];
|
||||
|
||||
|
@@ -41,6 +41,7 @@ struct BLI_Stack;
|
||||
struct MemArena;
|
||||
struct BMEditMesh;
|
||||
struct BMesh;
|
||||
struct DupliObjectData;
|
||||
struct Main;
|
||||
struct Mesh;
|
||||
struct MPoly;
|
||||
@@ -135,6 +136,7 @@ void BKE_mesh_split_faces(struct Mesh *mesh);
|
||||
|
||||
struct Mesh *BKE_mesh_new_from_object(struct Main *bmain, struct Scene *sce, struct Object *ob,
|
||||
int apply_modifiers, int settings, int calc_tessface, int calc_undeformed);
|
||||
struct Mesh *BKE_mesh_new_from_dupli_data(struct Main *bmain, struct DupliObjectData *data, bool calc_tessface, bool calc_undeformed);
|
||||
|
||||
/* vertex level transformations & checks (no derived mesh) */
|
||||
|
||||
|
@@ -37,6 +37,7 @@ set(INC
|
||||
../modifiers
|
||||
../nodes
|
||||
../physics
|
||||
../pointcache
|
||||
../render/extern/include
|
||||
../../../intern/ghost
|
||||
../../../intern/guardedalloc
|
||||
@@ -75,6 +76,7 @@ set(SRC
|
||||
intern/brush.c
|
||||
intern/bullet.c
|
||||
intern/bvhutils.c
|
||||
intern/cache_library.c
|
||||
intern/camera.c
|
||||
intern/cdderivedmesh.c
|
||||
intern/cloth.c
|
||||
@@ -193,6 +195,7 @@ set(SRC
|
||||
BKE_brush.h
|
||||
BKE_bullet.h
|
||||
BKE_bvhutils.h
|
||||
BKE_cache_library.h
|
||||
BKE_camera.h
|
||||
BKE_ccg.h
|
||||
BKE_cdderivedmesh.h
|
||||
|
@@ -66,6 +66,7 @@ incs = [
|
||||
'../modifiers',
|
||||
'../nodes',
|
||||
'../physics',
|
||||
'../pointcache',
|
||||
'../render/extern/include',
|
||||
'../windowmanager',
|
||||
env['BF_ZLIB_INC'],
|
||||
|
@@ -482,10 +482,6 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
|
||||
BPATH_TRAVERSE_POINTCACHE(smd->domain->ptcaches[0]);
|
||||
}
|
||||
}
|
||||
else if (md->type == eModifierType_Cloth) {
|
||||
ClothModifierData *clmd = (ClothModifierData *) md;
|
||||
BPATH_TRAVERSE_POINTCACHE(clmd->ptcaches);
|
||||
}
|
||||
else if (md->type == eModifierType_Ocean) {
|
||||
OceanModifierData *omd = (OceanModifierData *) md;
|
||||
rewrite_path_fixed(omd->cachepath, visit_cb, absbase, bpath_user_data);
|
||||
|
746
source/blender/blenkernel/intern/cache_library.c
Normal file
746
source/blender/blenkernel/intern/cache_library.c
Normal file
@@ -0,0 +1,746 @@
|
||||
/*
|
||||
* ***** 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) 2015 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Lukas Toenne
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/blenkernel/intern/cache_library.c
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_fileops.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_path_util.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_cache_library_types.h"
|
||||
#include "DNA_group_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_particle_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BKE_anim.h"
|
||||
#include "BKE_cache_library.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_group.h"
|
||||
#include "BKE_library.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_modifier.h"
|
||||
|
||||
#include "PTC_api.h"
|
||||
|
||||
CacheLibrary *BKE_cache_library_add(Main *bmain, const char *name)
|
||||
{
|
||||
CacheLibrary *cachelib;
|
||||
char basename[MAX_NAME];
|
||||
|
||||
cachelib = BKE_libblock_alloc(bmain, ID_CL, name);
|
||||
|
||||
BLI_strncpy(basename, cachelib->id.name+2, sizeof(basename));
|
||||
BLI_filename_make_safe(basename);
|
||||
BLI_snprintf(cachelib->filepath, sizeof(cachelib->filepath), "//cache/%s.%s", basename, PTC_get_default_archive_extension());
|
||||
|
||||
cachelib->eval_mode = CACHE_LIBRARY_EVAL_REALTIME | CACHE_LIBRARY_EVAL_RENDER;
|
||||
|
||||
return cachelib;
|
||||
}
|
||||
|
||||
CacheLibrary *BKE_cache_library_copy(CacheLibrary *cachelib)
|
||||
{
|
||||
CacheLibrary *cachelibn;
|
||||
|
||||
cachelibn = BKE_libblock_copy(&cachelib->id);
|
||||
|
||||
BLI_duplicatelist(&cachelibn->items, &cachelib->items);
|
||||
/* hash table will be rebuilt when needed */
|
||||
cachelibn->items_hash = NULL;
|
||||
|
||||
if (cachelib->id.lib) {
|
||||
BKE_id_lib_local_paths(G.main, cachelib->id.lib, &cachelibn->id);
|
||||
}
|
||||
|
||||
return cachelibn;
|
||||
}
|
||||
|
||||
void BKE_cache_library_free(CacheLibrary *cachelib)
|
||||
{
|
||||
BLI_freelistN(&cachelib->items);
|
||||
if (cachelib->items_hash)
|
||||
BLI_ghash_free(cachelib->items_hash, NULL, NULL);
|
||||
}
|
||||
|
||||
void BKE_cache_library_unlink(CacheLibrary *UNUSED(cachelib))
|
||||
{
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
static void cache_library_tag_recursive(int level, Object *ob)
|
||||
{
|
||||
if (level > MAX_CACHE_GROUP_LEVEL)
|
||||
return;
|
||||
|
||||
/* dupli group recursion */
|
||||
if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
|
||||
GroupObject *gob;
|
||||
|
||||
for (gob = ob->dup_group->gobject.first; gob; gob = gob->next) {
|
||||
if (!(ob->id.flag & LIB_DOIT)) {
|
||||
ob->id.flag |= LIB_DOIT;
|
||||
|
||||
cache_library_tag_recursive(level + 1, gob->ob);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* tag IDs contained in the cache library group */
|
||||
void BKE_cache_library_make_object_list(Main *bmain, CacheLibrary *cachelib, ListBase *lb)
|
||||
{
|
||||
if (cachelib) {
|
||||
Object *ob;
|
||||
LinkData *link;
|
||||
|
||||
/* clear tags */
|
||||
BKE_main_id_tag_idcode(bmain, ID_OB, false);
|
||||
|
||||
for (ob = bmain->object.first; ob; ob = ob->id.next) {
|
||||
if (ob->cache_library == cachelib) {
|
||||
cache_library_tag_recursive(0, ob);
|
||||
}
|
||||
}
|
||||
|
||||
/* store object pointers in the list */
|
||||
for (ob = bmain->object.first; ob; ob = ob->id.next) {
|
||||
if (ob->id.flag & LIB_DOIT) {
|
||||
link = MEM_callocN(sizeof(LinkData), "cache library ID link");
|
||||
link->data = ob;
|
||||
BLI_addtail(lb, link);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_object_cache_iter_init(CacheLibraryObjectsIterator *iter, CacheLibrary *cachelib)
|
||||
{
|
||||
BLI_listbase_clear(&iter->objects);
|
||||
BKE_cache_library_make_object_list(G.main, cachelib, &iter->objects);
|
||||
|
||||
iter->cur = iter->objects.first;
|
||||
}
|
||||
|
||||
bool BKE_object_cache_iter_valid(CacheLibraryObjectsIterator *iter)
|
||||
{
|
||||
return iter->cur != NULL;
|
||||
}
|
||||
|
||||
void BKE_object_cache_iter_next(CacheLibraryObjectsIterator *iter)
|
||||
{
|
||||
iter->cur = iter->cur->next;
|
||||
}
|
||||
|
||||
Object *BKE_object_cache_iter_get(CacheLibraryObjectsIterator *iter)
|
||||
{
|
||||
return iter->cur->data;
|
||||
}
|
||||
|
||||
void BKE_object_cache_iter_end(CacheLibraryObjectsIterator *iter)
|
||||
{
|
||||
BLI_freelistN(&iter->objects);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
static int cache_count_items(Object *ob) {
|
||||
ParticleSystem *psys;
|
||||
int totitem = 1; /* base object */
|
||||
|
||||
if (ob->type == OB_MESH)
|
||||
totitem += 1; /* derived mesh */
|
||||
|
||||
for (psys = ob->particlesystem.first; psys; psys = psys->next) {
|
||||
if (psys->part->type == PART_HAIR) {
|
||||
totitem += 2; /* hair and hair paths */
|
||||
}
|
||||
else {
|
||||
totitem += 1; /* particles */
|
||||
}
|
||||
}
|
||||
|
||||
return totitem;
|
||||
}
|
||||
|
||||
static void cache_make_items(Object *ob, CacheItem *item) {
|
||||
ParticleSystem *psys;
|
||||
int i;
|
||||
|
||||
/* base object */
|
||||
item->ob = ob;
|
||||
item->type = CACHE_TYPE_OBJECT;
|
||||
item->index = -1;
|
||||
++item;
|
||||
|
||||
if (ob->type == OB_MESH) {
|
||||
/* derived mesh */
|
||||
item->ob = ob;
|
||||
item->type = CACHE_TYPE_DERIVED_MESH;
|
||||
item->index = -1;
|
||||
++item;
|
||||
}
|
||||
|
||||
for (psys = ob->particlesystem.first, i = 0; psys; psys = psys->next, ++i) {
|
||||
if (psys->part->type == PART_HAIR) {
|
||||
/* hair */
|
||||
item->ob = ob;
|
||||
item->type = CACHE_TYPE_HAIR;
|
||||
item->index = i;
|
||||
++item;
|
||||
|
||||
/* hair paths */
|
||||
item->ob = ob;
|
||||
item->type = CACHE_TYPE_HAIR_PATHS;
|
||||
item->index = i;
|
||||
++item;
|
||||
}
|
||||
else {
|
||||
/* hair paths */
|
||||
item->ob = ob;
|
||||
item->type = CACHE_TYPE_PARTICLES;
|
||||
item->index = i;
|
||||
++item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_cache_item_iter_init(CacheLibraryItemsIterator *iter, Object *ob)
|
||||
{
|
||||
iter->ob = ob;
|
||||
iter->totitems = cache_count_items(ob);
|
||||
iter->items = MEM_mallocN(sizeof(CacheItem) * iter->totitems, "object cache items");
|
||||
cache_make_items(ob, iter->items);
|
||||
|
||||
iter->cur = iter->items;
|
||||
}
|
||||
|
||||
bool BKE_cache_item_iter_valid(CacheLibraryItemsIterator *iter)
|
||||
{
|
||||
return (int)(iter->cur - iter->items) < iter->totitems;
|
||||
}
|
||||
|
||||
void BKE_cache_item_iter_next(CacheLibraryItemsIterator *iter)
|
||||
{
|
||||
++iter->cur;
|
||||
}
|
||||
|
||||
void BKE_cache_item_iter_end(CacheLibraryItemsIterator *iter)
|
||||
{
|
||||
if (iter->items)
|
||||
MEM_freeN(iter->items);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void cache_library_walk_recursive(CacheLibrary *cachelib, CacheGroupWalkFunc walk, void *userdata, int level, Object *ob)
|
||||
{
|
||||
CacheItemPath path;
|
||||
|
||||
if (level > MAX_CACHE_GROUP_LEVEL)
|
||||
return;
|
||||
|
||||
/* object dm */
|
||||
cache_path_object(&path, ob);
|
||||
walk(userdata, cachelib, &path);
|
||||
|
||||
/* dupli group recursion */
|
||||
if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
|
||||
GroupObject *gob;
|
||||
|
||||
for (gob = ob->dup_group->gobject.first; gob; gob = gob->next) {
|
||||
cache_library_walk_recursive(cachelib, walk, userdata, level + 1, gob->ob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_cache_library_walk(CacheLibrary *cachelib, CacheGroupWalkFunc walk, void *userdata)
|
||||
{
|
||||
if (cachelib && cachelib->group) {
|
||||
GroupObject *gob;
|
||||
|
||||
for (gob = cachelib->group->gobject.first; gob; gob = gob->next) {
|
||||
cache_library_walk_recursive(cachelib, walk, userdata, 0, gob->ob);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
BLI_INLINE unsigned int hash_int_2d(unsigned int kx, unsigned int ky)
|
||||
{
|
||||
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
|
||||
|
||||
uint a, b, c;
|
||||
|
||||
a = b = c = 0xdeadbeef + (2 << 2) + 13;
|
||||
a += kx;
|
||||
b += ky;
|
||||
|
||||
c ^= b; c -= rot(b,14);
|
||||
a ^= c; a -= rot(c,11);
|
||||
b ^= a; b -= rot(a,25);
|
||||
c ^= b; c -= rot(b,16);
|
||||
a ^= c; a -= rot(c,4);
|
||||
b ^= a; b -= rot(a,14);
|
||||
c ^= b; c -= rot(b,24);
|
||||
|
||||
return c;
|
||||
|
||||
#undef rot
|
||||
}
|
||||
|
||||
static unsigned int cache_item_hash(const void *key)
|
||||
{
|
||||
const CacheItem *item = key;
|
||||
unsigned int hash;
|
||||
|
||||
hash = BLI_ghashutil_inthash(item->type);
|
||||
|
||||
if (item->ob)
|
||||
hash = hash_int_2d(hash, BLI_ghashutil_ptrhash(item->ob));
|
||||
if (item->index >= 0)
|
||||
hash = hash_int_2d(hash, BLI_ghashutil_inthash(item->index));
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
static bool cache_item_cmp(const void *key_a, const void *key_b)
|
||||
{
|
||||
const CacheItem *item_a = key_a, *item_b = key_b;
|
||||
|
||||
if (item_a->type != item_b->type)
|
||||
return true;
|
||||
if (item_a->ob != item_b->ob)
|
||||
return true;
|
||||
if (item_a->index >= 0 || item_b->index >= 0) {
|
||||
if (item_a->index != item_b->index)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
BLI_INLINE void print_cachelib_items(CacheLibrary *cachelib)
|
||||
{
|
||||
CacheItem *item;
|
||||
int i;
|
||||
|
||||
printf("Cache Library %s:\n", cachelib->id.name+2);
|
||||
for (item = cachelib->items.first, i = 0; item; item = item->next, ++i) {
|
||||
printf(" Item %d: ob=%s, type=%d, index=%d, hash=%d\n", i, item->ob ? item->ob->id.name+2 : "!!!", item->type, item->index, cache_item_hash(item));
|
||||
}
|
||||
}
|
||||
|
||||
const char *BKE_cache_item_name_prefix(int type)
|
||||
{
|
||||
/* note: avoid underscores and the like here,
|
||||
* the prefixes must be unique and safe when combined with arbitrary strings!
|
||||
*/
|
||||
switch (type) {
|
||||
case CACHE_TYPE_OBJECT: return "OBJECT";
|
||||
case CACHE_TYPE_DERIVED_MESH: return "MESH";
|
||||
case CACHE_TYPE_HAIR: return "HAIR";
|
||||
case CACHE_TYPE_HAIR_PATHS: return "HAIRPATHS";
|
||||
case CACHE_TYPE_PARTICLES: return "PARTICLES";
|
||||
default: BLI_assert(false); return NULL; break;
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_cache_item_name(Object *ob, int type, int index, char *name)
|
||||
{
|
||||
if (index >= 0)
|
||||
sprintf(name, "%s_%s_%d", BKE_cache_item_name_prefix(type), ob->id.name+2, index);
|
||||
else
|
||||
sprintf(name, "%s_%s", BKE_cache_item_name_prefix(type), ob->id.name+2);
|
||||
}
|
||||
|
||||
int BKE_cache_item_name_length(Object *ob, int type, int index)
|
||||
{
|
||||
if (index >= 0)
|
||||
return snprintf(NULL, 0, "%s_%s_%d", BKE_cache_item_name_prefix(type), ob->id.name+2, index);
|
||||
else
|
||||
return snprintf(NULL, 0, "%s_%s", BKE_cache_item_name_prefix(type), ob->id.name+2);
|
||||
}
|
||||
|
||||
eCacheReadSampleResult BKE_cache_read_result(int ptc_result)
|
||||
{
|
||||
switch (ptc_result) {
|
||||
case PTC_READ_SAMPLE_INVALID: return CACHE_READ_SAMPLE_INVALID;
|
||||
case PTC_READ_SAMPLE_EARLY: return CACHE_READ_SAMPLE_EARLY;
|
||||
case PTC_READ_SAMPLE_LATE: return CACHE_READ_SAMPLE_LATE;
|
||||
case PTC_READ_SAMPLE_EXACT: return CACHE_READ_SAMPLE_EXACT;
|
||||
case PTC_READ_SAMPLE_INTERPOLATED: return CACHE_READ_SAMPLE_INTERPOLATED;
|
||||
default: BLI_assert(false); break; /* should never happen, enums out of sync? */
|
||||
}
|
||||
return CACHE_READ_SAMPLE_INVALID;
|
||||
}
|
||||
|
||||
static void cache_library_insert_item_hash(CacheLibrary *cachelib, CacheItem *item, bool replace)
|
||||
{
|
||||
CacheItem *exist = BLI_ghash_lookup(cachelib->items_hash, item);
|
||||
if (exist && replace) {
|
||||
BLI_remlink(&cachelib->items, exist);
|
||||
BLI_ghash_remove(cachelib->items_hash, item, NULL, NULL);
|
||||
MEM_freeN(exist);
|
||||
}
|
||||
if (!exist || replace)
|
||||
BLI_ghash_insert(cachelib->items_hash, item, item);
|
||||
}
|
||||
|
||||
/* make sure the items hash exists (lazy init after loading files) */
|
||||
static void cache_library_ensure_items_hash(CacheLibrary *cachelib)
|
||||
{
|
||||
CacheItem *item;
|
||||
|
||||
if (!cachelib->items_hash) {
|
||||
cachelib->items_hash = BLI_ghash_new(cache_item_hash, cache_item_cmp, "cache item hash");
|
||||
|
||||
for (item = cachelib->items.first; item; item = item->next) {
|
||||
cache_library_insert_item_hash(cachelib, item, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CacheItem *BKE_cache_library_find_item(CacheLibrary *cachelib, Object *ob, int type, int index)
|
||||
{
|
||||
CacheItem item;
|
||||
item.next = item.prev = NULL;
|
||||
item.ob = ob;
|
||||
item.type = type;
|
||||
item.index = index;
|
||||
|
||||
cache_library_ensure_items_hash(cachelib);
|
||||
|
||||
return BLI_ghash_lookup(cachelib->items_hash, &item);
|
||||
}
|
||||
|
||||
CacheItem *BKE_cache_library_add_item(CacheLibrary *cachelib, struct Object *ob, int type, int index)
|
||||
{
|
||||
CacheItem *item;
|
||||
|
||||
/* assert validity */
|
||||
BLI_assert(BKE_cache_library_validate_item(cachelib, ob, type, index));
|
||||
|
||||
cache_library_ensure_items_hash(cachelib);
|
||||
|
||||
item = BKE_cache_library_find_item(cachelib, ob, type, index);
|
||||
|
||||
if (!item) {
|
||||
item = MEM_callocN(sizeof(CacheItem), "cache library item");
|
||||
item->ob = ob;
|
||||
item->type = type;
|
||||
item->index = index;
|
||||
|
||||
BLI_addtail(&cachelib->items, item);
|
||||
cache_library_insert_item_hash(cachelib, item, false);
|
||||
|
||||
id_lib_extern((ID *)item->ob);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
void BKE_cache_library_remove_item(CacheLibrary *cachelib, CacheItem *item)
|
||||
{
|
||||
if (item) {
|
||||
if (cachelib->items_hash)
|
||||
BLI_ghash_remove(cachelib->items_hash, item, NULL, NULL);
|
||||
BLI_remlink(&cachelib->items, item);
|
||||
MEM_freeN(item);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_cache_library_clear(CacheLibrary *cachelib)
|
||||
{
|
||||
CacheItem *item, *item_next;
|
||||
|
||||
if (cachelib->items_hash)
|
||||
BLI_ghash_clear(cachelib->items_hash, NULL, NULL);
|
||||
|
||||
for (item = cachelib->items.first; item; item = item_next) {
|
||||
item_next = item->next;
|
||||
MEM_freeN(item);
|
||||
}
|
||||
BLI_listbase_clear(&cachelib->items);
|
||||
}
|
||||
|
||||
bool BKE_cache_library_validate_item(CacheLibrary *cachelib, Object *ob, int type, int index)
|
||||
{
|
||||
if (!cachelib)
|
||||
return false;
|
||||
|
||||
if (ELEM(type, CACHE_TYPE_DERIVED_MESH)) {
|
||||
if (ob->type != OB_MESH)
|
||||
return false;
|
||||
}
|
||||
else if (ELEM(type, CACHE_TYPE_PARTICLES, CACHE_TYPE_HAIR, CACHE_TYPE_HAIR_PATHS)) {
|
||||
ParticleSystem *psys = BLI_findlink(&ob->particlesystem, index);
|
||||
|
||||
if (!psys)
|
||||
return false;
|
||||
|
||||
if (ELEM(type, CACHE_TYPE_PARTICLES)) {
|
||||
if (psys->part->type != PART_EMITTER)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ELEM(type, CACHE_TYPE_HAIR, CACHE_TYPE_HAIR_PATHS)) {
|
||||
if (psys->part->type != PART_HAIR)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BKE_cache_library_group_update(Main *bmain, CacheLibrary *cachelib)
|
||||
{
|
||||
if (cachelib) {
|
||||
Object *ob;
|
||||
CacheItem *item, *item_next;
|
||||
|
||||
/* clear tags */
|
||||
BKE_main_id_tag_idcode(bmain, ID_OB, false);
|
||||
|
||||
for (ob = bmain->object.first; ob; ob = ob->id.next) {
|
||||
if (ob->cache_library == cachelib) {
|
||||
cache_library_tag_recursive(0, ob);
|
||||
}
|
||||
}
|
||||
|
||||
/* remove unused items */
|
||||
for (item = cachelib->items.first; item; item = item_next) {
|
||||
item_next = item->next;
|
||||
|
||||
if (!item->ob || !(item->ob->id.flag & LIB_DOIT)) {
|
||||
BKE_cache_library_remove_item(cachelib, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
#if 0
|
||||
typedef struct UpdateItemsData {
|
||||
CacheItem *cur;
|
||||
} UpdateItemsData;
|
||||
|
||||
static void cache_library_update_items_walk(void *userdata, CacheLibrary *cachelib)
|
||||
{
|
||||
UpdateItemsData *data = userdata;
|
||||
CacheItem *item;
|
||||
|
||||
if (data->cur) {
|
||||
item = data->cur;
|
||||
data->cur = data->cur->next;
|
||||
}
|
||||
else {
|
||||
item = MEM_callocN(sizeof(CacheItem), "cache library item");
|
||||
BLI_addtail(&cachelib->items, item);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_cache_library_update_items(CacheLibrary *cachelib)
|
||||
{
|
||||
UpdateItemsData data;
|
||||
|
||||
data.cur = cachelib->items.first;
|
||||
BKE_cache_library_walk(cachelib, cache_library_update_items_walk, &data);
|
||||
|
||||
/* truncate items list */
|
||||
if (data.cur) {
|
||||
cachelib->items.last = data.cur->prev;
|
||||
while (data.cur) {
|
||||
CacheItem *item = data.cur;
|
||||
data.cur = data.cur->next;
|
||||
|
||||
BLI_remlink(&cachelib->items, item);
|
||||
MEM_freeN(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
static const char *default_filename = "blendcache";
|
||||
|
||||
BLI_INLINE bool path_is_dirpath(const char *path)
|
||||
{
|
||||
/* last char is a slash? */
|
||||
return *(BLI_last_slash(path) + 1) == '\0';
|
||||
}
|
||||
|
||||
bool BKE_cache_archive_path_test(const char *path, ID *UNUSED(id), Library *lib)
|
||||
{
|
||||
if (BLI_path_is_rel(path)) {
|
||||
if (!(G.relbase_valid || lib))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
void BKE_cache_archive_path(const char *path, ID *id, Library *lib, char *result, int max)
|
||||
{
|
||||
char abspath[FILE_MAX];
|
||||
|
||||
result[0] = '\0';
|
||||
|
||||
if (BLI_path_is_rel(path)) {
|
||||
if (G.relbase_valid || lib) {
|
||||
const char *relbase = lib ? lib->filepath : G.main->name;
|
||||
|
||||
BLI_strncpy(abspath, path, sizeof(abspath));
|
||||
BLI_path_abs(abspath, relbase);
|
||||
}
|
||||
else {
|
||||
/* can't construct a valid path */
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
BLI_strncpy(abspath, path, sizeof(abspath));
|
||||
}
|
||||
|
||||
if (path_is_dirpath(abspath) || BLI_is_dir(abspath)) {
|
||||
BLI_join_dirfile(result, max, abspath, id ? id->name+2 : default_filename);
|
||||
}
|
||||
else {
|
||||
BLI_strncpy(result, abspath, max);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool BKE_cache_read_dupli_cache(Scene *scene, float frame, eCacheLibrary_EvalMode eval_mode,
|
||||
struct Group *dupgroup, struct DupliCache *dupcache, CacheLibrary *cachelib)
|
||||
{
|
||||
char filename[FILE_MAX];
|
||||
struct PTCReaderArchive *archive;
|
||||
struct PTCReader *reader;
|
||||
eCacheReadSampleResult result;
|
||||
|
||||
if (!dupcache || !dupgroup || !cachelib)
|
||||
return false;
|
||||
if (!(cachelib->eval_mode & eval_mode))
|
||||
return false;
|
||||
|
||||
BKE_cache_archive_path(cachelib->filepath, (ID *)cachelib, cachelib->id.lib, filename, sizeof(filename));
|
||||
archive = PTC_open_reader_archive(scene, filename);
|
||||
if (!archive)
|
||||
return false;
|
||||
|
||||
reader = PTC_reader_duplicache(dupgroup->id.name, dupgroup, dupcache);
|
||||
PTC_reader_init(reader, archive);
|
||||
|
||||
result = BKE_cache_read_result(PTC_read_sample(reader, frame));
|
||||
|
||||
PTC_reader_free(reader);
|
||||
PTC_close_reader_archive(archive);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BKE_cache_read_dupli_object(Scene *scene, float frame, eCacheLibrary_EvalMode eval_mode,
|
||||
struct Object *ob, struct DupliObjectData *data, CacheLibrary *cachelib)
|
||||
{
|
||||
char filename[FILE_MAX];
|
||||
struct PTCReaderArchive *archive;
|
||||
struct PTCReader *reader;
|
||||
eCacheReadSampleResult result;
|
||||
|
||||
if (!data || !ob || !cachelib)
|
||||
return false;
|
||||
if (!(cachelib->eval_mode & eval_mode))
|
||||
return false;
|
||||
|
||||
BKE_cache_archive_path(cachelib->filepath, (ID *)cachelib, cachelib->id.lib, filename, sizeof(filename));
|
||||
archive = PTC_open_reader_archive(scene, filename);
|
||||
if (!archive)
|
||||
return false;
|
||||
|
||||
PTC_reader_archive_use_render(archive, eval_mode == CACHE_LIBRARY_EVAL_RENDER);
|
||||
|
||||
reader = PTC_reader_duplicache_object(ob->id.name, ob, data);
|
||||
PTC_reader_init(reader, archive);
|
||||
|
||||
result = BKE_cache_read_result(PTC_read_sample(reader, frame));
|
||||
|
||||
PTC_reader_free(reader);
|
||||
PTC_close_reader_archive(archive);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void BKE_cache_library_dag_recalc_tag(EvaluationContext *eval_ctx, Main *bmain)
|
||||
{
|
||||
#if 0
|
||||
eCacheLibrary_EvalMode eval_mode = (eval_ctx->mode == DAG_EVAL_RENDER) ? CACHE_LIBRARY_EVAL_RENDER : CACHE_LIBRARY_EVAL_REALTIME;
|
||||
CacheLibrary *cachelib;
|
||||
|
||||
FOREACH_CACHELIB_READ(bmain, cachelib, eval_mode) {
|
||||
if (cachelib->flag & CACHE_LIBRARY_READ) {
|
||||
CacheItem *item;
|
||||
|
||||
// TODO tag group instance objects or so?
|
||||
|
||||
for (item = cachelib->items.first; item; item = item->next) {
|
||||
if (item->ob && (item->flag & CACHE_ITEM_ENABLED)) {
|
||||
|
||||
switch (item->type) {
|
||||
case CACHE_TYPE_OBJECT:
|
||||
DAG_id_tag_update(&item->ob->id, OB_RECALC_OB | OB_RECALC_TIME);
|
||||
break;
|
||||
case CACHE_TYPE_DERIVED_MESH:
|
||||
case CACHE_TYPE_PARTICLES:
|
||||
case CACHE_TYPE_HAIR:
|
||||
case CACHE_TYPE_HAIR_PATHS:
|
||||
DAG_id_tag_update(&item->ob->id, OB_RECALC_DATA | OB_RECALC_TIME);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
@@ -620,7 +620,12 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Sc
|
||||
/* inverted relation, so addtoroot shouldn't be set to zero */
|
||||
}
|
||||
|
||||
if (ob->transflag & OB_DUPLI) {
|
||||
/* XXX Fake dependency: duplicator object becomes a child of group objects.
|
||||
* This exploits the layer visibility mechanism, making the group objects update
|
||||
* when the duplicator is visible (even if group objects are not visible themselves).
|
||||
* It is not a true dependency, the duplicator does not in any way depend on group objects or data!
|
||||
*/
|
||||
if (ob->transflag & OB_DUPLI && !(ob->transflag & OB_DUPLI_READ_CACHE)) {
|
||||
if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
|
||||
GroupObject *go;
|
||||
for (go = ob->dup_group->gobject.first; go; go = go->next) {
|
||||
@@ -2137,6 +2142,10 @@ static void dag_object_time_update_flags(Main *bmain, Scene *scene, Object *ob)
|
||||
}
|
||||
}
|
||||
|
||||
/* invalidate dupli cache */
|
||||
if (ob->dup_cache)
|
||||
ob->dup_cache->flag |= DUPCACHE_FLAG_DIRTY;
|
||||
|
||||
if (ob->recalc & OB_RECALC_OB)
|
||||
lib_id_recalc_tag(bmain, &ob->id);
|
||||
if (ob->recalc & OB_RECALC_DATA)
|
||||
|
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_cache_library_types.h"
|
||||
#include "DNA_group_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
@@ -45,7 +46,7 @@
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
|
||||
#include "BKE_cache_library.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_group.h"
|
||||
@@ -318,7 +319,7 @@ bool BKE_group_is_animated(Group *group, Object *UNUSED(parent))
|
||||
GroupObject *go;
|
||||
|
||||
#if 0 /* XXX OLD ANIMSYS, NLASTRIPS ARE NO LONGER USED */
|
||||
if (parent->nlastrips.first)
|
||||
if (parent && parent->nlastrips.first)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
@@ -385,7 +386,7 @@ void BKE_group_handle_recalc_and_update(EvaluationContext *eval_ctx, Scene *scen
|
||||
* but when its enabled at some point it will need to be changed so as not to update so much - campbell */
|
||||
|
||||
/* if animated group... */
|
||||
if (parent->nlastrips.first) {
|
||||
if (parent && parent->nlastrips.first) {
|
||||
int cfrao;
|
||||
|
||||
/* switch to local time */
|
||||
|
@@ -53,6 +53,7 @@ static IDType idtypes[] = {
|
||||
{ ID_AC, "Action", "actions", IDTYPE_FLAGS_ISLINKABLE },
|
||||
{ ID_AR, "Armature", "armatures", IDTYPE_FLAGS_ISLINKABLE },
|
||||
{ ID_BR, "Brush", "brushes", IDTYPE_FLAGS_ISLINKABLE },
|
||||
{ ID_CL, "CacheLibrary", "cache_libraries", IDTYPE_FLAGS_ISLINKABLE },
|
||||
{ ID_CA, "Camera", "cameras", IDTYPE_FLAGS_ISLINKABLE },
|
||||
{ ID_CU, "Curve", "curves", IDTYPE_FLAGS_ISLINKABLE },
|
||||
{ ID_GD, "GPencil", "grease_pencil", IDTYPE_FLAGS_ISLINKABLE }, /* rename gpencil */
|
||||
|
@@ -45,6 +45,7 @@
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_brush_types.h"
|
||||
#include "DNA_cache_library_types.h"
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_group_types.h"
|
||||
#include "DNA_gpencil_types.h"
|
||||
@@ -79,6 +80,7 @@
|
||||
#include "BKE_armature.h"
|
||||
#include "BKE_bpath.h"
|
||||
#include "BKE_brush.h"
|
||||
#include "BKE_cache_library.h"
|
||||
#include "BKE_camera.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_curve.h"
|
||||
@@ -107,6 +109,7 @@
|
||||
#include "BKE_paint.h"
|
||||
#include "BKE_particle.h"
|
||||
#include "BKE_packedFile.h"
|
||||
#include "BKE_pointcache.h"
|
||||
#include "BKE_speaker.h"
|
||||
#include "BKE_sound.h"
|
||||
#include "BKE_screen.h"
|
||||
@@ -409,6 +412,10 @@ bool id_unlink(ID *id, int test)
|
||||
if (test) return true;
|
||||
BKE_object_unlink((Object *)id);
|
||||
break;
|
||||
case ID_CL:
|
||||
if (test) return true;
|
||||
BKE_cache_library_unlink((CacheLibrary *)id);
|
||||
break;
|
||||
}
|
||||
|
||||
if (id->us == 0) {
|
||||
@@ -521,6 +528,8 @@ ListBase *which_libbase(Main *mainlib, short type)
|
||||
return &(mainlib->palettes);
|
||||
case ID_PC:
|
||||
return &(mainlib->paintcurves);
|
||||
case ID_CL:
|
||||
return &(mainlib->cache_library);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -616,6 +625,7 @@ int set_listbasepointers(Main *main, ListBase **lb)
|
||||
lb[a++] = &(main->linestyle); /* referenced by scenes */
|
||||
lb[a++] = &(main->scene);
|
||||
lb[a++] = &(main->library);
|
||||
lb[a++] = &(main->cache_library);
|
||||
lb[a++] = &(main->wm);
|
||||
lb[a++] = &(main->mask);
|
||||
|
||||
@@ -747,6 +757,9 @@ static ID *alloc_libblock_notest(short type)
|
||||
case ID_PC:
|
||||
id = MEM_callocN(sizeof(PaintCurve), "Paint Curve");
|
||||
break;
|
||||
case ID_CL:
|
||||
id = MEM_callocN(sizeof(CacheLibrary), "Cache Library");
|
||||
break;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
@@ -1029,6 +1042,9 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, bool do_id_user)
|
||||
case ID_PC:
|
||||
BKE_paint_curve_free((PaintCurve *)id);
|
||||
break;
|
||||
case ID_CL:
|
||||
BKE_cache_library_free((CacheLibrary *)id);
|
||||
break;
|
||||
}
|
||||
|
||||
/* avoid notifying on removed data */
|
||||
|
@@ -2479,3 +2479,63 @@ Mesh *BKE_mesh_new_from_object(
|
||||
return tmpmesh;
|
||||
}
|
||||
|
||||
|
||||
/* settings: 1 - preview, 2 - render */
|
||||
Mesh *BKE_mesh_new_from_dupli_data(
|
||||
Main *bmain, DupliObjectData *data,
|
||||
bool calc_tessface, bool calc_undeformed)
|
||||
{
|
||||
Object *ob = data->ob;
|
||||
DerivedMesh *dm = data->cache_dm;
|
||||
CustomDataMask mask;
|
||||
|
||||
Mesh *tmpmesh;
|
||||
|
||||
if (!ob || !dm)
|
||||
return NULL;
|
||||
|
||||
mask = CD_MASK_MESH; /* this seems more suitable, exporter,
|
||||
* for example, needs CD_MASK_MDEFORMVERT */
|
||||
if (calc_undeformed)
|
||||
mask |= CD_MASK_ORCO;
|
||||
|
||||
tmpmesh = BKE_mesh_add(bmain, "Mesh");
|
||||
DM_to_mesh(dm, tmpmesh, ob, mask, true);
|
||||
|
||||
/* BKE_mesh_add/copy gives us a user count we don't need */
|
||||
tmpmesh->id.us--;
|
||||
|
||||
/* Copy materials to new mesh */
|
||||
switch (ob->type) {
|
||||
case OB_MESH: {
|
||||
Mesh *origmesh = ob->data;
|
||||
int i;
|
||||
|
||||
tmpmesh->flag = origmesh->flag;
|
||||
tmpmesh->mat = MEM_dupallocN(origmesh->mat);
|
||||
tmpmesh->totcol = origmesh->totcol;
|
||||
tmpmesh->smoothresh = origmesh->smoothresh;
|
||||
if (origmesh->mat) {
|
||||
for (i = origmesh->totcol; i-- > 0; ) {
|
||||
/* are we an object material or data based? */
|
||||
tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : origmesh->mat[i];
|
||||
|
||||
if (tmpmesh->mat[i]) {
|
||||
tmpmesh->mat[i]->id.us++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} /* end copy materials */
|
||||
|
||||
if (calc_tessface) {
|
||||
/* cycles and exporters rely on this still */
|
||||
BKE_mesh_tessface_ensure(tmpmesh);
|
||||
}
|
||||
|
||||
/* make sure materials get updated in objects */
|
||||
test_object_materials(bmain, &tmpmesh->id);
|
||||
|
||||
return tmpmesh;
|
||||
}
|
||||
|
@@ -38,6 +38,7 @@
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_cache_library_types.h"
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_constraint_types.h"
|
||||
#include "DNA_group_types.h"
|
||||
@@ -76,6 +77,7 @@
|
||||
#include "BKE_armature.h"
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_bullet.h"
|
||||
#include "BKE_cache_library.h"
|
||||
#include "BKE_deform.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
@@ -316,9 +318,12 @@ void BKE_object_free_derived_caches(Object *ob)
|
||||
}
|
||||
|
||||
if (ob->derivedFinal) {
|
||||
ob->derivedFinal->needsFree = 1;
|
||||
ob->derivedFinal->release(ob->derivedFinal);
|
||||
ob->derivedFinal = NULL;
|
||||
/* dupli cache owns the derivedFinal, is freed by duplicator object */
|
||||
if (!(ob->transflag & OB_IS_DUPLI_CACHE)) {
|
||||
ob->derivedFinal->needsFree = 1;
|
||||
ob->derivedFinal->release(ob->derivedFinal);
|
||||
ob->derivedFinal = NULL;
|
||||
}
|
||||
}
|
||||
if (ob->derivedDeform) {
|
||||
ob->derivedDeform->needsFree = 1;
|
||||
@@ -327,6 +332,8 @@ void BKE_object_free_derived_caches(Object *ob)
|
||||
}
|
||||
|
||||
BKE_object_free_curve_cache(ob);
|
||||
|
||||
BKE_object_dupli_cache_clear(ob);
|
||||
}
|
||||
|
||||
void BKE_object_free_caches(Object *object)
|
||||
@@ -447,6 +454,8 @@ void BKE_object_free_ex(Object *ob, bool do_id_user)
|
||||
free_path(ob->curve_cache->path);
|
||||
MEM_freeN(ob->curve_cache);
|
||||
}
|
||||
|
||||
BKE_object_dupli_cache_free(ob);
|
||||
}
|
||||
|
||||
void BKE_object_free(Object *ob)
|
||||
@@ -486,6 +495,7 @@ void BKE_object_unlink(Object *ob)
|
||||
ARegion *ar;
|
||||
RegionView3D *rv3d;
|
||||
LodLevel *lod;
|
||||
CacheLibrary *cachelib;
|
||||
int a, found;
|
||||
|
||||
unlink_controllers(&ob->controllers);
|
||||
@@ -673,6 +683,10 @@ void BKE_object_unlink(Object *ob)
|
||||
lod->source = NULL;
|
||||
}
|
||||
|
||||
/* dupli cache is cleared entirely if the object in question is duplified to keep it simple */
|
||||
if (BKE_object_dupli_cache_contains(obt, ob))
|
||||
BKE_object_dupli_cache_clear(ob);
|
||||
|
||||
obt = obt->id.next;
|
||||
}
|
||||
|
||||
@@ -858,6 +872,17 @@ void BKE_object_unlink(Object *ob)
|
||||
}
|
||||
camera = camera->id.next;
|
||||
}
|
||||
|
||||
/* cache libraries */
|
||||
for (cachelib = bmain->cache_library.first; cachelib; cachelib = cachelib->id.next) {
|
||||
CacheItem *item, *item_next;
|
||||
for (item = cachelib->items.first; item; item = item_next) {
|
||||
item_next = item->next;
|
||||
if (item->ob == ob) {
|
||||
BKE_cache_library_remove_item(cachelib, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* actual check for internal data, not context or flags */
|
||||
@@ -1330,12 +1355,6 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys)
|
||||
|
||||
psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, false);
|
||||
|
||||
/* XXX - from reading existing code this seems correct but intended usage of
|
||||
* pointcache should /w cloth should be added in 'ParticleSystem' - campbell */
|
||||
if (psysn->clmd) {
|
||||
psysn->clmd->point_cache = psysn->pointcache;
|
||||
}
|
||||
|
||||
id_us_plus((ID *)psysn->part);
|
||||
|
||||
return psysn;
|
||||
@@ -1527,6 +1546,7 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches)
|
||||
id_us_plus((ID *)obn->data);
|
||||
id_us_plus((ID *)obn->gpd);
|
||||
id_lib_extern((ID *)obn->dup_group);
|
||||
id_lib_extern((ID *)obn->cache_library);
|
||||
|
||||
for (a = 0; a < obn->totcol; a++) id_us_plus((ID *)obn->mat[a]);
|
||||
|
||||
@@ -1558,6 +1578,8 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches)
|
||||
/* Copy runtime surve data. */
|
||||
obn->curve_cache = NULL;
|
||||
|
||||
obn->dup_cache = NULL;
|
||||
|
||||
if (ob->id.lib) {
|
||||
BKE_id_lib_local_paths(bmain, ob->id.lib, &obn->id);
|
||||
}
|
||||
@@ -1589,6 +1611,7 @@ static void extern_local_object(Object *ob)
|
||||
|
||||
id_lib_extern((ID *)ob->data);
|
||||
id_lib_extern((ID *)ob->dup_group);
|
||||
id_lib_extern((ID *)ob->cache_library);
|
||||
id_lib_extern((ID *)ob->poselib);
|
||||
id_lib_extern((ID *)ob->gpd);
|
||||
|
||||
@@ -2846,7 +2869,15 @@ bool BKE_object_minmax_dupli(Scene *scene, Object *ob, float r_min[3], float r_m
|
||||
/* pass */
|
||||
}
|
||||
else {
|
||||
BoundBox *bb = BKE_object_boundbox_get(dob->ob);
|
||||
BoundBox *bb = NULL;
|
||||
if (ob->dup_cache) {
|
||||
DupliObjectData *dob_data = BKE_dupli_cache_find_data(ob->dup_cache, dob->ob);
|
||||
if (dob_data->cache_dm) {
|
||||
bb = &dob_data->bb;
|
||||
}
|
||||
}
|
||||
if (!bb)
|
||||
bb = BKE_object_boundbox_get(dob->ob);
|
||||
|
||||
if (bb) {
|
||||
int i;
|
||||
|
@@ -35,6 +35,8 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
|
||||
@@ -48,6 +50,7 @@
|
||||
#include "DNA_vfont_types.h"
|
||||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_cache_library.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_font.h"
|
||||
@@ -96,7 +99,7 @@ typedef struct DupliGenerator {
|
||||
static const DupliGenerator *get_dupli_generator(const DupliContext *ctx);
|
||||
|
||||
/* create initial context for root object */
|
||||
static void init_context(DupliContext *r_ctx, EvaluationContext *eval_ctx, Scene *scene, Object *ob, float space_mat[4][4], bool update)
|
||||
static void init_context_ex(DupliContext *r_ctx, EvaluationContext *eval_ctx, Scene *scene, Object *ob, float space_mat[4][4], const DupliGenerator *gen, bool update)
|
||||
{
|
||||
r_ctx->eval_ctx = eval_ctx;
|
||||
r_ctx->scene = scene;
|
||||
@@ -110,14 +113,19 @@ static void init_context(DupliContext *r_ctx, EvaluationContext *eval_ctx, Scene
|
||||
copy_m4_m4(r_ctx->space_mat, space_mat);
|
||||
else
|
||||
unit_m4(r_ctx->space_mat);
|
||||
r_ctx->lay = ob->lay;
|
||||
r_ctx->lay = ob ? ob->lay : 0;
|
||||
r_ctx->level = 0;
|
||||
|
||||
r_ctx->gen = get_dupli_generator(r_ctx);
|
||||
r_ctx->gen = gen ? gen : get_dupli_generator(r_ctx);
|
||||
|
||||
r_ctx->duplilist = NULL;
|
||||
}
|
||||
|
||||
static void init_context(DupliContext *r_ctx, EvaluationContext *eval_ctx, Scene *scene, Object *ob, bool update)
|
||||
{
|
||||
init_context_ex(r_ctx, eval_ctx, scene, ob, NULL, NULL, update);
|
||||
}
|
||||
|
||||
/* create sub-context for recursive duplis */
|
||||
static void copy_dupli_context(DupliContext *r_ctx, const DupliContext *ctx, Object *ob, float mat[4][4], int index, bool animated)
|
||||
{
|
||||
@@ -126,7 +134,7 @@ static void copy_dupli_context(DupliContext *r_ctx, const DupliContext *ctx, Obj
|
||||
r_ctx->animated |= animated; /* object animation makes all children animated */
|
||||
|
||||
/* XXX annoying, previously was done by passing an ID* argument, this at least is more explicit */
|
||||
if (ctx->gen->type == OB_DUPLIGROUP)
|
||||
if (ctx->gen->type == OB_DUPLIGROUP && ctx->object)
|
||||
r_ctx->group = ctx->object->dup_group;
|
||||
|
||||
r_ctx->object = ob;
|
||||
@@ -219,7 +227,10 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild
|
||||
{
|
||||
Object *parent = ctx->object;
|
||||
Object *obedit = ctx->scene->obedit;
|
||||
|
||||
|
||||
if (!parent)
|
||||
return;
|
||||
|
||||
if (ctx->group) {
|
||||
unsigned int lay = ctx->group->layer;
|
||||
GroupObject *go;
|
||||
@@ -255,69 +266,84 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild
|
||||
|
||||
/*---- Implementations ----*/
|
||||
|
||||
/* OB_DUPLIGROUP */
|
||||
static void make_duplis_group(const DupliContext *ctx)
|
||||
/* Intern function for creating instances of group content
|
||||
* with or without a parent (parent == NULL is allowed!)
|
||||
* Note: some of the group animation update functions use the parent object,
|
||||
* but this is old NLA code that is currently disabled and might be removed entirely.
|
||||
*/
|
||||
static void make_duplis_group_intern(const DupliContext *ctx, Group *group, Object *parent)
|
||||
{
|
||||
bool for_render = (ctx->eval_ctx->mode == DAG_EVAL_RENDER);
|
||||
Object *ob = ctx->object;
|
||||
Group *group;
|
||||
const bool for_render = (ctx->eval_ctx->mode == DAG_EVAL_RENDER);
|
||||
|
||||
GroupObject *go;
|
||||
float group_mat[4][4];
|
||||
int id;
|
||||
bool animated, hide;
|
||||
|
||||
if (ob->dup_group == NULL) return;
|
||||
group = ob->dup_group;
|
||||
|
||||
/* combine group offset and obmat */
|
||||
bool animated;
|
||||
|
||||
unit_m4(group_mat);
|
||||
sub_v3_v3(group_mat[3], group->dupli_ofs);
|
||||
mul_m4_m4m4(group_mat, ob->obmat, group_mat);
|
||||
/* don't access 'ob->obmat' from now on. */
|
||||
|
||||
|
||||
if (parent) {
|
||||
/* combine group offset and obmat */
|
||||
mul_m4_m4m4(group_mat, parent->obmat, group_mat);
|
||||
/* don't access 'parent->obmat' from now on. */
|
||||
}
|
||||
|
||||
/* handles animated groups */
|
||||
|
||||
|
||||
/* we need to check update for objects that are not in scene... */
|
||||
if (ctx->do_update) {
|
||||
/* note: update is optional because we don't always need object
|
||||
* transformations to be correct. Also fixes bug [#29616]. */
|
||||
BKE_group_handle_recalc_and_update(ctx->eval_ctx, ctx->scene, ob, group);
|
||||
BKE_group_handle_recalc_and_update(ctx->eval_ctx, ctx->scene, parent, group);
|
||||
}
|
||||
|
||||
animated = BKE_group_is_animated(group, ob);
|
||||
|
||||
|
||||
animated = BKE_group_is_animated(group, parent);
|
||||
|
||||
for (go = group->gobject.first, id = 0; go; go = go->next, id++) {
|
||||
float mat[4][4];
|
||||
bool hide;
|
||||
|
||||
/* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */
|
||||
if (go->ob != ob) {
|
||||
float mat[4][4];
|
||||
|
||||
/* Special case for instancing dupli-groups, see: T40051
|
||||
* this object may be instanced via dupli-verts/faces, in this case we don't want to render
|
||||
* (blender convention), but _do_ show in the viewport.
|
||||
*
|
||||
* Regular objects work fine but not if we're instancing dupli-groups,
|
||||
* because the rules for rendering aren't applied to objects they instance.
|
||||
* We could recursively pass down the 'hide' flag instead, but that seems unnecessary.
|
||||
*/
|
||||
if (for_render && go->ob->parent && go->ob->parent->transflag & (OB_DUPLIVERTS | OB_DUPLIFACES)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* group dupli offset, should apply after everything else */
|
||||
mul_m4_m4m4(mat, group_mat, go->ob->obmat);
|
||||
|
||||
/* check the group instance and object layers match, also that the object visible flags are ok. */
|
||||
hide = (go->ob->lay & group->layer) == 0 ||
|
||||
(for_render ? go->ob->restrictflag & OB_RESTRICT_RENDER : go->ob->restrictflag & OB_RESTRICT_VIEW);
|
||||
|
||||
make_dupli(ctx, go->ob, mat, id, animated, hide);
|
||||
|
||||
/* recursion */
|
||||
make_recursive_duplis(ctx, go->ob, group_mat, id, animated);
|
||||
if (go->ob == parent)
|
||||
continue;
|
||||
|
||||
/* Special case for instancing dupli-groups, see: T40051
|
||||
* this object may be instanced via dupli-verts/faces, in this case we don't want to render
|
||||
* (blender convention), but _do_ show in the viewport.
|
||||
*
|
||||
* Regular objects work fine but not if we're instancing dupli-groups,
|
||||
* because the rules for rendering aren't applied to objects they instance.
|
||||
* We could recursively pass down the 'hide' flag instead, but that seems unnecessary.
|
||||
*/
|
||||
if (for_render && go->ob->parent && go->ob->parent->transflag & (OB_DUPLIVERTS | OB_DUPLIFACES)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* group dupli offset, should apply after everything else */
|
||||
mul_m4_m4m4(mat, group_mat, go->ob->obmat);
|
||||
|
||||
/* check the group instance and object layers match, also that the object visible flags are ok. */
|
||||
hide = (go->ob->lay & group->layer) == 0 ||
|
||||
(for_render ? go->ob->restrictflag & OB_RESTRICT_RENDER : go->ob->restrictflag & OB_RESTRICT_VIEW);
|
||||
|
||||
make_dupli(ctx, go->ob, mat, id, animated, hide);
|
||||
|
||||
/* recursion */
|
||||
make_recursive_duplis(ctx, go->ob, group_mat, id, animated);
|
||||
}
|
||||
}
|
||||
|
||||
/* OB_DUPLIGROUP */
|
||||
static void make_duplis_group(const DupliContext *ctx)
|
||||
{
|
||||
Object *ob = ctx->object;
|
||||
if (!ob || !ob->dup_group)
|
||||
return;
|
||||
|
||||
make_duplis_group_intern(ctx, ob->dup_group, ob);
|
||||
}
|
||||
|
||||
const DupliGenerator gen_dupli_group = {
|
||||
OB_DUPLIGROUP, /* type */
|
||||
make_duplis_group /* make_duplis */
|
||||
@@ -331,8 +357,9 @@ static void make_duplis_frames(const DupliContext *ctx)
|
||||
extern int enable_cu_speed; /* object.c */
|
||||
Object copyob;
|
||||
int cfrao = scene->r.cfra;
|
||||
int dupend = ob->dupend;
|
||||
|
||||
if (!ob)
|
||||
return;
|
||||
/* dupliframes not supported inside groups */
|
||||
if (ctx->group)
|
||||
return;
|
||||
@@ -341,7 +368,7 @@ static void make_duplis_frames(const DupliContext *ctx)
|
||||
*/
|
||||
if (ob->parent == NULL && BLI_listbase_is_empty(&ob->constraints) && ob->adt == NULL)
|
||||
return;
|
||||
|
||||
|
||||
/* make a copy of the object's original data (before any dupli-data overwrites it)
|
||||
* as we'll need this to keep track of unkeyed data
|
||||
* - this doesn't take into account other data that can be reached from the object,
|
||||
@@ -356,7 +383,7 @@ static void make_duplis_frames(const DupliContext *ctx)
|
||||
* updates, as this is not a permanent change to the object */
|
||||
ob->id.flag |= LIB_ANIM_NO_RECALC;
|
||||
|
||||
for (scene->r.cfra = ob->dupsta; scene->r.cfra <= dupend; scene->r.cfra++) {
|
||||
for (scene->r.cfra = ob->dupsta; scene->r.cfra <= ob->dupend; scene->r.cfra++) {
|
||||
int ok = 1;
|
||||
|
||||
/* - dupoff = how often a frames within the range shouldn't be made into duplis
|
||||
@@ -512,6 +539,9 @@ static void make_duplis_verts(const DupliContext *ctx)
|
||||
Object *parent = ctx->object;
|
||||
bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW);
|
||||
VertexDupliData vdd;
|
||||
|
||||
if (!parent)
|
||||
return;
|
||||
|
||||
vdd.ctx = ctx;
|
||||
vdd.use_rotation = parent->transflag & OB_DUPLIROT;
|
||||
@@ -592,6 +622,8 @@ static void make_duplis_font(const DupliContext *ctx)
|
||||
const wchar_t *text = NULL;
|
||||
bool text_free = false;
|
||||
|
||||
if (!par)
|
||||
return;
|
||||
/* font dupliverts not supported inside groups */
|
||||
if (ctx->group)
|
||||
return;
|
||||
@@ -779,6 +811,9 @@ static void make_duplis_faces(const DupliContext *ctx)
|
||||
bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW);
|
||||
FaceDupliData fdd;
|
||||
|
||||
if (!parent)
|
||||
return;
|
||||
|
||||
fdd.use_scale = ((parent->transflag & OB_DUPLIFACES_SCALE) != 0);
|
||||
|
||||
/* gather mesh info */
|
||||
@@ -842,7 +877,8 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
|
||||
|
||||
int no_draw_flag = PARS_UNEXIST;
|
||||
|
||||
if (psys == NULL) return;
|
||||
if (!psys)
|
||||
return;
|
||||
|
||||
part = psys->part;
|
||||
|
||||
@@ -1123,6 +1159,9 @@ static void make_duplis_particles(const DupliContext *ctx)
|
||||
ParticleSystem *psys;
|
||||
int psysid;
|
||||
|
||||
if (!ctx->object)
|
||||
return;
|
||||
|
||||
/* particle system take up one level in id, the particles another */
|
||||
for (psys = ctx->object->particlesystem.first, psysid = 0; psys; psys = psys->next, psysid++) {
|
||||
/* particles create one more level for persistent psys index */
|
||||
@@ -1142,8 +1181,13 @@ const DupliGenerator gen_dupli_particles = {
|
||||
/* select dupli generator from given context */
|
||||
static const DupliGenerator *get_dupli_generator(const DupliContext *ctx)
|
||||
{
|
||||
int transflag = ctx->object->transflag;
|
||||
int restrictflag = ctx->object->restrictflag;
|
||||
int transflag, restrictflag;
|
||||
|
||||
if (!ctx->object)
|
||||
return NULL;
|
||||
|
||||
transflag = ctx->object->transflag;
|
||||
restrictflag = ctx->object->restrictflag;
|
||||
|
||||
if ((transflag & OB_DUPLI) == 0)
|
||||
return NULL;
|
||||
@@ -1183,15 +1227,36 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx)
|
||||
/* Returns a list of DupliObject */
|
||||
ListBase *object_duplilist_ex(EvaluationContext *eval_ctx, Scene *scene, Object *ob, bool update)
|
||||
{
|
||||
ListBase *duplilist = MEM_callocN(sizeof(ListBase), "duplilist");
|
||||
DupliContext ctx;
|
||||
init_context(&ctx, eval_ctx, scene, ob, NULL, update);
|
||||
if (ctx.gen) {
|
||||
ctx.duplilist = duplilist;
|
||||
ctx.gen->make_duplis(&ctx);
|
||||
if (update) {
|
||||
BKE_object_dupli_cache_update(scene, ob, eval_ctx, (float)scene->r.cfra);
|
||||
}
|
||||
|
||||
if (ob->dup_cache) {
|
||||
/* Note: duplis in the cache don't have the main duplicator obmat applied.
|
||||
* duplilist also should return a full copy of duplis, so we copy
|
||||
* the cached list and apply the obmat to each.
|
||||
*/
|
||||
ListBase *duplilist = MEM_callocN(sizeof(ListBase), "duplilist");
|
||||
DupliObject *dob;
|
||||
|
||||
BLI_duplicatelist(duplilist, &ob->dup_cache->duplilist);
|
||||
|
||||
for (dob = duplilist->first; dob; dob = dob->next) {
|
||||
mul_m4_m4m4(dob->mat, ob->obmat, dob->mat);
|
||||
}
|
||||
|
||||
return duplilist;
|
||||
}
|
||||
else {
|
||||
ListBase *duplilist = MEM_callocN(sizeof(ListBase), "duplilist");
|
||||
DupliContext ctx;
|
||||
init_context(&ctx, eval_ctx, scene, ob, update);
|
||||
if (ctx.gen) {
|
||||
ctx.duplilist = duplilist;
|
||||
ctx.gen->make_duplis(&ctx);
|
||||
}
|
||||
return duplilist;
|
||||
}
|
||||
|
||||
return duplilist;
|
||||
}
|
||||
|
||||
/* note: previously updating was always done, this is why it defaults to be on
|
||||
@@ -1201,6 +1266,24 @@ ListBase *object_duplilist(EvaluationContext *eval_ctx, Scene *sce, Object *ob)
|
||||
return object_duplilist_ex(eval_ctx, sce, ob, true);
|
||||
}
|
||||
|
||||
ListBase *group_duplilist_ex(EvaluationContext *eval_ctx, Scene *scene, Group *group, bool update)
|
||||
{
|
||||
ListBase *duplilist = MEM_callocN(sizeof(ListBase), "duplilist");
|
||||
DupliContext ctx;
|
||||
|
||||
init_context_ex(&ctx, eval_ctx, scene, NULL, NULL, &gen_dupli_group, update);
|
||||
ctx.duplilist = duplilist;
|
||||
|
||||
make_duplis_group_intern(&ctx, group, NULL);
|
||||
|
||||
return duplilist;
|
||||
}
|
||||
|
||||
ListBase *group_duplilist(EvaluationContext *eval_ctx, Scene *scene, Group *group)
|
||||
{
|
||||
return group_duplilist_ex(eval_ctx, scene, group, true);
|
||||
}
|
||||
|
||||
void free_object_duplilist(ListBase *lb)
|
||||
{
|
||||
BLI_freelistN(lb);
|
||||
@@ -1237,6 +1320,209 @@ int count_duplilist(Object *ob)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static void dupli_cache_calc_boundbox(DupliObjectData *data)
|
||||
{
|
||||
float min[3], max[3];
|
||||
|
||||
if (data->cache_dm) {
|
||||
INIT_MINMAX(min, max);
|
||||
data->cache_dm->getMinMax(data->cache_dm, min, max);
|
||||
}
|
||||
else {
|
||||
zero_v3(min);
|
||||
zero_v3(max);
|
||||
}
|
||||
|
||||
BKE_boundbox_init_from_minmax(&data->bb, min, max);
|
||||
}
|
||||
|
||||
void BKE_dupli_object_data_init(DupliObjectData *data, Object *ob, DerivedMesh *dm)
|
||||
{
|
||||
data->ob = ob;
|
||||
|
||||
data->cache_dm = dm;
|
||||
dm->needsFree = false; /* take ownership */
|
||||
|
||||
memset(&data->bb, 0, sizeof(data->bb));
|
||||
dupli_cache_calc_boundbox(data);
|
||||
}
|
||||
|
||||
void BKE_dupli_object_data_clear(DupliObjectData *data)
|
||||
{
|
||||
if (data->cache_dm) {
|
||||
/* we lock DMs in the cache to prevent freeing outside,
|
||||
* now allow releasing again
|
||||
*/
|
||||
data->cache_dm->needsFree = true;
|
||||
|
||||
data->cache_dm->release(data->cache_dm);
|
||||
}
|
||||
}
|
||||
|
||||
static void dupli_object_data_free(DupliObjectData *data)
|
||||
{
|
||||
BKE_dupli_object_data_clear(data);
|
||||
MEM_freeN(data);
|
||||
}
|
||||
|
||||
static void dupli_object_free(DupliObject *dob)
|
||||
{
|
||||
MEM_freeN(dob);
|
||||
}
|
||||
|
||||
static void dupli_cache_clear(DupliCache *dupcache)
|
||||
{
|
||||
DupliObject *dob, *dob_next;
|
||||
for (dob = dupcache->duplilist.first; dob; dob = dob_next) {
|
||||
dob_next = dob->next;
|
||||
|
||||
dupli_object_free(dob);
|
||||
}
|
||||
BLI_listbase_clear(&dupcache->duplilist);
|
||||
|
||||
BLI_ghash_clear(dupcache->ghash, NULL, (GHashValFreeFP)dupli_object_data_free);
|
||||
}
|
||||
|
||||
static void dupli_cache_free(DupliCache *dupcache)
|
||||
{
|
||||
dupli_cache_clear(dupcache);
|
||||
|
||||
BLI_ghash_free(dupcache->ghash, NULL, (GHashValFreeFP)dupli_object_data_free);
|
||||
MEM_freeN(dupcache);
|
||||
}
|
||||
|
||||
static DupliCache *dupli_cache_new(void)
|
||||
{
|
||||
DupliCache *dupcache = MEM_callocN(sizeof(DupliCache), "dupli object cache");
|
||||
|
||||
dupcache->ghash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "dupli object data hash");
|
||||
|
||||
return dupcache;
|
||||
}
|
||||
|
||||
static DupliObjectData *dupli_cache_add_object_data(DupliCache *dupcache, Object *ob)
|
||||
{
|
||||
DupliObjectData *data = MEM_callocN(sizeof(DupliObjectData), "dupli object data");
|
||||
|
||||
data->ob = ob;
|
||||
BLI_ghash_insert(dupcache->ghash, data->ob, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
static DupliObject *dupli_cache_add_object(DupliCache *dupcache)
|
||||
{
|
||||
DupliObject *dob = MEM_callocN(sizeof(DupliObject), "dupli object");
|
||||
|
||||
unit_m4(dob->mat);
|
||||
|
||||
BLI_addtail(&dupcache->duplilist, dob);
|
||||
return dob;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
void BKE_object_dupli_cache_update(Scene *scene, Object *ob, EvaluationContext *eval_ctx, float frame)
|
||||
{
|
||||
const eCacheLibrary_EvalMode eval_mode = eval_ctx->mode == DAG_EVAL_RENDER ? CACHE_LIBRARY_EVAL_RENDER : CACHE_LIBRARY_EVAL_REALTIME;
|
||||
|
||||
bool is_dupligroup = (ob->transflag & OB_DUPLIGROUP) && ob->dup_group;
|
||||
bool is_cached = (ob->transflag & OB_DUPLI_READ_CACHE) && ob->cache_library;
|
||||
|
||||
/* cache is a group duplicator feature only */
|
||||
if (is_dupligroup && is_cached) {
|
||||
|
||||
if (ob->dup_cache && !(ob->dup_cache->flag & DUPCACHE_FLAG_DIRTY)) {
|
||||
/* skip if cache is valid */
|
||||
}
|
||||
else {
|
||||
if (G.debug & G_DEBUG)
|
||||
printf("Update dupli cache for object '%s'\n", ob->id.name+2);
|
||||
|
||||
if (ob->dup_cache) {
|
||||
dupli_cache_clear(ob->dup_cache);
|
||||
}
|
||||
else {
|
||||
ob->dup_cache = dupli_cache_new();
|
||||
}
|
||||
|
||||
/* TODO at this point we could apply animation offset */
|
||||
BKE_cache_read_dupli_cache(scene, frame, eval_mode, ob->dup_group, ob->dup_cache, ob->cache_library);
|
||||
|
||||
ob->dup_cache->flag &= ~DUPCACHE_FLAG_DIRTY;
|
||||
ob->dup_cache->cfra = frame;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
if (ob->dup_cache) {
|
||||
dupli_cache_free(ob->dup_cache);
|
||||
ob->dup_cache = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_object_dupli_cache_clear(Object *ob)
|
||||
{
|
||||
if (ob->dup_cache) {
|
||||
dupli_cache_clear(ob->dup_cache);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_object_dupli_cache_free(Object *ob)
|
||||
{
|
||||
if (ob->dup_cache) {
|
||||
dupli_cache_free(ob->dup_cache);
|
||||
ob->dup_cache = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool BKE_object_dupli_cache_contains(Object *ob, Object *other)
|
||||
{
|
||||
if (ob->dup_cache) {
|
||||
DupliObject *dob;
|
||||
for (dob = ob->dup_cache->duplilist.first; dob; dob = dob->next) {
|
||||
if (dob->ob == other)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DupliObjectData *BKE_dupli_cache_find_data(DupliCache *dupcache, Object *ob)
|
||||
{
|
||||
DupliObjectData *data = BLI_ghash_lookup(dupcache->ghash, ob);
|
||||
return data;
|
||||
}
|
||||
|
||||
DupliObjectData *BKE_dupli_cache_add_mesh(DupliCache *dupcache, Object *ob, DerivedMesh *dm)
|
||||
{
|
||||
DupliObjectData *data = dupli_cache_add_object_data(dupcache, ob);
|
||||
data->cache_dm = dm;
|
||||
dupli_cache_calc_boundbox(data);
|
||||
|
||||
/* we own this dm now and need to protect it until we free it ourselves */
|
||||
dm->needsFree = false;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void BKE_dupli_cache_add_instance(DupliCache *dupcache, float obmat[4][4], DupliObjectData *data)
|
||||
{
|
||||
DupliObject *dob = dupli_cache_add_object(dupcache);
|
||||
|
||||
/* data must have been created correctly */
|
||||
BLI_assert(BLI_ghash_lookup(dupcache->ghash, data->ob) != NULL);
|
||||
|
||||
dob->ob = data->ob;
|
||||
copy_m4_m4(dob->mat, obmat);
|
||||
|
||||
dob->data = data;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
DupliApplyData *duplilist_apply(Object *ob, ListBase *duplilist)
|
||||
{
|
||||
DupliApplyData *apply_data = NULL;
|
||||
|
@@ -64,6 +64,7 @@
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_armature.h"
|
||||
#include "BKE_cache_library.h"
|
||||
#include "BKE_colortools.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_editmesh.h"
|
||||
@@ -1771,6 +1772,9 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain,
|
||||
/* clear animation overrides */
|
||||
/* XXX TODO... */
|
||||
|
||||
/* tag cached objects */
|
||||
BKE_cache_library_dag_recalc_tag(eval_ctx, bmain);
|
||||
|
||||
for (sce_iter = sce; sce_iter; sce_iter = sce_iter->set)
|
||||
DAG_scene_relations_update(bmain, sce_iter);
|
||||
|
||||
|
@@ -58,6 +58,7 @@
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_actuator_types.h"
|
||||
#include "DNA_brush_types.h"
|
||||
#include "DNA_cache_library_types.h"
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_cloth_types.h"
|
||||
#include "DNA_controller_types.h"
|
||||
@@ -113,6 +114,7 @@
|
||||
|
||||
#include "BKE_armature.h"
|
||||
#include "BKE_brush.h"
|
||||
#include "BKE_cache_library.h"
|
||||
#include "BKE_cloth.h"
|
||||
#include "BKE_constraint.h"
|
||||
#include "BKE_context.h"
|
||||
@@ -1969,7 +1971,6 @@ static void direct_link_paint_curve(FileData *fd, PaintCurve *pc)
|
||||
pc->points = newdataadr(fd, pc->points);
|
||||
}
|
||||
|
||||
|
||||
static void direct_link_script(FileData *UNUSED(fd), Script *script)
|
||||
{
|
||||
script->id.us = 1;
|
||||
@@ -1977,6 +1978,36 @@ static void direct_link_script(FileData *UNUSED(fd), Script *script)
|
||||
}
|
||||
|
||||
|
||||
/* ************ READ CacheLibrary *************** */
|
||||
|
||||
static void lib_link_cache_library(FileData *fd, Main *main)
|
||||
{
|
||||
CacheLibrary *cachelib;
|
||||
CacheItem *item, *item_next;
|
||||
|
||||
for (cachelib = main->cache_library.first; cachelib; cachelib = cachelib->id.next) {
|
||||
if (cachelib->id.flag & LIB_NEED_LINK) {
|
||||
cachelib->id.flag -= LIB_NEED_LINK;
|
||||
|
||||
for (item = cachelib->items.first; item; item = item_next) {
|
||||
item_next = item->next;
|
||||
|
||||
item->ob = newlibadr(fd, cachelib->id.lib, item->ob);
|
||||
|
||||
if (!item->ob)
|
||||
BKE_cache_library_remove_item(cachelib, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void direct_link_cache_library(FileData *fd, CacheLibrary *cachelib)
|
||||
{
|
||||
link_list(fd, &cachelib->items);
|
||||
cachelib->items_hash = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* ************ READ PACKEDFILE *************** */
|
||||
|
||||
static PackedFile *direct_link_packedfile(FileData *fd, PackedFile *oldpf)
|
||||
@@ -4406,6 +4437,7 @@ static void lib_link_object(FileData *fd, Main *main)
|
||||
ob->track = newlibadr(fd, ob->id.lib, ob->track);
|
||||
ob->poselib = newlibadr_us(fd, ob->id.lib, ob->poselib);
|
||||
ob->dup_group = newlibadr_us(fd, ob->id.lib, ob->dup_group);
|
||||
ob->cache_library = newlibadr_us(fd, ob->id.lib, ob->cache_library);
|
||||
|
||||
ob->proxy = newlibadr_us(fd, ob->id.lib, ob->proxy);
|
||||
if (ob->proxy) {
|
||||
@@ -4949,6 +4981,13 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
|
||||
}
|
||||
lmd->cache_system = NULL;
|
||||
}
|
||||
else if (md->type == eModifierType_Cache) {
|
||||
CacheModifierData *cmd = (CacheModifierData *)md;
|
||||
|
||||
cmd->output_dm = NULL;
|
||||
cmd->input_dm = NULL;
|
||||
cmd->flag &= ~(MOD_CACHE_USE_OUTPUT_REALTIME | MOD_CACHE_USE_OUTPUT_RENDER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5004,6 +5043,8 @@ static void direct_link_object(FileData *fd, Object *ob)
|
||||
/* do it here, below old data gets converted */
|
||||
direct_link_modifiers(fd, &ob->modifiers);
|
||||
|
||||
ob->dup_cache = NULL;
|
||||
|
||||
link_list(fd, &ob->effect);
|
||||
paf= ob->effect.first;
|
||||
while (paf) {
|
||||
@@ -7450,6 +7491,7 @@ static const char *dataname(short id_code)
|
||||
case ID_MC: return "Data from MC";
|
||||
case ID_MSK: return "Data from MSK";
|
||||
case ID_LS: return "Data from LS";
|
||||
case ID_CL: return "Data from CL";
|
||||
}
|
||||
return "Data from Lib Block";
|
||||
|
||||
@@ -7636,6 +7678,9 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
|
||||
case ID_PC:
|
||||
direct_link_paint_curve(fd, (PaintCurve *)id);
|
||||
break;
|
||||
case ID_CL:
|
||||
direct_link_cache_library(fd, (CacheLibrary *)id);
|
||||
break;
|
||||
}
|
||||
|
||||
oldnewmap_free_unused(fd->datamap);
|
||||
@@ -7830,6 +7875,7 @@ static void lib_link_all(FileData *fd, Main *main)
|
||||
lib_link_mask(fd, main);
|
||||
lib_link_linestyle(fd, main);
|
||||
lib_link_gpencil(fd, main);
|
||||
lib_link_cache_library(fd, main);
|
||||
|
||||
lib_link_mesh(fd, main); /* as last: tpage images with users at zero */
|
||||
|
||||
@@ -8706,6 +8752,8 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
|
||||
|
||||
if (ob->dup_group)
|
||||
expand_doit(fd, mainvar, ob->dup_group);
|
||||
if (ob->cache_library)
|
||||
expand_doit(fd, mainvar, ob->cache_library);
|
||||
|
||||
if (ob->proxy)
|
||||
expand_doit(fd, mainvar, ob->proxy);
|
||||
@@ -8980,6 +9028,15 @@ static void expand_gpencil(FileData *fd, Main *mainvar, bGPdata *gpd)
|
||||
expand_animdata(fd, mainvar, gpd->adt);
|
||||
}
|
||||
|
||||
static void expand_cache_library(FileData *fd, Main *mainvar, CacheLibrary *cachelib)
|
||||
{
|
||||
CacheItem *item;
|
||||
|
||||
for (item = cachelib->items.first; item; item = item->next) {
|
||||
expand_doit(fd, mainvar, item->ob);
|
||||
}
|
||||
}
|
||||
|
||||
void BLO_main_expander(void (*expand_doit_func)(void *, Main *, void *))
|
||||
{
|
||||
expand_doit = expand_doit_func;
|
||||
@@ -9077,6 +9134,9 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
|
||||
case ID_GD:
|
||||
expand_gpencil(fd, mainvar, (bGPdata *)id);
|
||||
break;
|
||||
case ID_CL:
|
||||
expand_cache_library(fd, mainvar, (CacheLibrary *)id);
|
||||
break;
|
||||
}
|
||||
|
||||
do_it = true;
|
||||
|
@@ -97,6 +97,7 @@
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_actuator_types.h"
|
||||
#include "DNA_brush_types.h"
|
||||
#include "DNA_cache_library_types.h"
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_cloth_types.h"
|
||||
#include "DNA_constraint_types.h"
|
||||
@@ -147,6 +148,7 @@
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_blender.h"
|
||||
#include "BKE_bpath.h"
|
||||
#include "BKE_cache_library.h"
|
||||
#include "BKE_curve.h"
|
||||
#include "BKE_constraint.h"
|
||||
#include "BKE_global.h" // for G
|
||||
@@ -3473,6 +3475,24 @@ static void write_linestyles(WriteData *wd, ListBase *idbase)
|
||||
}
|
||||
}
|
||||
|
||||
static void write_cachelibraries(WriteData *wd, ListBase *idbase)
|
||||
{
|
||||
CacheLibrary *cachelib;
|
||||
CacheItem *item;
|
||||
|
||||
for (cachelib = idbase->first; cachelib; cachelib = cachelib->id.next) {
|
||||
if (cachelib->id.us > 0 || wd->current) {
|
||||
writestruct(wd, ID_CL, "CacheLibrary", 1, cachelib);
|
||||
if (cachelib->id.properties)
|
||||
IDP_WriteProperty(cachelib->id.properties, wd);
|
||||
|
||||
for (item = cachelib->items.first; item; item = item->next) {
|
||||
writestruct(wd, DATA, "CacheItem", 1, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* context is usually defined by WM, two cases where no WM is available:
|
||||
* - for forward compatibility, curscreen has to be saved
|
||||
* - for undofile, curscene needs to be saved */
|
||||
@@ -3601,6 +3621,7 @@ static int write_file_handle(
|
||||
write_scripts (wd, &mainvar->script);
|
||||
write_gpencils (wd, &mainvar->gpencil);
|
||||
write_linestyles(wd, &mainvar->linestyle);
|
||||
write_cachelibraries(wd, &mainvar->cache_library);
|
||||
write_libraries(wd, mainvar->next);
|
||||
|
||||
if (write_user_block) {
|
||||
|
@@ -75,6 +75,7 @@ struct ImBuf;
|
||||
struct bNodeTree;
|
||||
struct bNode;
|
||||
struct bNodeSocket;
|
||||
struct CacheLibrary;
|
||||
struct wmDropBox;
|
||||
struct wmDrag;
|
||||
struct wmEvent;
|
||||
@@ -907,6 +908,8 @@ void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C);
|
||||
void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr);
|
||||
void uiTemplateComponentMenu(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name);
|
||||
void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color);
|
||||
uiLayout *uiTemplateCacheLibraryItem(uiLayout *layout, struct bContext *C, struct CacheLibrary *cachelib,
|
||||
struct Object *ob, int type, int index, int enabled);
|
||||
|
||||
/* Default UIList class name, keep in sync with its declaration in bl_ui/__init__.py */
|
||||
#define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list"
|
||||
|
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_cache_library_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
@@ -49,6 +50,7 @@
|
||||
#include "BLF_api.h"
|
||||
#include "BLF_translation.h"
|
||||
|
||||
#include "BKE_cache_library.h"
|
||||
#include "BKE_colortools.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
@@ -73,6 +75,7 @@
|
||||
#include "ED_util.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_enum_types.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
@@ -354,6 +357,7 @@ static const char *template_id_browse_tip(StructRNA *type)
|
||||
case ID_MSK: return N_("Browse Mask 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_CL: return N_("Browse Cache Library Data to be linked");
|
||||
}
|
||||
}
|
||||
return N_("Browse ID data to be linked");
|
||||
@@ -394,6 +398,7 @@ static const char *template_id_context(StructRNA *type)
|
||||
case ID_MSK: return BLF_I18NCONTEXT_ID_MASK;
|
||||
case ID_PAL: return BLF_I18NCONTEXT_ID_PALETTE;
|
||||
case ID_PC: return BLF_I18NCONTEXT_ID_PAINTCURVE;
|
||||
case ID_CL: return BLF_I18NCONTEXT_ID_CACHELIBRARY;
|
||||
}
|
||||
}
|
||||
return BLF_I18NCONTEXT_DEFAULT;
|
||||
@@ -3693,3 +3698,81 @@ void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float *color)
|
||||
|
||||
UI_block_align_end(block);
|
||||
}
|
||||
|
||||
/************************* Cache Library Item **************************/
|
||||
|
||||
static void cache_item_button(uiLayout *layout, bContext *UNUSED(C), CacheLibrary *cachelib, CacheItem *item, Object *ob, int type, int index)
|
||||
{
|
||||
if (item) {
|
||||
PointerRNA itemptr;
|
||||
RNA_pointer_create((ID *)cachelib, &RNA_CacheItem, item, &itemptr);
|
||||
|
||||
uiItemR(layout, &itemptr, "enabled", 0, "", ICON_NONE);
|
||||
}
|
||||
else {
|
||||
uiLayout *row = uiLayoutRow(layout, false);
|
||||
uiBlock *block = uiLayoutGetBlock(row);
|
||||
uiBut *but;
|
||||
PointerRNA obptr;
|
||||
PointerRNA *opptr;
|
||||
|
||||
RNA_id_pointer_create((ID *)ob, &obptr);
|
||||
uiLayoutSetContextPointer(row, "cache_object", &obptr);
|
||||
|
||||
but = uiDefButO(block, UI_BTYPE_CHECKBOX, "CACHELIBRARY_OT_item_enable", WM_OP_EXEC_DEFAULT, "",
|
||||
0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
|
||||
opptr = UI_but_operator_ptr_get(but);
|
||||
RNA_enum_set(opptr, "type", type);
|
||||
RNA_int_set(opptr, "index", index);
|
||||
}
|
||||
}
|
||||
|
||||
static int cache_item_indent(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case CACHE_TYPE_OBJECT:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
uiLayout *uiTemplateCacheLibraryItem(uiLayout *layout, bContext *C, CacheLibrary *cachelib,
|
||||
Object *ob, int type, int index, int enabled)
|
||||
{
|
||||
CacheItem *item = BKE_cache_library_find_item(cachelib, ob, type, index);
|
||||
|
||||
uiLayout *split, *row, *sub;
|
||||
int i;
|
||||
char name[2*MAX_NAME];
|
||||
int icon = ICON_NONE;
|
||||
|
||||
row = uiLayoutRow(layout, false);
|
||||
uiLayoutSetEnabled(row, enabled);
|
||||
uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
|
||||
|
||||
split = uiLayoutSplit(row, 0.0f, false);
|
||||
|
||||
for (i = 0; i < cache_item_indent(type); ++i)
|
||||
uiItemL(split, "", ICON_NONE);
|
||||
cache_item_button(split, C, cachelib, item, ob, type, index);
|
||||
|
||||
split = uiLayoutSplit(row, 0.1f, false);
|
||||
uiLayoutSetEnabled(split, item && (item->flag & CACHE_ITEM_ENABLED));
|
||||
sub = uiLayoutColumn(split, false);
|
||||
|
||||
BKE_cache_item_name(ob, type, index, name);
|
||||
RNA_enum_icon_from_value(cache_library_item_type_items, type, &icon);
|
||||
uiItemL(split, name, icon);
|
||||
|
||||
/* display read result */
|
||||
split = uiLayoutSplit(row, 0.9f, false);
|
||||
if (item && (item->flag & CACHE_ITEM_ENABLED))
|
||||
RNA_enum_icon_from_value(cache_library_read_result_items, item->read_result, &icon);
|
||||
else
|
||||
icon = ICON_NONE;
|
||||
uiItemL(split, NULL, icon);
|
||||
|
||||
return sub;
|
||||
}
|
||||
|
@@ -26,8 +26,10 @@ set(INC
|
||||
../../bmesh
|
||||
../../makesdna
|
||||
../../makesrna
|
||||
../../pointcache
|
||||
../../windowmanager
|
||||
../../collada
|
||||
../../../../intern/guardedalloc
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
@@ -35,9 +37,11 @@ set(INC_SYS
|
||||
)
|
||||
|
||||
set(SRC
|
||||
io_cache_library.c
|
||||
io_collada.c
|
||||
io_ops.c
|
||||
|
||||
io_cache_library.h
|
||||
io_collada.h
|
||||
io_ops.h
|
||||
)
|
||||
|
@@ -36,10 +36,13 @@ incs = [
|
||||
'../../blenfont',
|
||||
'../../blenkernel',
|
||||
'../../blenlib',
|
||||
'../../bmesh',
|
||||
'../../collada',
|
||||
'../../makesdna',
|
||||
'../../makesrna',
|
||||
'../../pointcache',
|
||||
'../../windowmanager',
|
||||
'../../bmesh../../makesdna',
|
||||
'../../../../intern/guardedalloc',
|
||||
]
|
||||
|
||||
if env['WITH_BF_COLLADA']:
|
||||
|
576
source/blender/editors/io/io_cache_library.c
Normal file
576
source/blender/editors/io/io_cache_library.c
Normal file
@@ -0,0 +1,576 @@
|
||||
/*
|
||||
* ***** 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) 2015 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Blender Foundation
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/editors/io/io_cache_library.c
|
||||
* \ingroup editor/io
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLF_translation.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_fileops.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_path_util.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_cache_library_types.h"
|
||||
#include "DNA_group_types.h"
|
||||
#include "DNA_listBase.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BKE_anim.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_cache_library.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_library.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "ED_screen.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_cache_library.h"
|
||||
|
||||
#include "PTC_api.h"
|
||||
|
||||
static int ED_cache_library_active_object_poll(bContext *C)
|
||||
{
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
if (!ob || !ob->cache_library)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/********************** new cache library operator *********************/
|
||||
|
||||
static int new_cachelib_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
CacheLibrary *cachelib = ob->cache_library;
|
||||
Main *bmain = CTX_data_main(C);
|
||||
PointerRNA ptr, idptr;
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* add or copy material */
|
||||
if (cachelib) {
|
||||
cachelib = BKE_cache_library_copy(cachelib);
|
||||
}
|
||||
else {
|
||||
cachelib = BKE_cache_library_add(bmain, DATA_("CacheLibrary"));
|
||||
}
|
||||
|
||||
/* enable fake user by default */
|
||||
cachelib->id.flag |= LIB_FAKEUSER;
|
||||
|
||||
/* hook into UI */
|
||||
UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
|
||||
|
||||
if (prop) {
|
||||
/* when creating new ID blocks, use is already 1, but RNA
|
||||
* pointer se also increases user, so this compensates it */
|
||||
cachelib->id.us--;
|
||||
|
||||
RNA_id_pointer_create(&cachelib->id, &idptr);
|
||||
RNA_property_pointer_set(&ptr, prop, idptr);
|
||||
RNA_property_update(C, &ptr, prop);
|
||||
}
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE, cachelib);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void CACHELIBRARY_OT_new(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "New Cache Library";
|
||||
ot->idname = "CACHELIBRARY_OT_new";
|
||||
ot->description = "Add a new cache library";
|
||||
|
||||
/* api callbacks */
|
||||
ot->poll = ED_operator_object_active;
|
||||
ot->exec = new_cachelib_exec;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
|
||||
}
|
||||
|
||||
/********************** delete cache library operator *********************/
|
||||
|
||||
static int cache_library_delete_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
CacheLibrary *cachelib = ob->cache_library;
|
||||
|
||||
BKE_cache_library_unlink(cachelib);
|
||||
BKE_libblock_free(bmain, cachelib);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE, cachelib);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void CACHELIBRARY_OT_delete(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Delete Cache Library";
|
||||
ot->idname = "CACHELIBRARY_OT_delete";
|
||||
ot->description = "Delete a cache library data block";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = cache_library_delete_exec;
|
||||
ot->invoke = WM_operator_confirm;
|
||||
ot->poll = ED_cache_library_active_object_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/********************** enable cache item operator *********************/
|
||||
|
||||
static int cache_item_enable_poll(bContext *C)
|
||||
{
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
CacheLibrary *cachelib = ob->cache_library;
|
||||
Object *obcache = CTX_data_pointer_get_type(C, "cache_object", &RNA_Object).data;
|
||||
|
||||
if (!cachelib || !obcache)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int cache_item_enable_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
CacheLibrary *cachelib = ob->cache_library;
|
||||
Object *obcache = CTX_data_pointer_get_type(C, "cache_object", &RNA_Object).data;
|
||||
int type = RNA_enum_get(op->ptr, "type");
|
||||
int index = RNA_int_get(op->ptr, "index");
|
||||
|
||||
CacheItem *item = BKE_cache_library_add_item(cachelib, obcache, type, index);
|
||||
item->flag |= CACHE_ITEM_ENABLED;
|
||||
|
||||
WM_event_add_notifier(C, NC_OBJECT, cachelib);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void CACHELIBRARY_OT_item_enable(wmOperatorType *ot)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* identifiers */
|
||||
ot->name = "Enable Cache Item";
|
||||
ot->idname = "CACHELIBRARY_OT_item_enable";
|
||||
ot->description = "Enable a cache item";
|
||||
|
||||
/* api callbacks */
|
||||
ot->poll = cache_item_enable_poll;
|
||||
ot->exec = cache_item_enable_exec;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
|
||||
|
||||
prop = RNA_def_enum(ot->srna, "type", cache_library_item_type_items, CACHE_TYPE_OBJECT, "Type", "Type of cache item to add");
|
||||
RNA_def_property_flag(prop, PROP_REQUIRED);
|
||||
RNA_def_int(ot->srna, "index", -1, -1, INT_MAX, "Index", "Index of data in the object", -1, INT_MAX);
|
||||
}
|
||||
|
||||
/********************** bake cache operator *********************/
|
||||
|
||||
static int cache_library_bake_poll(bContext *C)
|
||||
{
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
|
||||
if (!ob || !(ob->transflag & OB_DUPLIGROUP) || !ob->dup_group || !ob->cache_library)
|
||||
return false;
|
||||
/* re-baking cached results doesn't make much sense,
|
||||
* clarify workflow by enabling either reading or writing, but not both
|
||||
*/
|
||||
if (ob->transflag & OB_DUPLI_READ_CACHE)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef struct CacheLibraryBakeJob {
|
||||
short *stop, *do_update;
|
||||
float *progress;
|
||||
|
||||
struct Main *bmain;
|
||||
struct Scene *scene;
|
||||
EvaluationContext eval_ctx;
|
||||
struct CacheLibrary *cachelib;
|
||||
struct Group *group;
|
||||
|
||||
struct PTCWriterArchive *archive;
|
||||
struct PTCWriter *writer;
|
||||
|
||||
int origfra; /* original frame to reset scene after export */
|
||||
float origframelen; /* original frame length to reset scene after export */
|
||||
} CacheLibraryBakeJob;
|
||||
|
||||
static void cache_library_bake_freejob(void *customdata)
|
||||
{
|
||||
CacheLibraryBakeJob *data= (CacheLibraryBakeJob *)customdata;
|
||||
MEM_freeN(data);
|
||||
}
|
||||
|
||||
static void cache_library_bake_do(CacheLibraryBakeJob *data, short *stop, short *do_update, float *progress)
|
||||
{
|
||||
Scene *scene = data->scene;
|
||||
int start_frame, end_frame;
|
||||
|
||||
if ((*stop) || (G.is_break))
|
||||
return;
|
||||
|
||||
data->writer = PTC_writer_dupligroup(data->group->id.name, &data->eval_ctx, scene, data->group, data->cachelib);
|
||||
PTC_writer_init(data->writer, data->archive);
|
||||
|
||||
/* XXX where to get this from? */
|
||||
start_frame = scene->r.sfra;
|
||||
end_frame = scene->r.efra;
|
||||
PTC_bake(data->bmain, scene, &data->eval_ctx, data->writer, start_frame, end_frame, stop, do_update, progress);
|
||||
|
||||
if (data->writer) {
|
||||
PTC_writer_free(data->writer);
|
||||
data->writer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void cache_library_bake_startjob(void *customdata, short *stop, short *do_update, float *progress)
|
||||
{
|
||||
CacheLibraryBakeJob *data = (CacheLibraryBakeJob *)customdata;
|
||||
Scene *scene = data->scene;
|
||||
char filename[FILE_MAX];
|
||||
|
||||
data->stop = stop;
|
||||
data->do_update = do_update;
|
||||
data->progress = progress;
|
||||
|
||||
data->origfra = scene->r.cfra;
|
||||
data->origframelen = scene->r.framelen;
|
||||
scene->r.framelen = 1.0f;
|
||||
|
||||
BKE_cache_archive_path(data->cachelib->filepath, (ID *)data->cachelib, data->cachelib->id.lib, filename, sizeof(filename));
|
||||
data->archive = PTC_open_writer_archive(scene, filename);
|
||||
|
||||
if (data->archive) {
|
||||
|
||||
G.is_break = false;
|
||||
|
||||
if (data->cachelib->eval_mode & CACHE_LIBRARY_EVAL_REALTIME) {
|
||||
data->eval_ctx.mode = DAG_EVAL_VIEWPORT;
|
||||
PTC_writer_archive_use_render(data->archive, false);
|
||||
cache_library_bake_do(data, stop, do_update, progress);
|
||||
}
|
||||
|
||||
if (data->cachelib->eval_mode & CACHE_LIBRARY_EVAL_RENDER) {
|
||||
data->eval_ctx.mode = DAG_EVAL_RENDER;
|
||||
PTC_writer_archive_use_render(data->archive, true);
|
||||
cache_library_bake_do(data, stop, do_update, progress);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*do_update = true;
|
||||
*stop = 0;
|
||||
}
|
||||
|
||||
static void cache_library_bake_endjob(void *customdata)
|
||||
{
|
||||
CacheLibraryBakeJob *data = (CacheLibraryBakeJob *)customdata;
|
||||
Scene *scene = data->scene;
|
||||
|
||||
G.is_rendering = false;
|
||||
BKE_spacedata_draw_locks(false);
|
||||
|
||||
if (data->writer)
|
||||
PTC_writer_free(data->writer);
|
||||
if (data->archive)
|
||||
PTC_close_writer_archive(data->archive);
|
||||
|
||||
/* reset scene frame */
|
||||
scene->r.cfra = data->origfra;
|
||||
scene->r.framelen = data->origframelen;
|
||||
BKE_scene_update_for_newframe(&data->eval_ctx, data->bmain, scene, scene->lay);
|
||||
}
|
||||
|
||||
/* Warning! Deletes existing files if possible, operator should show confirm dialog! */
|
||||
static bool cache_library_bake_ensure_file_target(CacheLibrary *cachelib)
|
||||
{
|
||||
char filename[FILE_MAX];
|
||||
|
||||
BKE_cache_archive_path(cachelib->filepath, (ID *)cachelib, cachelib->id.lib, filename, sizeof(filename));
|
||||
|
||||
if (BLI_exists(filename)) {
|
||||
if (BLI_is_dir(filename)) {
|
||||
return false;
|
||||
}
|
||||
else if (BLI_is_file(filename)) {
|
||||
if (BLI_file_is_writable(filename)) {
|
||||
/* returns 0 on success */
|
||||
return (BLI_delete(filename, false, false) == 0);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int cache_library_bake_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
CacheLibraryBakeJob *data;
|
||||
wmJob *wm_job;
|
||||
|
||||
/* make sure we can write */
|
||||
cache_library_bake_ensure_file_target(ob->cache_library);
|
||||
|
||||
/* XXX annoying hack: needed to prevent data corruption when changing
|
||||
* scene frame in separate threads
|
||||
*/
|
||||
G.is_rendering = true;
|
||||
|
||||
BKE_spacedata_draw_locks(true);
|
||||
|
||||
/* XXX set WM_JOB_EXCL_RENDER to prevent conflicts with render jobs,
|
||||
* since we need to set G.is_rendering
|
||||
*/
|
||||
wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Cache Library Bake",
|
||||
WM_JOB_PROGRESS | WM_JOB_EXCL_RENDER, WM_JOB_TYPE_CACHELIBRARY_BAKE);
|
||||
|
||||
/* setup job */
|
||||
data = MEM_callocN(sizeof(CacheLibraryBakeJob), "Cache Library Bake Job");
|
||||
data->bmain = bmain;
|
||||
data->scene = scene;
|
||||
data->cachelib = ob->cache_library;
|
||||
data->group = ob->dup_group;
|
||||
|
||||
WM_jobs_customdata_set(wm_job, data, cache_library_bake_freejob);
|
||||
WM_jobs_timer(wm_job, 0.1, NC_SCENE|ND_FRAME, NC_SCENE|ND_FRAME);
|
||||
WM_jobs_callbacks(wm_job, cache_library_bake_startjob, NULL, NULL, cache_library_bake_endjob);
|
||||
|
||||
WM_jobs_start(CTX_wm_manager(C), wm_job);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int cache_library_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
|
||||
{
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
CacheLibrary *cachelib = ob->cache_library;
|
||||
|
||||
char filename[FILE_MAX];
|
||||
|
||||
if (!cachelib)
|
||||
return OPERATOR_CANCELLED;
|
||||
if (!BKE_cache_archive_path_test(cachelib->filepath, (ID *)cachelib, cachelib->id.lib)) {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "Cannot create file path for cache library %200s", cachelib->id.name+2);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
BKE_cache_archive_path(cachelib->filepath, (ID *)cachelib, cachelib->id.lib, filename, sizeof(filename));
|
||||
|
||||
if (BLI_exists(filename)) {
|
||||
if (BLI_is_dir(filename)) {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "Cache Library target is a directory: %200s", filename);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
else if (BLI_is_file(filename)) {
|
||||
if (BLI_file_is_writable(filename)) {
|
||||
return WM_operator_confirm_message(C, op, "Overwrite?");
|
||||
}
|
||||
else {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "Cannot overwrite Cache Library target: %200s", filename);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "Invalid Cache Library target: %200s", filename);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
}
|
||||
else
|
||||
return cache_library_bake_exec(C, op);
|
||||
}
|
||||
|
||||
void CACHELIBRARY_OT_bake(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Bake";
|
||||
ot->description = "Bake cache library";
|
||||
ot->idname = "CACHELIBRARY_OT_bake";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = cache_library_bake_invoke;
|
||||
ot->exec = cache_library_bake_exec;
|
||||
ot->poll = cache_library_bake_poll;
|
||||
|
||||
/* flags */
|
||||
/* no undo for this operator, cannot restore old cache files anyway */
|
||||
ot->flag = OPTYPE_REGISTER;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
static void ui_item_nlabel(uiLayout *layout, const char *s, size_t len)
|
||||
{
|
||||
char buf[256];
|
||||
|
||||
BLI_strncpy(buf, s, sizeof(buf)-1);
|
||||
buf[min_ii(len, sizeof(buf)-1)] = '\0';
|
||||
|
||||
uiItemL(layout, buf, ICON_NONE);
|
||||
}
|
||||
|
||||
static void archive_info_labels(uiLayout *layout, const char *info)
|
||||
{
|
||||
const char delim[] = {'\n', '\0'};
|
||||
const char *cur = info;
|
||||
size_t linelen;
|
||||
char *sep, *suf;
|
||||
|
||||
linelen = BLI_str_partition(cur, delim, &sep, &suf);
|
||||
while (sep) {
|
||||
ui_item_nlabel(layout, cur, linelen);
|
||||
cur = suf;
|
||||
|
||||
linelen = BLI_str_partition(cur, delim, &sep, &suf);
|
||||
}
|
||||
ui_item_nlabel(layout, cur, linelen);
|
||||
}
|
||||
|
||||
static uiBlock *archive_info_popup_create(bContext *C, ARegion *ar, void *arg)
|
||||
{
|
||||
const char *info = arg;
|
||||
uiBlock *block;
|
||||
uiLayout *layout;
|
||||
|
||||
block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
|
||||
UI_block_flag_disable(block, UI_BLOCK_LOOP);
|
||||
UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT);
|
||||
|
||||
layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, UI_UNIT_X * 20, UI_UNIT_Y, 0, UI_style_get());
|
||||
|
||||
archive_info_labels(layout, info);
|
||||
|
||||
UI_block_bounds_set_centered(block, 0);
|
||||
UI_block_direction_set(block, UI_DIR_DOWN);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
static int cache_library_archive_info_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
CacheLibrary *cachelib = ob->cache_library;
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
const bool use_stdout = RNA_boolean_get(op->ptr, "use_stdout");
|
||||
const bool use_popup = RNA_boolean_get(op->ptr, "use_popup");
|
||||
const bool use_clipboard = RNA_boolean_get(op->ptr, "use_clipboard");
|
||||
|
||||
char filename[FILE_MAX];
|
||||
struct PTCReaderArchive *archive;
|
||||
char *info;
|
||||
|
||||
BKE_cache_archive_path(cachelib->filepath, (ID *)cachelib, cachelib->id.lib, filename, sizeof(filename));
|
||||
archive = PTC_open_reader_archive(scene, filename);
|
||||
if (!archive) {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "Cannot open cache file at '%s'", cachelib->filepath);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
info = PTC_get_archive_info(archive);
|
||||
PTC_close_reader_archive(archive);
|
||||
|
||||
if (info) {
|
||||
if (use_stdout) {
|
||||
printf("%s", info);
|
||||
}
|
||||
|
||||
if (use_popup) {
|
||||
UI_popup_block_invoke(C, archive_info_popup_create, info);
|
||||
}
|
||||
|
||||
if (use_clipboard) {
|
||||
WM_clipboard_text_set(info, false);
|
||||
}
|
||||
|
||||
MEM_freeN(info);
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void CACHELIBRARY_OT_archive_info(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Archive Info";
|
||||
ot->description = "Get archive details from a cache library archive";
|
||||
ot->idname = "CACHELIBRARY_OT_archive_info";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = cache_library_archive_info_exec;
|
||||
ot->poll = ED_cache_library_active_object_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
RNA_def_boolean(ot->srna, "use_stdout", false, "Use stdout", "Print info in standard output");
|
||||
RNA_def_boolean(ot->srna, "use_popup", false, "Show Popup", "Display archive info in a popup");
|
||||
RNA_def_boolean(ot->srna, "use_clipboard", false, "Copy to Clipboard", "Copy archive info to the clipboard");
|
||||
}
|
44
source/blender/editors/io/io_cache_library.h
Normal file
44
source/blender/editors/io/io_cache_library.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* ***** 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) 2015 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Blender Foundation
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/editors/io/io_cache_library.h
|
||||
* \ingroup editor/io
|
||||
*/
|
||||
|
||||
#ifndef __IO_CACHE_LIBRARY_H__
|
||||
#define __IO_CACHE_LIBRARY_H__
|
||||
|
||||
struct wmOperatorType;
|
||||
|
||||
void CACHELIBRARY_OT_new(struct wmOperatorType *ot);
|
||||
void CACHELIBRARY_OT_delete(struct wmOperatorType *ot);
|
||||
|
||||
void CACHELIBRARY_OT_item_enable(struct wmOperatorType *ot);
|
||||
|
||||
void CACHELIBRARY_OT_bake(struct wmOperatorType *ot);
|
||||
|
||||
void CACHELIBRARY_OT_archive_info(struct wmOperatorType *ot);
|
||||
|
||||
#endif
|
@@ -30,13 +30,21 @@
|
||||
|
||||
#include "io_ops.h" /* own include */
|
||||
|
||||
#include "io_cache_library.h"
|
||||
#ifdef WITH_COLLADA
|
||||
# include "io_collada.h"
|
||||
# include "WM_api.h"
|
||||
#endif
|
||||
|
||||
#include "WM_api.h"
|
||||
|
||||
void ED_operatortypes_io(void)
|
||||
{
|
||||
WM_operatortype_append(CACHELIBRARY_OT_new);
|
||||
WM_operatortype_append(CACHELIBRARY_OT_delete);
|
||||
WM_operatortype_append(CACHELIBRARY_OT_item_enable);
|
||||
WM_operatortype_append(CACHELIBRARY_OT_bake);
|
||||
WM_operatortype_append(CACHELIBRARY_OT_archive_info);
|
||||
|
||||
#ifdef WITH_COLLADA
|
||||
/* Collada operators: */
|
||||
WM_operatortype_append(WM_OT_collada_export);
|
||||
|
@@ -1190,29 +1190,30 @@ static void filelist_from_main(struct FileList *filelist)
|
||||
|
||||
filelist->filelist[0].relname = BLI_strdup(FILENAME_PARENT);
|
||||
filelist->filelist[1].relname = BLI_strdup("Scene");
|
||||
filelist->filelist[2].relname = BLI_strdup("Object");
|
||||
filelist->filelist[3].relname = BLI_strdup("Mesh");
|
||||
filelist->filelist[4].relname = BLI_strdup("Curve");
|
||||
filelist->filelist[5].relname = BLI_strdup("Metaball");
|
||||
filelist->filelist[6].relname = BLI_strdup("Material");
|
||||
filelist->filelist[7].relname = BLI_strdup("Texture");
|
||||
filelist->filelist[8].relname = BLI_strdup("Image");
|
||||
filelist->filelist[9].relname = BLI_strdup("Ika");
|
||||
filelist->filelist[10].relname = BLI_strdup("Wave");
|
||||
filelist->filelist[11].relname = BLI_strdup("Lattice");
|
||||
filelist->filelist[12].relname = BLI_strdup("Lamp");
|
||||
filelist->filelist[13].relname = BLI_strdup("Camera");
|
||||
filelist->filelist[14].relname = BLI_strdup("Ipo");
|
||||
filelist->filelist[15].relname = BLI_strdup("World");
|
||||
filelist->filelist[16].relname = BLI_strdup("Screen");
|
||||
filelist->filelist[17].relname = BLI_strdup("VFont");
|
||||
filelist->filelist[18].relname = BLI_strdup("Text");
|
||||
filelist->filelist[19].relname = BLI_strdup("Armature");
|
||||
filelist->filelist[20].relname = BLI_strdup("Action");
|
||||
filelist->filelist[21].relname = BLI_strdup("NodeTree");
|
||||
filelist->filelist[22].relname = BLI_strdup("Speaker");
|
||||
filelist->filelist[2].relname = BLI_strdup("CacheLibrary");
|
||||
filelist->filelist[3].relname = BLI_strdup("Object");
|
||||
filelist->filelist[4].relname = BLI_strdup("Mesh");
|
||||
filelist->filelist[5].relname = BLI_strdup("Curve");
|
||||
filelist->filelist[6].relname = BLI_strdup("Metaball");
|
||||
filelist->filelist[7].relname = BLI_strdup("Material");
|
||||
filelist->filelist[8].relname = BLI_strdup("Texture");
|
||||
filelist->filelist[9].relname = BLI_strdup("Image");
|
||||
filelist->filelist[10].relname = BLI_strdup("Ika");
|
||||
filelist->filelist[11].relname = BLI_strdup("Wave");
|
||||
filelist->filelist[12].relname = BLI_strdup("Lattice");
|
||||
filelist->filelist[13].relname = BLI_strdup("Lamp");
|
||||
filelist->filelist[14].relname = BLI_strdup("Camera");
|
||||
filelist->filelist[15].relname = BLI_strdup("Ipo");
|
||||
filelist->filelist[16].relname = BLI_strdup("World");
|
||||
filelist->filelist[17].relname = BLI_strdup("Screen");
|
||||
filelist->filelist[18].relname = BLI_strdup("VFont");
|
||||
filelist->filelist[19].relname = BLI_strdup("Text");
|
||||
filelist->filelist[20].relname = BLI_strdup("Armature");
|
||||
filelist->filelist[21].relname = BLI_strdup("Action");
|
||||
filelist->filelist[22].relname = BLI_strdup("NodeTree");
|
||||
filelist->filelist[23].relname = BLI_strdup("Speaker");
|
||||
#ifdef WITH_FREESTYLE
|
||||
filelist->filelist[23].relname = BLI_strdup("FreestyleLineStyle");
|
||||
filelist->filelist[24].relname = BLI_strdup("FreestyleLineStyle");
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
|
@@ -1170,6 +1170,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
|
||||
UI_icon_draw(x, y, ICON_MOD_DATA_TRANSFER); break;
|
||||
case eModifierType_NormalEdit:
|
||||
UI_icon_draw(x, y, ICON_MOD_NORMALEDIT); break;
|
||||
case eModifierType_Cache:
|
||||
UI_icon_draw(x, y, ICON_PHYSICS); break;
|
||||
/* Default */
|
||||
case eModifierType_None:
|
||||
case eModifierType_ShapeKey:
|
||||
|
@@ -7611,7 +7611,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
|
||||
|
||||
/* code for new particle system */
|
||||
if ((ob->particlesystem.first) &&
|
||||
(ob != scene->obedit))
|
||||
(ob != scene->obedit) &&
|
||||
!(ob->transflag & OB_IS_DUPLI_CACHE))
|
||||
{
|
||||
ParticleSystem *psys;
|
||||
|
||||
|
@@ -55,6 +55,7 @@
|
||||
#include "BKE_camera.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_key.h"
|
||||
#include "BKE_main.h"
|
||||
@@ -2044,7 +2045,7 @@ static void draw_dupli_objects_color(
|
||||
UI_GetThemeColorBlend3ubv(color, TH_BACK, 0.5f, color_rgb);
|
||||
}
|
||||
|
||||
tbase.flag = OB_FROMDUPLI | base->flag;
|
||||
tbase.flag |= OB_FROMDUPLI;
|
||||
lb = object_duplilist(G.main->eval_ctx, scene, base->object);
|
||||
// BLI_listbase_sort(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */
|
||||
|
||||
@@ -2054,7 +2055,11 @@ static void draw_dupli_objects_color(
|
||||
if (dob) dob_next = dupli_step(dob->next);
|
||||
|
||||
for (; dob; dob_prev = dob, dob = dob_next, dob_next = dob_next ? dupli_step(dob_next->next) : NULL) {
|
||||
/* for restoring after override */
|
||||
DerivedMesh *store_final_dm;
|
||||
|
||||
tbase.object = dob->ob;
|
||||
store_final_dm = dob->ob->derivedFinal;
|
||||
|
||||
/* Make sure lod is updated from dupli's position */
|
||||
|
||||
@@ -2091,6 +2096,21 @@ static void draw_dupli_objects_color(
|
||||
glColor3ubv(color_rgb);
|
||||
}
|
||||
|
||||
/* override final DM */
|
||||
bb_tmp = NULL;
|
||||
tbase.object->transflag &= ~OB_IS_DUPLI_CACHE;
|
||||
if (base->object->dup_cache) {
|
||||
DupliObjectData *dob_data = BKE_dupli_cache_find_data(base->object->dup_cache, tbase.object);
|
||||
if (dob_data->cache_dm) {
|
||||
tbase.object->transflag |= OB_IS_DUPLI_CACHE;
|
||||
|
||||
tbase.object->derivedFinal = dob_data->cache_dm;
|
||||
bb_tmp = &dob_data->bb;
|
||||
}
|
||||
}
|
||||
if (!bb_tmp)
|
||||
bb_tmp = BKE_object_boundbox_get(dob->ob);
|
||||
|
||||
/* generate displist, test for new object */
|
||||
if (dob_prev && dob_prev->ob != dob->ob) {
|
||||
if (use_displist == true)
|
||||
@@ -2099,7 +2119,7 @@ static void draw_dupli_objects_color(
|
||||
use_displist = false;
|
||||
}
|
||||
|
||||
if ((bb_tmp = BKE_object_boundbox_get(dob->ob))) {
|
||||
if (bb_tmp) {
|
||||
bb = *bb_tmp; /* must make a copy */
|
||||
testbb = true;
|
||||
}
|
||||
@@ -2160,6 +2180,10 @@ static void draw_dupli_objects_color(
|
||||
tbase.object->dtx = dtx;
|
||||
tbase.object->transflag = transflag;
|
||||
tbase.object->currentlod = savedlod;
|
||||
|
||||
/* restore final DM */
|
||||
tbase.object->transflag &= ~OB_IS_DUPLI_CACHE;
|
||||
tbase.object->derivedFinal = store_final_dm;
|
||||
}
|
||||
|
||||
if (apply_data) {
|
||||
|
@@ -1030,23 +1030,40 @@ static void view3d_select_loop(ViewContext *vc, Scene *scene, View3D *v3d, ARegi
|
||||
lb = object_duplilist(G.main->eval_ctx, scene, base->object);
|
||||
|
||||
for (dob = lb->first; dob; dob = dob->next) {
|
||||
float omat[4][4];
|
||||
/* for restoring after override */
|
||||
struct DerivedMesh *store_final_dm;
|
||||
float store_obmat[4][4];
|
||||
|
||||
tbase.object = dob->ob;
|
||||
copy_m4_m4(omat, dob->ob->obmat);
|
||||
copy_m4_m4(store_obmat, dob->ob->obmat);
|
||||
copy_m4_m4(dob->ob->obmat, dob->mat);
|
||||
store_final_dm = dob->ob->derivedFinal;
|
||||
|
||||
/* extra service: draw the duplicator in drawtype of parent */
|
||||
/* MIN2 for the drawtype to allow bounding box objects in groups for lods */
|
||||
dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt);
|
||||
dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx;
|
||||
|
||||
/* override final DM */
|
||||
tbase.object->transflag &= ~OB_IS_DUPLI_CACHE;
|
||||
if (base->object->dup_cache) {
|
||||
DupliObjectData *dob_data = BKE_dupli_cache_find_data(base->object->dup_cache, tbase.object);
|
||||
if (dob_data->cache_dm) {
|
||||
tbase.object->transflag |= OB_IS_DUPLI_CACHE;
|
||||
|
||||
tbase.object->derivedFinal = dob_data->cache_dm;
|
||||
}
|
||||
}
|
||||
|
||||
draw_object(scene, ar, v3d, &tbase, DRAW_PICKING | DRAW_CONSTCOLOR);
|
||||
|
||||
tbase.object->dt = dt;
|
||||
tbase.object->dtx = dtx;
|
||||
|
||||
copy_m4_m4(dob->ob->obmat, omat);
|
||||
/* restore obmat and final DM */
|
||||
tbase.object->transflag &= ~OB_IS_DUPLI_CACHE;
|
||||
copy_m4_m4(dob->ob->obmat, store_obmat);
|
||||
tbase.object->derivedFinal = store_final_dm;
|
||||
}
|
||||
free_object_duplilist(lb);
|
||||
}
|
||||
|
@@ -222,6 +222,7 @@ typedef struct PreviewImage {
|
||||
#define ID_LS MAKE_ID2('L', 'S') /* FreestyleLineStyle */
|
||||
#define ID_PAL MAKE_ID2('P', 'L') /* Palette */
|
||||
#define ID_PC MAKE_ID2('P', 'C') /* PaintCurve */
|
||||
#define ID_CL MAKE_ID2('C', 'L') /* CacheLibrary */
|
||||
|
||||
/* NOTE! Fake IDs, needed for g.sipo->blocktype or outliner */
|
||||
#define ID_SEQ MAKE_ID2('S', 'Q')
|
||||
|
94
source/blender/makesdna/DNA_cache_library_types.h
Normal file
94
source/blender/makesdna/DNA_cache_library_types.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* ***** 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) 2015 by Blender Foundation
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file DNA_cache_library_types.h
|
||||
* \ingroup DNA
|
||||
*/
|
||||
|
||||
#ifndef __DNA_CACHE_LIBRARY_TYPES_H__
|
||||
#define __DNA_CACHE_LIBRARY_TYPES_H__
|
||||
|
||||
#include "DNA_defs.h"
|
||||
#include "DNA_ID.h"
|
||||
#include "DNA_listBase.h"
|
||||
|
||||
#define MAX_CACHE_GROUP_LEVEL 8
|
||||
|
||||
typedef enum eCacheItemType {
|
||||
CACHE_TYPE_OBJECT = 0,
|
||||
CACHE_TYPE_DERIVED_MESH = 1,
|
||||
CACHE_TYPE_HAIR = 2,
|
||||
CACHE_TYPE_HAIR_PATHS = 3,
|
||||
CACHE_TYPE_PARTICLES = 4,
|
||||
} eCacheItemType;
|
||||
|
||||
typedef enum eCacheReadSampleResult {
|
||||
CACHE_READ_SAMPLE_INVALID = 0, /* no valid result can be retrieved */
|
||||
CACHE_READ_SAMPLE_EARLY = 1, /* request time before first sample */
|
||||
CACHE_READ_SAMPLE_LATE = 2, /* request time after last sample */
|
||||
CACHE_READ_SAMPLE_EXACT = 3, /* found sample for requested frame */
|
||||
CACHE_READ_SAMPLE_INTERPOLATED = 4, /* no exact sample, but found enclosing samples for interpolation */
|
||||
} eCacheReadSampleResult;
|
||||
|
||||
typedef struct CacheItem {
|
||||
struct CacheItem *next, *prev;
|
||||
|
||||
struct Object *ob;
|
||||
int type;
|
||||
int index;
|
||||
|
||||
int flag;
|
||||
short read_result;
|
||||
short pad;
|
||||
} CacheItem;
|
||||
|
||||
typedef enum eCacheItem_Flag {
|
||||
CACHE_ITEM_ENABLED = 1,
|
||||
} eCacheItem_Flag;
|
||||
|
||||
typedef struct CacheLibrary {
|
||||
ID id;
|
||||
|
||||
int flag;
|
||||
short eval_mode;
|
||||
short pad;
|
||||
|
||||
char filepath[1024]; /* 1024 = FILE_MAX */
|
||||
|
||||
ListBase items; /* cached items */
|
||||
struct GHash *items_hash; /* runtime: cached items hash for fast lookup */
|
||||
} CacheLibrary;
|
||||
|
||||
//typedef enum eCacheLibrary_Flag {
|
||||
//} eCacheLibrary_Flag;
|
||||
|
||||
typedef enum eCacheLibrary_EvalMode {
|
||||
CACHE_LIBRARY_EVAL_REALTIME = (1 << 0), /* evaluate data with realtime settings */
|
||||
CACHE_LIBRARY_EVAL_RENDER = (1 << 1), /* evaluate data with render settings */
|
||||
} eCacheLibrary_EvalMode;
|
||||
|
||||
#endif
|
@@ -84,6 +84,7 @@ typedef enum ModifierType {
|
||||
eModifierType_Wireframe = 48,
|
||||
eModifierType_DataTransfer = 49,
|
||||
eModifierType_NormalEdit = 50,
|
||||
eModifierType_Cache = 51,
|
||||
NUM_MODIFIER_TYPES
|
||||
} ModifierType;
|
||||
|
||||
@@ -1444,6 +1445,25 @@ enum {
|
||||
MOD_DATATRANSFER_USE_POLY = 1 << 31,
|
||||
};
|
||||
|
||||
/* point cache modifier */
|
||||
typedef struct CacheModifierData {
|
||||
ModifierData modifier;
|
||||
|
||||
int flag;
|
||||
int pad;
|
||||
|
||||
/* DM data for writing into the cache */
|
||||
struct DerivedMesh *output_dm;
|
||||
|
||||
/* DM data read from the cache for modifier input */
|
||||
struct DerivedMesh *input_dm;
|
||||
} CacheModifierData;
|
||||
|
||||
typedef enum eCacheModifier_Flag {
|
||||
MOD_CACHE_USE_OUTPUT_REALTIME = 1,
|
||||
MOD_CACHE_USE_OUTPUT_RENDER = 2,
|
||||
} eCacheModifier_Flag;
|
||||
|
||||
/* Set Split Normals modifier */
|
||||
typedef struct NormalEditModifierData {
|
||||
ModifierData modifier;
|
||||
|
@@ -180,7 +180,8 @@ typedef struct Object {
|
||||
short flag; /* copy of Base */
|
||||
short colbits DNA_DEPRECATED; /* deprecated, use 'matbits' */
|
||||
|
||||
short transflag, protectflag; /* transformation settings and transform locks */
|
||||
int transflag; /* transformation settings */
|
||||
short protectflag, pad; /* transform locks */
|
||||
short trackflag, upflag;
|
||||
short nlaflag; /* used for DopeSheet filtering settings (expanded/collapsed) */
|
||||
short ipoflag; // xxx deprecated... old animation system
|
||||
@@ -191,8 +192,6 @@ typedef struct Object {
|
||||
/* dupli-frame settings */
|
||||
int dupon, dupoff, dupsta, dupend;
|
||||
|
||||
int pad;
|
||||
|
||||
/* during realtime */
|
||||
|
||||
/* note that inertia is only called inertia for historical reasons
|
||||
@@ -263,6 +262,8 @@ typedef struct Object {
|
||||
struct PartDeflect *pd; /* particle deflector/attractor/collision data */
|
||||
struct SoftBody *soft; /* if exists, saved in file */
|
||||
struct Group *dup_group; /* object duplicator for group */
|
||||
struct DupliCache *dup_cache; /* cached dupli overrides */
|
||||
struct CacheLibrary *cache_library; /* cache library to use */
|
||||
|
||||
char body_type; /* for now used to temporarily holds the type of collision object */
|
||||
char shapeflag; /* flag for pinning */
|
||||
@@ -328,8 +329,33 @@ typedef struct DupliObject {
|
||||
|
||||
/* particle this dupli was generated from */
|
||||
struct ParticleSystem *particle_system;
|
||||
|
||||
struct DupliObjectData *data;
|
||||
} DupliObject;
|
||||
|
||||
/* data that can be shared by multiple DupliObject instances */
|
||||
typedef struct DupliObjectData {
|
||||
/* XXX eventually it should be possible to construct dupli instances
|
||||
* entirely without Objects in the DNA, but current drawing code and
|
||||
* others make this too difficult
|
||||
*/
|
||||
struct Object *ob;
|
||||
struct BoundBox bb;
|
||||
struct DerivedMesh *cache_dm;
|
||||
} DupliObjectData;
|
||||
|
||||
typedef struct DupliCache {
|
||||
int flag;
|
||||
float cfra; /* frame for which the cache was constructed */
|
||||
|
||||
struct GHash *ghash;
|
||||
ListBase duplilist;
|
||||
} DupliCache;
|
||||
|
||||
typedef enum eDupliCache_Flag {
|
||||
DUPCACHE_FLAG_DIRTY = (1 << 0), /* cache requires update */
|
||||
} eDupliCache_Flag;
|
||||
|
||||
/* **************** OBJECT ********************* */
|
||||
|
||||
/* used many places... should be specialized */
|
||||
@@ -405,6 +431,9 @@ enum {
|
||||
OB_RENDER_DUPLI = 1 << 12,
|
||||
OB_NO_CONSTRAINTS = 1 << 13, /* runtime constraints disable */
|
||||
OB_NO_PSYS_UPDATE = 1 << 14, /* hack to work around particle issue */
|
||||
OB_DUPLI_READ_CACHE = 1 << 15, /* use cache instead of object data */
|
||||
|
||||
OB_IS_DUPLI_CACHE = 1 << 31, /* temporary flag: object data overridden from cache */
|
||||
|
||||
OB_DUPLI = OB_DUPLIFRAMES | OB_DUPLIVERTS | OB_DUPLIGROUP | OB_DUPLIFACES | OB_DUPLIPARTS,
|
||||
};
|
||||
|
@@ -136,6 +136,7 @@ static const char *includefiles[] = {
|
||||
"DNA_rigidbody_types.h",
|
||||
"DNA_freestyle_types.h",
|
||||
"DNA_linestyle_types.h",
|
||||
"DNA_cache_library_types.h",
|
||||
|
||||
/* empty string to indicate end of includefiles */
|
||||
""
|
||||
@@ -1287,4 +1288,5 @@ int main(int argc, char **argv)
|
||||
#include "DNA_rigidbody_types.h"
|
||||
#include "DNA_freestyle_types.h"
|
||||
#include "DNA_linestyle_types.h"
|
||||
#include "DNA_cache_library_types.h"
|
||||
/* end of list */
|
||||
|
@@ -95,6 +95,8 @@ extern StructRNA RNA_Brush;
|
||||
extern StructRNA RNA_BrushTextureSlot;
|
||||
extern StructRNA RNA_BuildModifier;
|
||||
extern StructRNA RNA_MeshCacheModifier;
|
||||
extern StructRNA RNA_CacheItem;
|
||||
extern StructRNA RNA_CacheLibrary;
|
||||
extern StructRNA RNA_Camera;
|
||||
extern StructRNA RNA_CastModifier;
|
||||
extern StructRNA RNA_ChildOfConstraint;
|
||||
@@ -451,6 +453,7 @@ extern StructRNA RNA_ParticleSystemModifier;
|
||||
extern StructRNA RNA_ParticleTarget;
|
||||
extern StructRNA RNA_PivotConstraint;
|
||||
extern StructRNA RNA_PointCache;
|
||||
extern StructRNA RNA_PointCacheModifier;
|
||||
extern StructRNA RNA_PointDensity;
|
||||
extern StructRNA RNA_PointDensityTexture;
|
||||
extern StructRNA RNA_PointLamp;
|
||||
|
@@ -174,6 +174,9 @@ extern EnumPropertyItem prop_dynamicpaint_type_items[];
|
||||
|
||||
extern EnumPropertyItem clip_editor_mode_items[];
|
||||
|
||||
extern EnumPropertyItem cache_library_item_type_items[];
|
||||
extern EnumPropertyItem cache_library_read_result_items[];
|
||||
|
||||
extern EnumPropertyItem icon_items[];
|
||||
extern EnumPropertyItem uilist_layout_type_items[];
|
||||
|
||||
@@ -213,5 +216,7 @@ EnumPropertyItem *RNA_movieclip_itemf(struct bContext *C, struct PointerRNA *ptr
|
||||
EnumPropertyItem *RNA_movieclip_local_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
|
||||
EnumPropertyItem *RNA_mask_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
|
||||
EnumPropertyItem *RNA_mask_local_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
|
||||
EnumPropertyItem *RNA_cachelibrary_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
|
||||
EnumPropertyItem *RNA_cachelibrary_local_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
|
||||
|
||||
#endif /* __RNA_ENUM_TYPES_H__ */
|
||||
|
@@ -38,6 +38,7 @@ set(DEFSRC
|
||||
rna_armature.c
|
||||
rna_boid.c
|
||||
rna_brush.c
|
||||
rna_cache_library.c
|
||||
rna_camera.c
|
||||
rna_cloth.c
|
||||
rna_color.c
|
||||
|
@@ -3283,6 +3283,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
|
||||
{"rna_boid.c", NULL, RNA_def_boid},
|
||||
{"rna_brush.c", NULL, RNA_def_brush},
|
||||
{"rna_camera.c", "rna_camera_api.c", RNA_def_camera},
|
||||
{"rna_cache_library.c", NULL, RNA_def_cache_library},
|
||||
{"rna_cloth.c", NULL, RNA_def_cloth},
|
||||
{"rna_color.c", NULL, RNA_def_color},
|
||||
{"rna_constraint.c", NULL, RNA_def_constraint},
|
||||
|
@@ -50,6 +50,7 @@ EnumPropertyItem id_type_items[] = {
|
||||
{ID_AR, "ARMATURE", ICON_ARMATURE_DATA, "Armature", ""},
|
||||
{ID_BR, "BRUSH", ICON_BRUSH_DATA, "Brush", ""},
|
||||
{ID_CA, "CAMERA", ICON_CAMERA_DATA, "Camera", ""},
|
||||
{ID_CL, "CACHELIBRARY", ICON_PHYSICS, "Cache Library", ""},
|
||||
{ID_CU, "CURVE", ICON_CURVE_DATA, "Curve", ""},
|
||||
{ID_VF, "FONT", ICON_FONT_DATA, "Font", ""},
|
||||
{ID_GD, "GREASEPENCIL", ICON_GREASEPENCIL, "Grease Pencil", ""},
|
||||
@@ -130,6 +131,7 @@ short RNA_type_to_ID_code(StructRNA *type)
|
||||
if (RNA_struct_is_a(type, &RNA_Action)) return ID_AC;
|
||||
if (RNA_struct_is_a(type, &RNA_Armature)) return ID_AR;
|
||||
if (RNA_struct_is_a(type, &RNA_Brush)) return ID_BR;
|
||||
if (RNA_struct_is_a(type, &RNA_CacheLibrary)) return ID_CL;
|
||||
if (RNA_struct_is_a(type, &RNA_Camera)) return ID_CA;
|
||||
if (RNA_struct_is_a(type, &RNA_Curve)) return ID_CU;
|
||||
if (RNA_struct_is_a(type, &RNA_GreasePencil)) return ID_GD;
|
||||
@@ -170,6 +172,7 @@ StructRNA *ID_code_to_RNA_type(short idcode)
|
||||
case ID_AR: return &RNA_Armature;
|
||||
case ID_BR: return &RNA_Brush;
|
||||
case ID_CA: return &RNA_Camera;
|
||||
case ID_CL: return &RNA_CacheLibrary;
|
||||
case ID_CU: return &RNA_Curve;
|
||||
case ID_GD: return &RNA_GreasePencil;
|
||||
case ID_GR: return &RNA_Group;
|
||||
|
339
source/blender/makesrna/intern/rna_cache_library.c
Normal file
339
source/blender/makesrna/intern/rna_cache_library.c
Normal file
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
* ***** 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): Blender Foundation (2015).
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/makesrna/intern/rna_cache_library.c
|
||||
* \ingroup RNA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "DNA_cache_library_types.h"
|
||||
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_enum_types.h"
|
||||
|
||||
#include "rna_internal.h"
|
||||
|
||||
#include "WM_types.h"
|
||||
|
||||
EnumPropertyItem cache_library_item_type_items[] = {
|
||||
{CACHE_TYPE_OBJECT, "OBJECT", ICON_OBJECT_DATA, "Object", "Object base properties"},
|
||||
{CACHE_TYPE_DERIVED_MESH, "DERIVED_MESH", ICON_OUTLINER_OB_MESH, "Derived Mesh", "Mesh result from modifiers"},
|
||||
{CACHE_TYPE_HAIR, "HAIR", ICON_PARTICLE_POINT, "Hair", "Hair parent strands"},
|
||||
{CACHE_TYPE_HAIR_PATHS, "HAIR_PATHS", ICON_PARTICLE_PATH, "Hair Paths", "Full hair paths"},
|
||||
{CACHE_TYPE_PARTICLES, "PARTICLES", ICON_PARTICLES, "Particles", "Emitter particles"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
EnumPropertyItem cache_library_read_result_items[] = {
|
||||
{CACHE_READ_SAMPLE_INVALID, "INVALID", ICON_ERROR, "Invalid", "No valid sample found"},
|
||||
{CACHE_READ_SAMPLE_EXACT, "EXACT", ICON_SPACE3, "Exact", "Found sample for requested frame"},
|
||||
{CACHE_READ_SAMPLE_INTERPOLATED, "INTERPOLATED", ICON_TRIA_DOWN_BAR, "Interpolated", "Enclosing samples found for interpolation"},
|
||||
{CACHE_READ_SAMPLE_EARLY, "EARLY", ICON_TRIA_RIGHT_BAR, "Early", "Requested frame before the first sample"},
|
||||
{CACHE_READ_SAMPLE_LATE, "LATE", ICON_TRIA_LEFT_BAR, "Late", "Requested frame after the last sample"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BKE_cache_library.h"
|
||||
#include "BKE_main.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
|
||||
static void rna_CacheItem_name_get(PointerRNA *ptr, char *value)
|
||||
{
|
||||
CacheItem *item = ptr->data;
|
||||
BKE_cache_item_name(item->ob, item->type, item->index, value);
|
||||
}
|
||||
|
||||
static int rna_CacheItem_name_length(PointerRNA *ptr)
|
||||
{
|
||||
CacheItem *item = ptr->data;
|
||||
return BKE_cache_item_name_length(item->ob, item->type, item->index);
|
||||
}
|
||||
|
||||
static void rna_CacheItem_get_name(struct Object *ob, int type, int index, char *name)
|
||||
{
|
||||
BKE_cache_item_name(ob, type, index, name);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
static void rna_CacheLibrary_update(Main *UNUSED(main), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
|
||||
{
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
static PointerRNA rna_ObjectCache_object_get(PointerRNA *ptr)
|
||||
{
|
||||
Object *ob = ptr->data;
|
||||
PointerRNA rptr;
|
||||
RNA_id_pointer_create((ID *)ob, &rptr);
|
||||
return rptr;
|
||||
}
|
||||
|
||||
static void rna_CacheLibrary_object_caches_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
CacheLibraryObjectsIterator *internal = (CacheLibraryObjectsIterator *)(&iter->internal.listbase);
|
||||
CacheLibrary *cachelib = ptr->data;
|
||||
|
||||
/* XXX this is not particularly elegant, but works:
|
||||
* abuse the internal union for storing our own iterator
|
||||
*/
|
||||
BLI_STATIC_ASSERT(sizeof(iter->internal) >= sizeof(CacheLibraryObjectsIterator), "CollectionPropertyIterator internal not large enough");
|
||||
|
||||
BKE_object_cache_iter_init(internal, cachelib);
|
||||
iter->valid = BKE_object_cache_iter_valid(internal);
|
||||
}
|
||||
|
||||
void rna_CacheLibrary_object_caches_next(CollectionPropertyIterator *iter)
|
||||
{
|
||||
CacheLibraryObjectsIterator *internal = (CacheLibraryObjectsIterator *)(&iter->internal.listbase);
|
||||
|
||||
BKE_object_cache_iter_next(internal);
|
||||
iter->valid = BKE_object_cache_iter_valid(internal);
|
||||
}
|
||||
|
||||
void rna_CacheLibrary_object_caches_end(CollectionPropertyIterator *iter)
|
||||
{
|
||||
CacheLibraryObjectsIterator *internal = (CacheLibraryObjectsIterator *)(&iter->internal.listbase);
|
||||
|
||||
BKE_object_cache_iter_end(internal);
|
||||
}
|
||||
|
||||
PointerRNA rna_CacheLibrary_object_caches_get(CollectionPropertyIterator *iter)
|
||||
{
|
||||
CacheLibraryObjectsIterator *internal = (CacheLibraryObjectsIterator *)(&iter->internal.listbase);
|
||||
PointerRNA rptr;
|
||||
|
||||
RNA_pointer_create((ID *)iter->parent.id.data, &RNA_ObjectCache, BKE_object_cache_iter_get(internal), &rptr);
|
||||
|
||||
return rptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
static PointerRNA rna_CacheLibrary_cache_item_find(CacheLibrary *cachelib, Object *ob, int type, int index)
|
||||
{
|
||||
CacheItem *item = BKE_cache_library_find_item(cachelib, ob, type, index);
|
||||
PointerRNA rptr;
|
||||
|
||||
RNA_pointer_create((ID *)cachelib, &RNA_CacheItem, item, &rptr);
|
||||
return rptr;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
static void rna_ObjectCache_caches_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
CacheLibraryItemsIterator *internal = (CacheLibraryItemsIterator *)(&iter->internal.listbase);
|
||||
Object *ob = ptr->data;
|
||||
|
||||
/* XXX this is not particularly elegant, but works:
|
||||
* abuse the internal union for storing our own iterator
|
||||
*/
|
||||
BLI_STATIC_ASSERT(sizeof(iter->internal) >= sizeof(CacheLibraryItemsIterator), "CollectionPropertyIterator internal not large enough");
|
||||
|
||||
BKE_cache_item_iter_init(internal, ob);
|
||||
iter->valid = BKE_cache_item_iter_valid(internal);
|
||||
}
|
||||
|
||||
void rna_ObjectCache_caches_next(CollectionPropertyIterator *iter)
|
||||
{
|
||||
CacheLibraryItemsIterator *internal = (CacheLibraryItemsIterator *)(&iter->internal.listbase);
|
||||
|
||||
BKE_cache_item_iter_next(internal);
|
||||
iter->valid = BKE_cache_item_iter_valid(internal);
|
||||
}
|
||||
|
||||
void rna_ObjectCache_caches_end(CollectionPropertyIterator *iter)
|
||||
{
|
||||
CacheLibraryItemsIterator *internal = (CacheLibraryItemsIterator *)(&iter->internal.listbase);
|
||||
|
||||
BKE_cache_item_iter_end(internal);
|
||||
}
|
||||
|
||||
PointerRNA rna_ObjectCache_caches_get(CollectionPropertyIterator *iter)
|
||||
{
|
||||
CacheLibraryItemsIterator *internal = (CacheLibraryItemsIterator *)(&iter->internal.listbase);
|
||||
PointerRNA rptr;
|
||||
|
||||
/* XXX this returns a temporary pointer that becomes invalid after iteration, potentially dangerous! */
|
||||
RNA_pointer_create((ID *)iter->parent.id.data, &RNA_CacheItem, internal->cur, &rptr);
|
||||
|
||||
return rptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
static void rna_def_cache_item(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *prop, *parm;
|
||||
|
||||
srna = RNA_def_struct(brna, "CacheItem", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Cache Item", "Description of a cacheable item in an object");
|
||||
|
||||
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "ob");
|
||||
RNA_def_property_struct_type(prop, "Object");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Object", "");
|
||||
|
||||
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "type");
|
||||
RNA_def_property_enum_items(prop, cache_library_item_type_items);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Type", "Type of cached data");
|
||||
|
||||
prop = RNA_def_property(srna, "index", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "index");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Index", "Index of the cached data");
|
||||
|
||||
prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", CACHE_ITEM_ENABLED);
|
||||
RNA_def_property_ui_text(prop, "Enabled", "Enable caching for this item");
|
||||
|
||||
prop = RNA_def_property(srna, "read_result", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "read_result");
|
||||
RNA_def_property_enum_items(prop, cache_library_read_result_items);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Read Result", "Result of cache read");
|
||||
|
||||
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_maxlength(prop, 2*MAX_NAME);
|
||||
RNA_def_property_string_funcs(prop, "rna_CacheItem_name_get", "rna_CacheItem_name_length", NULL);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Name", "");
|
||||
RNA_def_struct_name_property(srna, prop);
|
||||
|
||||
func = RNA_def_function(srna, "get_name", "rna_CacheItem_get_name");
|
||||
RNA_def_function_flag(func, FUNC_NO_SELF);
|
||||
RNA_def_function_ui_description(func, "Get name of items from properties without an instance");
|
||||
parm = RNA_def_pointer(func, "object", "Object", "Object", "");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
|
||||
parm = RNA_def_enum(func, "type", cache_library_item_type_items, CACHE_TYPE_OBJECT, "Type", "Type of cache item");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
RNA_def_int(func, "index", -1, -1, INT_MAX, "Index", "Index of the data in it's' collection", -1, INT_MAX);
|
||||
parm = RNA_def_string(func, "name", NULL, 2*MAX_NAME, "Name", "");
|
||||
RNA_def_property_flag(parm, PROP_THICK_WRAP);
|
||||
RNA_def_function_output(func, parm);
|
||||
}
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
static void rna_def_object_cache(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "ObjectCache", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Object Cache", "Cacheable data in an Object");
|
||||
|
||||
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_funcs(prop, "rna_ObjectCache_object_get", NULL, NULL, NULL);
|
||||
RNA_def_property_struct_type(prop, "Object");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Object", "");
|
||||
|
||||
prop = RNA_def_property(srna, "caches", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "CacheItem");
|
||||
RNA_def_property_collection_funcs(prop, "rna_ObjectCache_caches_begin", "rna_ObjectCache_caches_next", "rna_ObjectCache_caches_end",
|
||||
"rna_ObjectCache_caches_get", NULL, NULL, NULL, NULL);
|
||||
RNA_def_property_ui_text(prop, "Caches", "Cacheable items for in an object cache");
|
||||
}
|
||||
#endif
|
||||
|
||||
static void rna_def_cache_library(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *prop, *parm;
|
||||
|
||||
static EnumPropertyItem eval_mode_items[] = {
|
||||
{CACHE_LIBRARY_EVAL_REALTIME, "REALTIME", ICON_RESTRICT_VIEW_OFF, "Realtime", "Evaluate data with realtime settings"},
|
||||
{CACHE_LIBRARY_EVAL_RENDER, "RENDER", ICON_RESTRICT_RENDER_OFF, "Render", "Evaluate data with render settings"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
srna = RNA_def_struct(brna, "CacheLibrary", "ID");
|
||||
RNA_def_struct_ui_text(srna, "Cache Library", "Cache Library datablock for constructing an archive of caches");
|
||||
RNA_def_struct_ui_icon(srna, ICON_PHYSICS);
|
||||
|
||||
prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
|
||||
RNA_def_property_string_sdna(prop, NULL, "filepath");
|
||||
RNA_def_property_ui_text(prop, "File Path", "Path to cache library storage");
|
||||
RNA_def_property_update(prop, 0, "rna_CacheLibrary_update");
|
||||
|
||||
prop = RNA_def_property(srna, "eval_mode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "eval_mode");
|
||||
RNA_def_property_enum_items(prop, eval_mode_items);
|
||||
RNA_def_property_flag(prop, PROP_ENUM_FLAG);
|
||||
RNA_def_property_ui_text(prop, "Evaluation Mode", "Mode to use when evaluating data");
|
||||
RNA_def_property_update(prop, 0, "rna_CacheLibrary_update");
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
prop = RNA_def_property(srna, "object_caches", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "ObjectCache");
|
||||
RNA_def_property_collection_funcs(prop, "rna_CacheLibrary_object_caches_begin", "rna_CacheLibrary_object_caches_next", "rna_CacheLibrary_object_caches_end",
|
||||
"rna_CacheLibrary_object_caches_get", NULL, NULL, NULL, NULL);
|
||||
RNA_def_property_ui_text(prop, "Object Caches", "Cacheable objects inside the cache library group");
|
||||
#endif
|
||||
|
||||
func = RNA_def_function(srna, "cache_item_find", "rna_CacheLibrary_cache_item_find");
|
||||
RNA_def_function_ui_description(func, "Find item for an object cache item");
|
||||
parm = RNA_def_pointer(func, "object", "Object", "Object", "");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
|
||||
parm = RNA_def_enum(func, "type", cache_library_item_type_items, CACHE_TYPE_OBJECT, "Type", "Type of cache item");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
RNA_def_int(func, "index", -1, -1, INT_MAX, "Index", "Index of the data in it's' collection", -1, INT_MAX);
|
||||
parm = RNA_def_pointer(func, "item", "CacheItem", "Item", "Item in the cache");
|
||||
RNA_def_property_flag(parm, PROP_RNAPTR);
|
||||
RNA_def_function_return(func, parm);
|
||||
}
|
||||
|
||||
void RNA_def_cache_library(BlenderRNA *brna)
|
||||
{
|
||||
rna_def_cache_item(brna);
|
||||
#if 0 /* UNUSED */
|
||||
rna_def_object_cache(brna);
|
||||
#endif
|
||||
rna_def_cache_library(brna);
|
||||
}
|
||||
|
||||
#endif
|
@@ -136,6 +136,7 @@ void RNA_def_armature(struct BlenderRNA *brna);
|
||||
void RNA_def_actuator(struct BlenderRNA *brna);
|
||||
void RNA_def_boid(struct BlenderRNA *brna);
|
||||
void RNA_def_brush(struct BlenderRNA *brna);
|
||||
void RNA_def_cache_library(struct BlenderRNA *brna);
|
||||
void RNA_def_camera(struct BlenderRNA *brna);
|
||||
void RNA_def_cloth(struct BlenderRNA *brna);
|
||||
void RNA_def_color(struct BlenderRNA *brna);
|
||||
@@ -332,6 +333,7 @@ void RNA_def_main_gpencil(BlenderRNA *brna, PropertyRNA *cprop);
|
||||
void RNA_def_main_movieclips(BlenderRNA *brna, PropertyRNA *cprop);
|
||||
void RNA_def_main_masks(BlenderRNA *brna, PropertyRNA *cprop);
|
||||
void RNA_def_main_linestyles(BlenderRNA *brna, PropertyRNA *cprop);
|
||||
void RNA_def_main_cache_libraries(BlenderRNA *brna, PropertyRNA *cprop);
|
||||
|
||||
/* ID Properties */
|
||||
|
||||
|
@@ -287,6 +287,12 @@ static void rna_Main_linestyle_begin(CollectionPropertyIterator *iter, PointerRN
|
||||
rna_iterator_listbase_begin(iter, &bmain->linestyle, NULL);
|
||||
}
|
||||
|
||||
static void rna_Main_cachelibraries_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
Main *bmain = (Main *)ptr->data;
|
||||
rna_iterator_listbase_begin(iter, &bmain->cache_library, NULL);
|
||||
}
|
||||
|
||||
static void rna_Main_version_get(PointerRNA *ptr, int *value)
|
||||
{
|
||||
Main *bmain = (Main *)ptr->data;
|
||||
@@ -361,6 +367,7 @@ void RNA_def_main(BlenderRNA *brna)
|
||||
{"movieclips", "MovieClip", "rna_Main_movieclips_begin", "Movie Clips", "Movie Clip datablocks", RNA_def_main_movieclips},
|
||||
{"masks", "Mask", "rna_Main_masks_begin", "Masks", "Masks datablocks", RNA_def_main_masks},
|
||||
{"linestyles", "FreestyleLineStyle", "rna_Main_linestyle_begin", "Line Styles", "Line Style datablocks", RNA_def_main_linestyles},
|
||||
{"cache_libraries", "CacheLibrary", "rna_Main_cachelibraries_begin", "Cache Libraries", "Cache Library datablocks", RNA_def_main_cache_libraries},
|
||||
{NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
@@ -48,6 +48,8 @@
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_anim.h"
|
||||
#include "BKE_cache_library.h"
|
||||
#include "BKE_camera.h"
|
||||
#include "BKE_curve.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
@@ -80,6 +82,7 @@
|
||||
#include "BKE_linestyle.h"
|
||||
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_cache_library_types.h"
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_curve_types.h"
|
||||
#include "DNA_lamp_types.h"
|
||||
@@ -308,6 +311,62 @@ Mesh *rna_Main_meshes_new_from_object(
|
||||
return BKE_mesh_new_from_object(bmain, sce, ob, apply_modifiers, settings, calc_tessface, calc_undeformed);
|
||||
}
|
||||
|
||||
/* copied from Mesh_getFromObject and adapted to RNA interface */
|
||||
/* settings: 1 - preview, 2 - render */
|
||||
Mesh *rna_Main_meshes_new_from_dupli(
|
||||
Main *bmain, ReportList *reports, Scene *scene, Object *parent, DupliObject *dob,
|
||||
int settings, int calc_tessface, int calc_undeformed)
|
||||
{
|
||||
Mesh *mesh = NULL;
|
||||
|
||||
switch (dob->ob->type) {
|
||||
case OB_FONT:
|
||||
case OB_CURVE:
|
||||
case OB_SURF:
|
||||
case OB_MBALL:
|
||||
case OB_MESH:
|
||||
break;
|
||||
default:
|
||||
BKE_report(reports, RPT_ERROR, "Object does not have geometry data");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((parent->transflag & OB_DUPLI_READ_CACHE) && parent->cache_library) {
|
||||
float frame = (float)scene->r.cfra;
|
||||
eCacheLibrary_EvalMode eval_mode;
|
||||
|
||||
if (settings == 1)
|
||||
eval_mode = CACHE_LIBRARY_EVAL_REALTIME;
|
||||
else if (settings == 2)
|
||||
eval_mode = CACHE_LIBRARY_EVAL_RENDER;
|
||||
else
|
||||
return NULL;
|
||||
|
||||
if (settings == 1 && parent->dup_cache) {
|
||||
DupliObjectData *data;
|
||||
|
||||
/* use dupli cache for realtime dupli data if possible */
|
||||
data = BKE_dupli_cache_find_data(parent->dup_cache, dob->ob);
|
||||
if (data)
|
||||
mesh = BKE_mesh_new_from_dupli_data(bmain, data, calc_tessface, calc_undeformed);
|
||||
}
|
||||
else {
|
||||
DupliObjectData data;
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
if (BKE_cache_read_dupli_object(scene, frame, eval_mode, dob->ob, &data, parent->cache_library))
|
||||
mesh = BKE_mesh_new_from_dupli_data(bmain, &data, calc_tessface, calc_undeformed);
|
||||
|
||||
BKE_dupli_object_data_clear(&data);
|
||||
}
|
||||
}
|
||||
else {
|
||||
mesh = BKE_mesh_new_from_object(bmain, scene, dob->ob, true, settings, calc_tessface, calc_undeformed);
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
static void rna_Main_meshes_remove(Main *bmain, ReportList *reports, PointerRNA *mesh_ptr)
|
||||
{
|
||||
Mesh *mesh = mesh_ptr->data;
|
||||
@@ -721,6 +780,22 @@ static void rna_Main_linestyles_remove(Main *bmain, ReportList *reports, Freesty
|
||||
/* XXX python now has invalid pointer? */
|
||||
}
|
||||
|
||||
static CacheLibrary *rna_Main_cachelibraries_new(Main *bmain, const char *name)
|
||||
{
|
||||
CacheLibrary *cachelib = BKE_cache_library_add(bmain, name);
|
||||
id_us_min(&cachelib->id);
|
||||
return cachelib;
|
||||
}
|
||||
|
||||
static void rna_Main_cachelibraries_remove(Main *bmain, ReportList *reports, CacheLibrary *cachelib)
|
||||
{
|
||||
if (ID_REAL_USERS(cachelib) <= 0)
|
||||
BKE_libblock_free(bmain, cachelib);
|
||||
else
|
||||
BKE_reportf(reports, RPT_ERROR, "Cache library '%s' must have zero users to be removed, found %d",
|
||||
cachelib->id.name + 2, ID_REAL_USERS(cachelib));
|
||||
}
|
||||
|
||||
/* tag functions, all the same */
|
||||
static void rna_Main_cameras_tag(Main *bmain, int value) { BKE_main_id_tag_listbase(&bmain->camera, value); }
|
||||
static void rna_Main_scenes_tag(Main *bmain, int value) { BKE_main_id_tag_listbase(&bmain->scene, value); }
|
||||
@@ -754,6 +829,7 @@ static void rna_Main_gpencil_tag(Main *bmain, int value) { BKE_main_id_tag_listb
|
||||
static void rna_Main_movieclips_tag(Main *bmain, int value) { BKE_main_id_tag_listbase(&bmain->movieclip, value); }
|
||||
static void rna_Main_masks_tag(Main *bmain, int value) { BKE_main_id_tag_listbase(&bmain->mask, value); }
|
||||
static void rna_Main_linestyle_tag(Main *bmain, int value) { BKE_main_id_tag_listbase(&bmain->linestyle, value); }
|
||||
static void rna_Main_cachelibraries_tag(Main *bmain, int value) { BKE_main_id_tag_listbase(&bmain->cache_library, value); }
|
||||
|
||||
static int rna_Main_cameras_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_CA) != 0; }
|
||||
static int rna_Main_scenes_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_SCE) != 0; }
|
||||
@@ -783,6 +859,7 @@ static int rna_Main_particles_is_updated_get(PointerRNA *ptr) { return DAG_id_ty
|
||||
static int rna_Main_palettes_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_PAL) != 0; }
|
||||
static int rna_Main_gpencil_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_GD) != 0; }
|
||||
static int rna_Main_linestyle_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_LS) != 0; }
|
||||
static int rna_Main_cachelibraries_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_CL) != 0; }
|
||||
|
||||
#else
|
||||
|
||||
@@ -1037,6 +1114,23 @@ void RNA_def_main_meshes(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
"Mesh created from object, remove it if it is only used for export");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func = RNA_def_function(srna, "new_from_dupli", "rna_Main_meshes_new_from_dupli");
|
||||
RNA_def_function_ui_description(func, "Add a new mesh created from dupli cache data");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene within which to evaluate modifiers");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
|
||||
parm = RNA_def_pointer(func, "parent", "Object", "", "Duplicator parent of the object");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
|
||||
parm = RNA_def_pointer(func, "dupli_object", "DupliObject", "", "Dupli Object to create mesh from");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
|
||||
parm = RNA_def_enum(func, "settings", mesh_type_items, 0, "", "Modifier settings to apply");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
RNA_def_boolean(func, "calc_tessface", true, "Calculate Tessellation", "Calculate tessellation faces");
|
||||
RNA_def_boolean(func, "calc_undeformed", false, "Calculate Undeformed", "Calculate undeformed vertex coordinates");
|
||||
parm = RNA_def_pointer(func, "mesh", "Mesh", "",
|
||||
"Mesh created from object, remove it if it is only used for export");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func = RNA_def_function(srna, "remove", "rna_Main_meshes_remove");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
RNA_def_function_ui_description(func, "Remove a mesh from the current blendfile");
|
||||
@@ -1869,4 +1963,39 @@ void RNA_def_main_linestyles(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
RNA_def_property_boolean_funcs(prop, "rna_Main_linestyle_is_updated_get", NULL);
|
||||
}
|
||||
|
||||
void RNA_def_main_cache_libraries(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
{
|
||||
StructRNA *srna;
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *parm;
|
||||
PropertyRNA *prop;
|
||||
|
||||
RNA_def_property_srna(cprop, "BlendDataCacheLibraries");
|
||||
srna = RNA_def_struct(brna, "BlendDataCacheLibraries", NULL);
|
||||
RNA_def_struct_sdna(srna, "Main");
|
||||
RNA_def_struct_ui_text(srna, "Main Cache Libraries", "Collection of cache libraries");
|
||||
|
||||
func = RNA_def_function(srna, "tag", "rna_Main_cachelibraries_tag");
|
||||
parm = RNA_def_boolean(func, "value", 0, "Value", "");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
|
||||
func = RNA_def_function(srna, "new", "rna_Main_cachelibraries_new");
|
||||
RNA_def_function_ui_description(func, "Add a new cache library to the main database");
|
||||
parm = RNA_def_string(func, "name", "CacheLibrary", 0, "", "New name for the datablock");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
/* return type */
|
||||
parm = RNA_def_pointer(func, "cachelib", "CacheLibrary", "", "New cache library datablock");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func = RNA_def_function(srna, "remove", "rna_Main_cachelibraries_remove");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
RNA_def_function_ui_description(func, "Remove a cache library from the current blendfile");
|
||||
parm = RNA_def_pointer(func, "cachelib", "CacheLibrary", "", "Cache Library to remove");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
|
||||
prop = RNA_def_property(srna, "is_updated", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_boolean_funcs(prop, "rna_Main_cachelibraries_is_updated_get", NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -65,6 +65,7 @@ EnumPropertyItem modifier_type_items[] = {
|
||||
{0, "", 0, N_("Modify"), ""},
|
||||
{eModifierType_DataTransfer, "DATA_TRANSFER", ICON_MOD_DATA_TRANSFER, "Data Transfer", ""},
|
||||
{eModifierType_MeshCache, "MESH_CACHE", ICON_MOD_MESHDEFORM, "Mesh Cache", ""},
|
||||
{eModifierType_Cache, "CACHE", ICON_MOD_MESHDEFORM, "Cache", ""},
|
||||
{eModifierType_NormalEdit, "NORMAL_EDIT", ICON_MOD_NORMALEDIT, "Normal Edit", ""},
|
||||
{eModifierType_UVProject, "UV_PROJECT", ICON_MOD_UVPROJECT, "UV Project", ""},
|
||||
{eModifierType_UVWarp, "UV_WARP", ICON_MOD_UVPROJECT, "UV Warp", ""},
|
||||
@@ -377,6 +378,8 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
|
||||
return &RNA_DataTransferModifier;
|
||||
case eModifierType_NormalEdit:
|
||||
return &RNA_NormalEditModifier;
|
||||
case eModifierType_Cache:
|
||||
return &RNA_CacheModifier;
|
||||
/* Default */
|
||||
case eModifierType_None:
|
||||
case eModifierType_ShapeKey:
|
||||
@@ -2498,7 +2501,7 @@ static void rna_def_modifier_cloth(BlenderRNA *brna)
|
||||
RNA_def_property_struct_type(prop, "ClothSolverResult");
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "solver_result");
|
||||
RNA_def_property_ui_text(prop, "Solver Result", "");
|
||||
|
||||
|
||||
prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_NEVER_NULL);
|
||||
RNA_def_property_ui_text(prop, "Point Cache", "");
|
||||
@@ -4438,6 +4441,16 @@ static void rna_def_modifier_normaledit(BlenderRNA *brna)
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
}
|
||||
|
||||
static void rna_def_modifier_cache(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
srna = RNA_def_struct(brna, "CacheModifier", "Modifier");
|
||||
RNA_def_struct_ui_text(srna, "Cache Modifier", "Write and Read mesh results to/from cache libraries");
|
||||
RNA_def_struct_sdna(srna, "CacheModifierData");
|
||||
RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM); /* XXX, needs own icon */
|
||||
}
|
||||
|
||||
void RNA_def_modifier(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@@ -4553,6 +4566,7 @@ void RNA_def_modifier(BlenderRNA *brna)
|
||||
rna_def_modifier_wireframe(brna);
|
||||
rna_def_modifier_datatransfer(brna);
|
||||
rna_def_modifier_normaledit(brna);
|
||||
rna_def_modifier_cache(brna);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -2634,6 +2634,17 @@ static void rna_def_object(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Dupli Faces Scale", "Scale the DupliFace objects");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_dupli_cache_read", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "transflag", OB_DUPLI_READ_CACHE);
|
||||
RNA_def_property_ui_text(prop, "Read Dupli Cache", "Use cached data instead of object data");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_dependency_update");
|
||||
|
||||
/* note: inversion of use_dupli_cache_read, for enum-like mode switch */
|
||||
prop = RNA_def_property(srna, "use_dupli_cache_write", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "transflag", OB_DUPLI_READ_CACHE);
|
||||
RNA_def_property_ui_text(prop, "Write Dupli Cache", "Enabling writing of dupli cache data");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_dependency_update");
|
||||
|
||||
prop = RNA_def_property(srna, "dupli_group", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "dup_group");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
@@ -2641,6 +2652,12 @@ static void rna_def_object(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Dupli Group", "Instance an existing group");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_dependency_update");
|
||||
|
||||
prop = RNA_def_property(srna, "cache_library", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "cache_library");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Cache Library", "Cache Library to use");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_dependency_update");
|
||||
|
||||
prop = RNA_def_property(srna, "dupli_frames_start", PROP_INT, PROP_NONE | PROP_UNIT_TIME);
|
||||
RNA_def_property_int_sdna(prop, NULL, "dupsta");
|
||||
RNA_def_property_range(prop, MINAFRAME, MAXFRAME);
|
||||
@@ -2847,6 +2864,16 @@ static void rna_def_dupli_object(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Dupli Type", "Duplicator type that generated this dupli object");
|
||||
}
|
||||
|
||||
static void rna_def_dupli_object_data(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
/*PropertyRNA *prop;*/
|
||||
|
||||
srna = RNA_def_struct(brna, "DupliObjectData", NULL);
|
||||
RNA_def_struct_sdna(srna, "DupliObjectData");
|
||||
RNA_def_struct_ui_text(srna, "Object Duplicate Data", "Override of object data for duplis");
|
||||
}
|
||||
|
||||
static void rna_def_object_base(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@@ -2893,6 +2920,7 @@ void RNA_def_object(BlenderRNA *brna)
|
||||
rna_def_vertex_group(brna);
|
||||
rna_def_material_slot(brna);
|
||||
rna_def_dupli_object(brna);
|
||||
rna_def_dupli_object_data(brna);
|
||||
RNA_define_animate_sdna(true);
|
||||
rna_def_object_lodlevel(brna);
|
||||
}
|
||||
|
@@ -222,6 +222,18 @@ static void rna_Object_free_duplilist(Object *ob)
|
||||
}
|
||||
}
|
||||
|
||||
static PointerRNA rna_Object_find_dupli_cache(Object *ob, Object *dupob)
|
||||
{
|
||||
DupliObjectData *data = NULL;
|
||||
PointerRNA ptr;
|
||||
|
||||
if (ob->dup_cache)
|
||||
data = BKE_dupli_cache_find_data(ob->dup_cache, dupob);
|
||||
|
||||
RNA_pointer_create((ID *)ob, &RNA_DupliObjectData, data, &ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static PointerRNA rna_Object_shape_key_add(Object *ob, bContext *C, ReportList *reports,
|
||||
const char *name, int from_mix)
|
||||
{
|
||||
@@ -547,6 +559,14 @@ void RNA_api_object(StructRNA *srna)
|
||||
func = RNA_def_function(srna, "dupli_list_clear", "rna_Object_free_duplilist");
|
||||
RNA_def_function_ui_description(func, "Free the list of dupli objects");
|
||||
|
||||
func = RNA_def_function(srna, "find_dupli_cache", "rna_Object_find_dupli_cache");
|
||||
RNA_def_function_ui_description(func, "Find cached data for a dupli object");
|
||||
parm = RNA_def_pointer(func, "object", "Object", "", "Object data to look up");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
|
||||
parm = RNA_def_pointer(func, "data", "DupliObjectData", "", "Cached object data");
|
||||
RNA_def_property_flag(parm, PROP_RNAPTR);
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
/* Armature */
|
||||
func = RNA_def_function(srna, "find_armature", "modifiers_isDeformedByArmature");
|
||||
RNA_def_function_ui_description(func, "Find armature influencing this object as a parent or via a modifier");
|
||||
|
@@ -899,6 +899,19 @@ void RNA_api_ui_layout(StructRNA *srna)
|
||||
RNA_def_function_ui_description(func, "Node Socket Icon");
|
||||
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
|
||||
RNA_def_float_array(func, "color", 4, node_socket_color_default, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f);
|
||||
|
||||
/* cache library item */
|
||||
func = RNA_def_function(srna, "template_cache_library_item", "uiTemplateCacheLibraryItem");
|
||||
RNA_def_function_ui_description(func, "Cache Library Item");
|
||||
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
|
||||
RNA_def_pointer(func, "cachelib", "CacheLibrary", "Cache Library", "Cache library containing the item");
|
||||
RNA_def_pointer(func, "object", "Object", "Object", "Object to cache");
|
||||
parm = RNA_def_enum(func, "type", cache_library_item_type_items, 0, "Type", "Type of cached data");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
RNA_def_int(func, "index", -1, -1, INT_MAX, "Index", "Index of cached data", -1, INT_MAX);
|
||||
RNA_def_boolean(func, "enabled", true, "Enabled", "Enable the item");
|
||||
parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in");
|
||||
RNA_def_function_return(func, parm);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -33,6 +33,7 @@ set(INC
|
||||
../makesdna
|
||||
../makesrna
|
||||
../bmesh
|
||||
../pointcache
|
||||
../render/extern/include
|
||||
../../../intern/elbeem/extern
|
||||
../../../intern/guardedalloc
|
||||
@@ -77,6 +78,7 @@ set(SRC
|
||||
intern/MOD_ocean.c
|
||||
intern/MOD_particleinstance.c
|
||||
intern/MOD_particlesystem.c
|
||||
intern/MOD_cache.c
|
||||
intern/MOD_remesh.c
|
||||
intern/MOD_screw.c
|
||||
intern/MOD_shapekey.c
|
||||
|
@@ -83,6 +83,7 @@ extern ModifierTypeInfo modifierType_LaplacianDeform;
|
||||
extern ModifierTypeInfo modifierType_Wireframe;
|
||||
extern ModifierTypeInfo modifierType_DataTransfer;
|
||||
extern ModifierTypeInfo modifierType_NormalEdit;
|
||||
extern ModifierTypeInfo modifierType_Cache;
|
||||
|
||||
/* MOD_util.c */
|
||||
void modifier_type_init(ModifierTypeInfo *types[]);
|
||||
|
@@ -44,6 +44,7 @@ incs = [
|
||||
'../makesrna',
|
||||
'../blenkernel',
|
||||
'../gpu',
|
||||
'../pointcache',
|
||||
env['BF_ZLIB_INC'],
|
||||
]
|
||||
|
||||
|
231
source/blender/modifiers/intern/MOD_cache.c
Normal file
231
source/blender/modifiers/intern/MOD_cache.c
Normal file
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* ***** 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): Lukas Toenne
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/modifiers/intern/MOD_cache.c
|
||||
* \ingroup modifiers
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "DNA_customdata_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
|
||||
#include "BKE_cdderivedmesh.h"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_main.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "MOD_modifiertypes.h"
|
||||
|
||||
#include "MOD_util.h"
|
||||
|
||||
struct BMEditMesh;
|
||||
|
||||
static void initData(ModifierData *UNUSED(md))
|
||||
{
|
||||
/*CacheModifierData *pcmd = (CacheModifierData *)md;*/
|
||||
}
|
||||
|
||||
static void copyData(ModifierData *md, ModifierData *target)
|
||||
{
|
||||
/*CacheModifierData *pcmd = (CacheModifierData *)md;*/
|
||||
CacheModifierData *tpcmd = (CacheModifierData *)target;
|
||||
|
||||
modifier_copyData_generic(md, target);
|
||||
|
||||
tpcmd->output_dm = NULL;
|
||||
tpcmd->input_dm = NULL;
|
||||
tpcmd->flag &= ~(MOD_CACHE_USE_OUTPUT_REALTIME | MOD_CACHE_USE_OUTPUT_RENDER);
|
||||
}
|
||||
|
||||
static void freeData(ModifierData *md)
|
||||
{
|
||||
CacheModifierData *pcmd = (CacheModifierData *)md;
|
||||
|
||||
if (pcmd->output_dm) {
|
||||
pcmd->output_dm->release(pcmd->output_dm);
|
||||
pcmd->output_dm = NULL;
|
||||
}
|
||||
if (pcmd->input_dm) {
|
||||
pcmd->input_dm->release(pcmd->input_dm);
|
||||
pcmd->input_dm = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static bool *store_nocopy_flags(CustomData *cdata)
|
||||
{
|
||||
if (cdata) {
|
||||
int totlayer = cdata->totlayer;
|
||||
bool *nocopy = MEM_mallocN(sizeof(bool) * totlayer, "customdata nocopy flags");
|
||||
CustomDataLayer *layer;
|
||||
int i;
|
||||
|
||||
for (i = 0, layer = cdata->layers; i < totlayer; ++i, ++layer) {
|
||||
nocopy[i] = layer->flag & CD_FLAG_NOCOPY;
|
||||
layer->flag &= ~CD_FLAG_NOCOPY;
|
||||
}
|
||||
|
||||
return nocopy;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void restore_nocopy_flags(CustomData *cdata, bool *nocopy)
|
||||
{
|
||||
if (cdata && nocopy) {
|
||||
int totlayer = cdata->totlayer;
|
||||
CustomDataLayer *layer;
|
||||
int i;
|
||||
|
||||
for (i = 0, layer = cdata->layers; i < totlayer; ++i, ++layer) {
|
||||
if (nocopy[i])
|
||||
layer->flag |= CD_FLAG_NOCOPY;
|
||||
else
|
||||
layer->flag &= ~CD_FLAG_NOCOPY;
|
||||
}
|
||||
}
|
||||
|
||||
if (nocopy)
|
||||
MEM_freeN(nocopy);
|
||||
}
|
||||
|
||||
static DerivedMesh *pointcache_do(CacheModifierData *pcmd, Object *UNUSED(ob), DerivedMesh *dm, ModifierApplyFlag flag)
|
||||
{
|
||||
bool use_output;
|
||||
|
||||
if (!(flag & MOD_APPLY_USECACHE))
|
||||
return dm;
|
||||
|
||||
use_output = (flag & MOD_APPLY_RENDER) ? (pcmd->flag & MOD_CACHE_USE_OUTPUT_RENDER) : (pcmd->flag & MOD_CACHE_USE_OUTPUT_REALTIME);
|
||||
if (use_output) {
|
||||
if (pcmd->output_dm) {
|
||||
pcmd->output_dm->release(pcmd->output_dm);
|
||||
}
|
||||
|
||||
/* XXX HACK!
|
||||
* DM copy will ignore all layers with CD_FLAG_NOCOPY set.
|
||||
* This include layers that are needed by subsequent modifiers,
|
||||
* which works for the modifier stack eval because DMs are passed
|
||||
* down the chain directly. Making a copy for keeping the DM for the
|
||||
* writer will discard those layers, so we have to temporarily disable
|
||||
* the NOCOPY flags ...
|
||||
*
|
||||
* Probably a better way of writing out temporary data could help
|
||||
*/
|
||||
{
|
||||
CustomData *vdata = dm->getVertDataLayout(dm);
|
||||
CustomData *edata = dm->getEdgeDataLayout(dm);
|
||||
CustomData *fdata = dm->getTessFaceDataLayout(dm);
|
||||
CustomData *pdata = dm->getPolyDataLayout(dm);
|
||||
CustomData *ldata = dm->getLoopDataLayout(dm);
|
||||
bool *vdata_nocopy = store_nocopy_flags(vdata);
|
||||
bool *edata_nocopy = store_nocopy_flags(edata);
|
||||
bool *fdata_nocopy = store_nocopy_flags(fdata);
|
||||
bool *pdata_nocopy = store_nocopy_flags(pdata);
|
||||
bool *ldata_nocopy = store_nocopy_flags(ldata);
|
||||
|
||||
pcmd->output_dm = CDDM_copy(dm);
|
||||
|
||||
restore_nocopy_flags(vdata, vdata_nocopy);
|
||||
restore_nocopy_flags(edata, edata_nocopy);
|
||||
restore_nocopy_flags(fdata, fdata_nocopy);
|
||||
restore_nocopy_flags(pdata, pdata_nocopy);
|
||||
restore_nocopy_flags(ldata, ldata_nocopy);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* unused cache output? clean up! */
|
||||
if (pcmd->output_dm) {
|
||||
pcmd->output_dm->release(pcmd->output_dm);
|
||||
pcmd->output_dm = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (pcmd->input_dm) {
|
||||
/* pass on the input DM from the cache */
|
||||
dm = pcmd->input_dm;
|
||||
pcmd->input_dm = NULL;
|
||||
}
|
||||
|
||||
return dm;
|
||||
}
|
||||
|
||||
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
|
||||
DerivedMesh *dm,
|
||||
ModifierApplyFlag flag)
|
||||
{
|
||||
CacheModifierData *pcmd = (CacheModifierData *)md;
|
||||
|
||||
return pointcache_do(pcmd, ob, dm, flag);
|
||||
}
|
||||
|
||||
static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
|
||||
struct BMEditMesh *UNUSED(editData),
|
||||
DerivedMesh *dm,
|
||||
ModifierApplyFlag flag)
|
||||
{
|
||||
CacheModifierData *pcmd = (CacheModifierData *)md;
|
||||
|
||||
return pointcache_do(pcmd, ob, dm, flag);
|
||||
}
|
||||
|
||||
ModifierTypeInfo modifierType_Cache = {
|
||||
/* name */ "Cache",
|
||||
/* structName */ "CacheModifierData",
|
||||
/* structSize */ sizeof(CacheModifierData),
|
||||
/* type */ eModifierTypeType_Constructive,
|
||||
/* flags */ eModifierTypeFlag_AcceptsMesh |
|
||||
eModifierTypeFlag_AcceptsCVs |
|
||||
eModifierTypeFlag_SupportsEditmode,
|
||||
|
||||
/* copyData */ copyData,
|
||||
/* deformVerts */ NULL,
|
||||
/* deformMatrices */ NULL,
|
||||
/* deformVertsEM */ NULL,
|
||||
/* deformMatricesEM */ NULL,
|
||||
/* applyModifier */ applyModifier,
|
||||
/* applyModifierEM */ applyModifierEM,
|
||||
/* initData */ initData,
|
||||
/* requiredDataMask */ NULL,
|
||||
/* freeData */ freeData,
|
||||
/* isDisabled */ NULL,
|
||||
/* updateDepgraph */ NULL,
|
||||
/* dependsOnTime */ NULL,
|
||||
/* dependsOnNormals */ NULL,
|
||||
/* foreachObjectLink */ NULL,
|
||||
/* foreachIDLink */ NULL,
|
||||
/* foreachTexLink */ NULL,
|
||||
};
|
@@ -306,5 +306,6 @@ void modifier_type_init(ModifierTypeInfo *types[])
|
||||
INIT_TYPE(Wireframe);
|
||||
INIT_TYPE(DataTransfer);
|
||||
INIT_TYPE(NormalEdit);
|
||||
INIT_TYPE(Cache);
|
||||
#undef INIT_TYPE
|
||||
}
|
||||
|
61
source/blender/pointcache/CMakeLists.txt
Normal file
61
source/blender/pointcache/CMakeLists.txt
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.
|
||||
#
|
||||
# The Original Code is Copyright (C) 2013, Blender Foundation
|
||||
# All rights reserved.
|
||||
#
|
||||
# The Original Code is: all of this file.
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
set(INC
|
||||
.
|
||||
intern
|
||||
util
|
||||
../blenkernel
|
||||
../blenlib
|
||||
../makesdna
|
||||
../makesrna
|
||||
../../../intern/guardedalloc
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
)
|
||||
|
||||
set(SRC
|
||||
intern/export.h
|
||||
intern/export.cpp
|
||||
intern/ptc_types.h
|
||||
intern/ptc_types.cpp
|
||||
intern/reader.h
|
||||
intern/reader.cpp
|
||||
intern/writer.h
|
||||
intern/writer.cpp
|
||||
|
||||
util/util_error_handler.h
|
||||
util/util_error_handler.cpp
|
||||
util/util_types.h
|
||||
|
||||
PTC_api.h
|
||||
PTC_api.cpp
|
||||
)
|
||||
|
||||
if(WITH_ALEMBIC)
|
||||
add_definitions(-DWITH_PTC_ALEMBIC)
|
||||
add_subdirectory(alembic)
|
||||
endif()
|
||||
|
||||
blender_add_lib(bf_pointcache "${SRC}" "${INC}" "${INC_SYS}")
|
408
source/blender/pointcache/PTC_api.cpp
Normal file
408
source/blender/pointcache/PTC_api.cpp
Normal file
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
* Copyright 2013, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "PTC_api.h"
|
||||
|
||||
#include "util/util_error_handler.h"
|
||||
|
||||
#include "reader.h"
|
||||
#include "writer.h"
|
||||
#include "export.h"
|
||||
|
||||
#include "ptc_types.h"
|
||||
|
||||
extern "C" {
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
|
||||
#include "DNA_listBase.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_report.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
}
|
||||
|
||||
using namespace PTC;
|
||||
|
||||
void PTC_error_handler_std(void)
|
||||
{
|
||||
ErrorHandler::clear_default_handler();
|
||||
}
|
||||
|
||||
void PTC_error_handler_callback(PTCErrorCallback cb, void *userdata)
|
||||
{
|
||||
ErrorHandler::set_default_handler(new CallbackErrorHandler(cb, userdata));
|
||||
}
|
||||
|
||||
static ReportType report_type_from_error_level(PTCErrorLevel level)
|
||||
{
|
||||
switch (level) {
|
||||
case PTC_ERROR_NONE: return RPT_DEBUG;
|
||||
case PTC_ERROR_INFO: return RPT_INFO;
|
||||
case PTC_ERROR_WARNING: return RPT_WARNING;
|
||||
case PTC_ERROR_CRITICAL: return RPT_ERROR;
|
||||
}
|
||||
return RPT_ERROR;
|
||||
}
|
||||
|
||||
static void error_handler_reports_cb(void *vreports, PTCErrorLevel level, const char *message)
|
||||
{
|
||||
ReportList *reports = (ReportList *)vreports;
|
||||
|
||||
BKE_report(reports, report_type_from_error_level(level), message);
|
||||
}
|
||||
|
||||
void PTC_error_handler_reports(struct ReportList *reports)
|
||||
{
|
||||
ErrorHandler::set_default_handler(new CallbackErrorHandler(error_handler_reports_cb, reports));
|
||||
}
|
||||
|
||||
static void error_handler_modifier_cb(void *vmd, PTCErrorLevel UNUSED(level), const char *message)
|
||||
{
|
||||
ModifierData *md = (ModifierData *)vmd;
|
||||
|
||||
modifier_setError(md, "%s", message);
|
||||
}
|
||||
|
||||
void PTC_error_handler_modifier(struct ModifierData *md)
|
||||
{
|
||||
ErrorHandler::set_default_handler(new CallbackErrorHandler(error_handler_modifier_cb, md));
|
||||
}
|
||||
|
||||
|
||||
const char *PTC_get_default_archive_extension(void)
|
||||
{
|
||||
return PTC::Factory::alembic->get_default_extension().c_str();
|
||||
}
|
||||
|
||||
PTCWriterArchive *PTC_open_writer_archive(Scene *scene, const char *path)
|
||||
{
|
||||
return (PTCWriterArchive *)PTC::Factory::alembic->open_writer_archive(scene, path, NULL);
|
||||
}
|
||||
|
||||
void PTC_close_writer_archive(PTCWriterArchive *_archive)
|
||||
{
|
||||
PTC::WriterArchive *archive = (PTC::WriterArchive *)_archive;
|
||||
delete archive;
|
||||
}
|
||||
|
||||
void PTC_writer_archive_use_render(PTCWriterArchive *_archive, bool enable)
|
||||
{
|
||||
PTC::WriterArchive *archive = (PTC::WriterArchive *)_archive;
|
||||
archive->use_render(enable);
|
||||
}
|
||||
|
||||
PTCReaderArchive *PTC_open_reader_archive(Scene *scene, const char *path)
|
||||
{
|
||||
return (PTCReaderArchive *)PTC::Factory::alembic->open_reader_archive(scene, path, NULL);
|
||||
}
|
||||
|
||||
void PTC_close_reader_archive(PTCReaderArchive *_archive)
|
||||
{
|
||||
PTC::ReaderArchive *archive = (PTC::ReaderArchive *)_archive;
|
||||
delete archive;
|
||||
}
|
||||
|
||||
void PTC_reader_archive_use_render(PTCReaderArchive *_archive, bool enable)
|
||||
{
|
||||
PTC::ReaderArchive *archive = (PTC::ReaderArchive *)_archive;
|
||||
archive->use_render(enable);
|
||||
}
|
||||
|
||||
void PTC_writer_init(PTCWriter *_writer, PTCWriterArchive *_archive)
|
||||
{
|
||||
PTC::Writer *writer = (PTC::Writer *)_writer;
|
||||
PTC::WriterArchive *archive = (PTC::WriterArchive *)_archive;
|
||||
writer->init(archive);
|
||||
}
|
||||
|
||||
void PTC_writer_create_refs(PTCWriter *_writer)
|
||||
{
|
||||
PTC::Writer *writer = (PTC::Writer *)_writer;
|
||||
writer->create_refs();
|
||||
}
|
||||
|
||||
void PTC_reader_init(PTCReader *_reader, PTCReaderArchive *_archive)
|
||||
{
|
||||
PTC::Reader *reader = (PTC::Reader *)_reader;
|
||||
PTC::ReaderArchive *archive = (PTC::ReaderArchive *)_archive;
|
||||
reader->init(archive);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
void PTC_writer_free(PTCWriter *_writer)
|
||||
{
|
||||
PTC::Writer *writer = (PTC::Writer *)_writer;
|
||||
delete writer;
|
||||
}
|
||||
|
||||
void PTC_write_sample(struct PTCWriter *_writer)
|
||||
{
|
||||
PTC::Writer *writer = (PTC::Writer *)_writer;
|
||||
writer->write_sample();
|
||||
}
|
||||
|
||||
void PTC_bake(struct Main *bmain, struct Scene *scene, struct EvaluationContext *evalctx,
|
||||
PTCWriter *writer, int start_frame, int end_frame,
|
||||
short *stop, short *do_update, float *progress)
|
||||
{
|
||||
PTC::Exporter exporter(bmain, scene, evalctx, stop, do_update, progress);
|
||||
exporter.bake(writer, start_frame, end_frame);
|
||||
}
|
||||
|
||||
|
||||
void PTC_reader_free(PTCReader *_reader)
|
||||
{
|
||||
PTC::Reader *reader = (PTC::Reader *)_reader;
|
||||
delete reader;
|
||||
}
|
||||
|
||||
bool PTC_reader_get_frame_range(PTCReader *_reader, int *start_frame, int *end_frame)
|
||||
{
|
||||
PTC::Reader *reader = (PTC::Reader *)_reader;
|
||||
int sfra, efra;
|
||||
if (reader->get_frame_range(sfra, efra)) {
|
||||
if (start_frame) *start_frame = sfra;
|
||||
if (end_frame) *end_frame = efra;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
PTCReadSampleResult PTC_read_sample(PTCReader *_reader, float frame)
|
||||
{
|
||||
PTC::Reader *reader = (PTC::Reader *)_reader;
|
||||
return reader->read_sample(frame);
|
||||
}
|
||||
|
||||
PTCReadSampleResult PTC_test_sample(PTCReader *_reader, float frame)
|
||||
{
|
||||
PTC::Reader *reader = (PTC::Reader *)_reader;
|
||||
return reader->test_sample(frame);
|
||||
}
|
||||
|
||||
char *PTC_get_archive_info(PTCReaderArchive *_archive)
|
||||
{
|
||||
PTC::ReaderArchive *archive = (PTC::ReaderArchive *)_archive;
|
||||
|
||||
std::string info = archive->get_info();
|
||||
return BLI_sprintfN("%s", info.c_str());
|
||||
}
|
||||
|
||||
|
||||
PTCWriter *PTC_writer_dupligroup(const char *name, struct EvaluationContext *eval_ctx, struct Scene *scene, struct Group *group, struct CacheLibrary *cachelib)
|
||||
{
|
||||
return (PTCWriter *)PTC::Factory::alembic->create_writer_dupligroup(name, eval_ctx, scene, group, cachelib);
|
||||
}
|
||||
|
||||
PTCReader *PTC_reader_duplicache(const char *name, struct Group *group, struct DupliCache *dupcache)
|
||||
{
|
||||
return (PTCReader *)PTC::Factory::alembic->create_reader_duplicache(name, group, dupcache);
|
||||
}
|
||||
|
||||
PTCReader *PTC_reader_duplicache_object(const char *name, struct Object *ob, struct DupliObjectData *data)
|
||||
{
|
||||
return (PTCReader *)PTC::Factory::alembic->create_reader_duplicache_object(name, ob, data);
|
||||
}
|
||||
|
||||
|
||||
/* get writer/reader from RNA type */
|
||||
PTCWriter *PTC_writer_from_rna(Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
#if 0
|
||||
#if 0
|
||||
if (RNA_struct_is_a(ptr->type, &RNA_ParticleSystem)) {
|
||||
Object *ob = (Object *)ptr->id.data;
|
||||
ParticleSystem *psys = (ParticleSystem *)ptr->data;
|
||||
return PTC_writer_particles_combined(scene, ob, psys);
|
||||
}
|
||||
#endif
|
||||
if (RNA_struct_is_a(ptr->type, &RNA_ClothModifier)) {
|
||||
Object *ob = (Object *)ptr->id.data;
|
||||
ClothModifierData *clmd = (ClothModifierData *)ptr->data;
|
||||
return PTC_writer_cloth(scene, ob, clmd);
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PTCReader *PTC_reader_from_rna(Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
#if 0
|
||||
if (RNA_struct_is_a(ptr->type, &RNA_ParticleSystem)) {
|
||||
Object *ob = (Object *)ptr->id.data;
|
||||
ParticleSystem *psys = (ParticleSystem *)ptr->data;
|
||||
/* XXX particles are bad ...
|
||||
* this can be either the actual particle cache or the hair dynamics cache,
|
||||
* which is actually the cache of the internal cloth modifier
|
||||
*/
|
||||
bool use_cloth_cache = psys->part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DYNAMICS);
|
||||
if (use_cloth_cache && psys->clmd)
|
||||
return PTC_reader_cloth(scene, ob, psys->clmd);
|
||||
else
|
||||
return PTC_reader_particles(scene, ob, psys);
|
||||
}
|
||||
if (RNA_struct_is_a(ptr->type, &RNA_ClothModifier)) {
|
||||
Object *ob = (Object *)ptr->id.data;
|
||||
ClothModifierData *clmd = (ClothModifierData *)ptr->data;
|
||||
return PTC_reader_cloth(scene, ob, clmd);
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* ==== CLOTH ==== */
|
||||
|
||||
PTCWriter *PTC_writer_cloth(const char *name, Object *ob, ClothModifierData *clmd)
|
||||
{
|
||||
return (PTCWriter *)PTC::Factory::alembic->create_writer_cloth(name, ob, clmd);
|
||||
}
|
||||
|
||||
PTCReader *PTC_reader_cloth(const char *name, Object *ob, ClothModifierData *clmd)
|
||||
{
|
||||
return (PTCReader *)PTC::Factory::alembic->create_reader_cloth(name, ob, clmd);
|
||||
}
|
||||
|
||||
|
||||
/* ==== MESH ==== */
|
||||
|
||||
PTCWriter *PTC_writer_derived_mesh(const char *name, Object *ob, DerivedMesh **dm_ptr)
|
||||
{
|
||||
return (PTCWriter *)PTC::Factory::alembic->create_writer_derived_mesh(name, ob, dm_ptr);
|
||||
}
|
||||
|
||||
PTCReader *PTC_reader_derived_mesh(const char *name, Object *ob)
|
||||
{
|
||||
return (PTCReader *)PTC::Factory::alembic->create_reader_derived_mesh(name, ob);
|
||||
}
|
||||
|
||||
struct DerivedMesh *PTC_reader_derived_mesh_acquire_result(PTCReader *_reader)
|
||||
{
|
||||
DerivedMeshReader *reader = (DerivedMeshReader *)_reader;
|
||||
return reader->acquire_result();
|
||||
}
|
||||
|
||||
void PTC_reader_derived_mesh_discard_result(PTCReader *_reader)
|
||||
{
|
||||
DerivedMeshReader *reader = (DerivedMeshReader *)_reader;
|
||||
reader->discard_result();
|
||||
}
|
||||
|
||||
|
||||
PTCWriter *PTC_writer_derived_final_realtime(const char *name, Object *ob)
|
||||
{
|
||||
return (PTCWriter *)PTC::Factory::alembic->create_writer_derived_final_realtime(name, ob);
|
||||
}
|
||||
|
||||
PTCWriter *PTC_writer_cache_modifier_realtime(const char *name, Object *ob, CacheModifierData *cmd)
|
||||
{
|
||||
return (PTCWriter *)PTC::Factory::alembic->create_writer_cache_modifier_realtime(name, ob, cmd);
|
||||
}
|
||||
|
||||
PTCWriter *PTC_writer_derived_final_render(const char *name, Scene *scene, Object *ob, DerivedMesh **render_dm_ptr)
|
||||
{
|
||||
return (PTCWriter *)PTC::Factory::alembic->create_writer_derived_final_render(name, scene, ob, render_dm_ptr);
|
||||
}
|
||||
|
||||
PTCWriter *PTC_writer_cache_modifier_render(const char *name, Scene *scene, Object *ob, CacheModifierData *cmd)
|
||||
{
|
||||
return (PTCWriter *)PTC::Factory::alembic->create_writer_cache_modifier_render(name, scene, ob, cmd);
|
||||
}
|
||||
|
||||
|
||||
/* ==== OBJECT ==== */
|
||||
|
||||
PTCWriter *PTC_writer_object(const char *name, Scene *scene, Object *ob)
|
||||
{
|
||||
return (PTCWriter *)PTC::Factory::alembic->create_writer_object(name, scene, ob);
|
||||
}
|
||||
|
||||
PTCReader *PTC_reader_object(const char *name, Object *ob)
|
||||
{
|
||||
return (PTCReader *)PTC::Factory::alembic->create_reader_object(name, ob);
|
||||
}
|
||||
|
||||
|
||||
/* ==== GROUP ==== */
|
||||
|
||||
PTCWriter *PTC_writer_group(const char *name, Group *group)
|
||||
{
|
||||
return (PTCWriter *)PTC::Factory::alembic->create_writer_group(name, group);
|
||||
}
|
||||
|
||||
PTCReader *PTC_reader_group(const char *name, Group *group)
|
||||
{
|
||||
return (PTCReader *)PTC::Factory::alembic->create_writer_group(name, group);
|
||||
}
|
||||
|
||||
|
||||
/* ==== PARTICLES ==== */
|
||||
|
||||
PTCWriter *PTC_writer_particles(const char *name, Object *ob, ParticleSystem *psys)
|
||||
{
|
||||
return (PTCWriter *)PTC::Factory::alembic->create_writer_particles(name, ob, psys);
|
||||
}
|
||||
|
||||
PTCReader *PTC_reader_particles(const char *name, Object *ob, ParticleSystem *psys)
|
||||
{
|
||||
return (PTCReader *)PTC::Factory::alembic->create_reader_particles(name, ob, psys);
|
||||
}
|
||||
|
||||
int PTC_reader_particles_totpoint(PTCReader *_reader)
|
||||
{
|
||||
return ((PTC::ParticlesReader *)_reader)->totpoint();
|
||||
}
|
||||
|
||||
PTCWriter *PTC_writer_hair_dynamics(const char *name, Object *ob, ParticleSystem *psys)
|
||||
{
|
||||
return (PTCWriter *)PTC::Factory::alembic->create_writer_hair_dynamics(name, ob, psys);
|
||||
}
|
||||
|
||||
PTCReader *PTC_reader_hair_dynamics(const char *name, Object *ob, ParticleSystem *psys)
|
||||
{
|
||||
return (PTCReader *)PTC::Factory::alembic->create_reader_hair_dynamics(name, ob, psys);
|
||||
}
|
||||
|
||||
PTCWriter *PTC_writer_particles_pathcache_parents(const char *name, Object *ob, ParticleSystem *psys)
|
||||
{
|
||||
return (PTCWriter *)PTC::Factory::alembic->create_writer_particles_pathcache_parents(name, ob, psys);
|
||||
}
|
||||
|
||||
PTCReader *PTC_reader_particles_pathcache_parents(const char *name, Object *ob, ParticleSystem *psys)
|
||||
{
|
||||
return (PTCReader *)PTC::Factory::alembic->create_reader_particles_pathcache_parents(name, ob, psys);
|
||||
}
|
||||
|
||||
PTCWriter *PTC_writer_particles_pathcache_children(const char *name, Object *ob, ParticleSystem *psys)
|
||||
{
|
||||
return (PTCWriter *)PTC::Factory::alembic->create_writer_particles_pathcache_children(name, ob, psys);
|
||||
}
|
||||
|
||||
PTCReader *PTC_reader_particles_pathcache_children(const char *name, Object *ob, ParticleSystem *psys)
|
||||
{
|
||||
return (PTCReader *)PTC::Factory::alembic->create_reader_particles_pathcache_children(name, ob, psys);
|
||||
}
|
137
source/blender/pointcache/PTC_api.h
Normal file
137
source/blender/pointcache/PTC_api.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2013, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef PTC_API_H
|
||||
#define PTC_API_H
|
||||
|
||||
#include "util/util_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct Main;
|
||||
struct Scene;
|
||||
struct EvaluationContext;
|
||||
struct ListBase;
|
||||
struct PointerRNA;
|
||||
struct ReportList;
|
||||
|
||||
struct DupliCache;
|
||||
struct ClothModifierData;
|
||||
struct DerivedMesh;
|
||||
struct Group;
|
||||
struct ModifierData;
|
||||
struct Object;
|
||||
struct ParticleSystem;
|
||||
struct CacheModifierData;
|
||||
struct SoftBody;
|
||||
|
||||
struct PTCWriterArchive;
|
||||
struct PTCReaderArchive;
|
||||
struct PTCWriter;
|
||||
struct PTCReader;
|
||||
|
||||
void PTC_alembic_init(void);
|
||||
|
||||
/*** Error Handling ***/
|
||||
void PTC_error_handler_std(void);
|
||||
void PTC_error_handler_callback(PTCErrorCallback cb, void *userdata);
|
||||
void PTC_error_handler_reports(struct ReportList *reports);
|
||||
void PTC_error_handler_modifier(struct ModifierData *md);
|
||||
|
||||
void PTC_bake(struct Main *bmain, struct Scene *scene, struct EvaluationContext *evalctx,
|
||||
struct PTCWriter *writer, int start_frame, int end_frame,
|
||||
short *stop, short *do_update, float *progress);
|
||||
|
||||
/*** Archive ***/
|
||||
|
||||
const char *PTC_get_default_archive_extension(void);
|
||||
|
||||
struct PTCWriterArchive *PTC_open_writer_archive(struct Scene *scene, const char *path);
|
||||
void PTC_close_writer_archive(struct PTCWriterArchive *archive);
|
||||
void PTC_writer_archive_use_render(struct PTCWriterArchive *archive, bool enable);
|
||||
|
||||
struct PTCReaderArchive *PTC_open_reader_archive(struct Scene *scene, const char *path);
|
||||
void PTC_close_reader_archive(struct PTCReaderArchive *archive);
|
||||
void PTC_reader_archive_use_render(struct PTCReaderArchive *archive, bool enable);
|
||||
|
||||
void PTC_writer_init(struct PTCWriter *writer, struct PTCWriterArchive *archive);
|
||||
void PTC_writer_create_refs(struct PTCWriter *writer);
|
||||
void PTC_reader_init(struct PTCReader *reader, struct PTCReaderArchive *archive);
|
||||
|
||||
/*** Reader/Writer Interface ***/
|
||||
|
||||
void PTC_writer_free(struct PTCWriter *writer);
|
||||
void PTC_write_sample(struct PTCWriter *writer);
|
||||
|
||||
void PTC_reader_free(struct PTCReader *reader);
|
||||
bool PTC_reader_get_frame_range(struct PTCReader *reader, int *start_frame, int *end_frame);
|
||||
PTCReadSampleResult PTC_read_sample(struct PTCReader *reader, float frame);
|
||||
PTCReadSampleResult PTC_test_sample(struct PTCReader *reader, float frame);
|
||||
|
||||
char *PTC_get_archive_info(struct PTCReaderArchive *archive);
|
||||
|
||||
struct PTCWriter *PTC_writer_dupligroup(const char *name, struct EvaluationContext *eval_ctx, struct Scene *scene, struct Group *group, struct CacheLibrary *cachelib);
|
||||
struct PTCReader *PTC_reader_duplicache(const char *name, struct Group *group, struct DupliCache *dupcache);
|
||||
struct PTCReader *PTC_reader_duplicache_object(const char *name, struct Object *ob, struct DupliObjectData *data);
|
||||
|
||||
/* get writer/reader from RNA type */
|
||||
struct PTCWriter *PTC_writer_from_rna(struct Scene *scene, struct PointerRNA *ptr);
|
||||
struct PTCReader *PTC_reader_from_rna(struct Scene *scene, struct PointerRNA *ptr);
|
||||
|
||||
/* Object */
|
||||
struct PTCWriter *PTC_writer_object(const char *name, struct Scene *scene, struct Object *ob);
|
||||
struct PTCReader *PTC_reader_object(const char *name, struct Object *ob);
|
||||
|
||||
/* Group */
|
||||
struct PTCWriter *PTC_writer_group(const char *name, struct Group *group);
|
||||
struct PTCReader *PTC_reader_group(const char *name, struct Group *group);
|
||||
|
||||
/* Particles */
|
||||
struct PTCWriter *PTC_writer_particles(const char *name, struct Object *ob, struct ParticleSystem *psys);
|
||||
struct PTCReader *PTC_reader_particles(const char *name, struct Object *ob, struct ParticleSystem *psys);
|
||||
int PTC_reader_particles_totpoint(struct PTCReader *reader);
|
||||
|
||||
struct PTCWriter *PTC_writer_hair_dynamics(const char *name, struct Object *ob, struct ParticleSystem *psys);
|
||||
struct PTCReader *PTC_reader_hair_dynamics(const char *name, struct Object *ob, struct ParticleSystem *psys);
|
||||
|
||||
struct PTCWriter *PTC_writer_particles_pathcache_parents(const char *name, struct Object *ob, struct ParticleSystem *psys);
|
||||
struct PTCReader *PTC_reader_particles_pathcache_parents(const char *name, struct Object *ob, struct ParticleSystem *psys);
|
||||
struct PTCWriter *PTC_writer_particles_pathcache_children(const char *name, struct Object *ob, struct ParticleSystem *psys);
|
||||
struct PTCReader *PTC_reader_particles_pathcache_children(const char *name, struct Object *ob, struct ParticleSystem *psys);
|
||||
|
||||
/* Cloth */
|
||||
struct PTCWriter *PTC_writer_cloth(const char *name, struct Object *ob, struct ClothModifierData *clmd);
|
||||
struct PTCReader *PTC_reader_cloth(const char *name, struct Object *ob, struct ClothModifierData *clmd);
|
||||
|
||||
struct PTCWriter *PTC_writer_derived_mesh(const char *name, struct Object *ob, struct DerivedMesh **dm_ptr);
|
||||
struct PTCReader *PTC_reader_derived_mesh(const char *name, struct Object *ob);
|
||||
struct DerivedMesh *PTC_reader_derived_mesh_acquire_result(struct PTCReader *reader);
|
||||
void PTC_reader_derived_mesh_discard_result(struct PTCReader *reader);
|
||||
|
||||
struct PTCWriter *PTC_writer_derived_final_realtime(const char *name, struct Object *ob);
|
||||
struct PTCWriter *PTC_writer_cache_modifier_realtime(const char *name, struct Object *ob, struct CacheModifierData *cmd);
|
||||
struct PTCWriter *PTC_writer_derived_final_render(const char *name, struct Scene *scene, struct Object *ob, struct DerivedMesh **render_dm_ptr);
|
||||
struct PTCWriter *PTC_writer_cache_modifier_render(const char *name, struct Scene *scene, struct Object *ob, struct CacheModifierData *cmd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif /* PTC_API_H */
|
56
source/blender/pointcache/SConscript
Normal file
56
source/blender/pointcache/SConscript
Normal file
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# The Original Code is Copyright (C) 2014, Blender Foundation
|
||||
# All rights reserved.
|
||||
#
|
||||
# The Original Code is: all of this file.
|
||||
#
|
||||
# Contributor(s): Lukas Toenne.
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
Import ('env')
|
||||
|
||||
sources = env.Glob('intern/*.cpp') + env.Glob('util/*.cpp') + env.Glob('*.cpp')
|
||||
|
||||
incs = [
|
||||
'.',
|
||||
'intern',
|
||||
'util',
|
||||
'../blenkernel',
|
||||
'../blenlib',
|
||||
'../makesdna',
|
||||
'../makesrna',
|
||||
'../../../intern/guardedalloc',
|
||||
]
|
||||
|
||||
defs = []
|
||||
|
||||
if env['WITH_BF_INTERNATIONAL']:
|
||||
defs.append('WITH_INTERNATIONAL')
|
||||
|
||||
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
|
||||
incs.append(env['BF_PTHREADS_INC'])
|
||||
|
||||
if env['WITH_BF_ALEMBIC']:
|
||||
defs.append('WITH_PTC_ALEMBIC')
|
||||
|
||||
SConscript(['alembic/SConscript'])
|
||||
|
||||
env.BlenderLib('bf_pointcache', sources, incs, defines=defs, libtype=['core'], priority=[900])
|
71
source/blender/pointcache/alembic/CMakeLists.txt
Normal file
71
source/blender/pointcache/alembic/CMakeLists.txt
Normal file
@@ -0,0 +1,71 @@
|
||||
# ***** 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) 2013, Blender Foundation
|
||||
# All rights reserved.
|
||||
#
|
||||
# The Original Code is: all of this file.
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
set(INC
|
||||
.
|
||||
../
|
||||
../intern
|
||||
../util
|
||||
../../blenkernel
|
||||
../../blenlib
|
||||
../../makesdna
|
||||
../../makesrna
|
||||
../../../../intern/guardedalloc
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
${BOOST_INCLUDE_DIR}
|
||||
${ALEMBIC_INCLUDE_DIRS}
|
||||
${OPENEXR_INCLUDE_DIR}/OpenEXR
|
||||
)
|
||||
|
||||
set(SRC
|
||||
alembic.cpp
|
||||
alembic.h
|
||||
|
||||
abc_frame_mapper.cpp
|
||||
abc_frame_mapper.h
|
||||
abc_info.cpp
|
||||
abc_reader.cpp
|
||||
abc_reader.h
|
||||
abc_schema.h
|
||||
abc_writer.cpp
|
||||
abc_writer.h
|
||||
|
||||
abc_cloth.cpp
|
||||
abc_cloth.h
|
||||
abc_customdata.cpp
|
||||
abc_customdata.h
|
||||
abc_group.cpp
|
||||
abc_group.h
|
||||
abc_mesh.cpp
|
||||
abc_mesh.h
|
||||
abc_object.cpp
|
||||
abc_object.h
|
||||
abc_particles.cpp
|
||||
abc_particles.h
|
||||
)
|
||||
|
||||
add_definitions(-DWITH_ALEMBIC)
|
||||
|
||||
blender_add_lib(bf_pointcache_alembic "${SRC}" "${INC}" "${INC_SYS}")
|
60
source/blender/pointcache/alembic/SConscript
Normal file
60
source/blender/pointcache/alembic/SConscript
Normal file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# The Original Code is Copyright (C) 2014, Blender Foundation
|
||||
# All rights reserved.
|
||||
#
|
||||
# The Original Code is: all of this file.
|
||||
#
|
||||
# Contributor(s): Lukas Toenne.
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
Import ('env')
|
||||
|
||||
sources = env.Glob('*.cpp')
|
||||
|
||||
incs = [
|
||||
'.',
|
||||
'../',
|
||||
'../intern',
|
||||
'../util',
|
||||
'../../blenkernel',
|
||||
'../../blenlib',
|
||||
'../../makesdna',
|
||||
'../../makesrna',
|
||||
'../../../../intern/guardedalloc',
|
||||
]
|
||||
|
||||
incs += Split(env['BF_OPENEXR_INC'])
|
||||
|
||||
defs = []
|
||||
|
||||
if env['WITH_BF_INTERNATIONAL']:
|
||||
defs.append('WITH_INTERNATIONAL')
|
||||
|
||||
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
|
||||
incs.append(env['BF_PTHREADS_INC'])
|
||||
|
||||
if env['WITH_BF_ALEMBIC']:
|
||||
incs.append(env['BF_OPENEXR_INC'])
|
||||
incs.append(env['BF_ALEMBIC_INC'])
|
||||
|
||||
defs.append('WITH_ALEMBIC')
|
||||
|
||||
env.BlenderLib('bf_pointcache_alembic', sources, incs, defines=defs, libtype=['core'], priority=[901])
|
244
source/blender/pointcache/alembic/abc_cloth.cpp
Normal file
244
source/blender/pointcache/alembic/abc_cloth.cpp
Normal file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright 2013, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "abc_cloth.h"
|
||||
|
||||
extern "C" {
|
||||
#include "BLI_math.h"
|
||||
|
||||
#include "DNA_cloth_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
|
||||
#include "BKE_cloth.h"
|
||||
}
|
||||
|
||||
#include "PTC_api.h"
|
||||
|
||||
namespace PTC {
|
||||
|
||||
using namespace Abc;
|
||||
using namespace AbcGeom;
|
||||
|
||||
AbcClothWriter::AbcClothWriter(const std::string &name, Object *ob, ClothModifierData *clmd) :
|
||||
ClothWriter(ob, clmd, name)
|
||||
{
|
||||
set_error_handler(new ModifierErrorHandler(&clmd->modifier));
|
||||
}
|
||||
|
||||
AbcClothWriter::~AbcClothWriter()
|
||||
{
|
||||
}
|
||||
|
||||
void AbcClothWriter::init_abc(OObject parent)
|
||||
{
|
||||
if (m_points)
|
||||
return;
|
||||
|
||||
m_points = OPoints(parent, m_name, abc_archive()->frame_sampling_index());
|
||||
|
||||
OPointsSchema &schema = m_points.getSchema();
|
||||
OCompoundProperty geom_params = schema.getArbGeomParams();
|
||||
|
||||
m_param_velocities = OV3fGeomParam(geom_params, "velocities", false, kVaryingScope, 1, 0);
|
||||
m_param_goal_positions = OP3fGeomParam(geom_params, "goal_positions", false, kVaryingScope, 1, 0);
|
||||
}
|
||||
|
||||
static V3fArraySample create_sample_velocities(Cloth *cloth, std::vector<V3f> &data)
|
||||
{
|
||||
ClothVertex *vert;
|
||||
int i, totvert = cloth->numverts;
|
||||
|
||||
data.reserve(totvert);
|
||||
for (i = 0, vert = cloth->verts; i < totvert; ++i, ++vert) {
|
||||
float *co = vert->v;
|
||||
data.push_back(V3f(co[0], co[1], co[2]));
|
||||
}
|
||||
|
||||
return V3fArraySample(data);
|
||||
}
|
||||
|
||||
static P3fArraySample create_sample_goal_positions(Cloth *cloth, std::vector<V3f> &data)
|
||||
{
|
||||
ClothVertex *vert;
|
||||
int i, totvert = cloth->numverts;
|
||||
|
||||
data.reserve(totvert);
|
||||
for (i = 0, vert = cloth->verts; i < totvert; ++i, ++vert) {
|
||||
float *co = vert->xconst;
|
||||
data.push_back(V3f(co[0], co[1], co[2]));
|
||||
}
|
||||
|
||||
return P3fArraySample(data);
|
||||
}
|
||||
|
||||
void AbcClothWriter::write_sample()
|
||||
{
|
||||
if (!m_points)
|
||||
return;
|
||||
|
||||
Cloth *cloth = m_clmd->clothObject;
|
||||
if (!cloth)
|
||||
return;
|
||||
|
||||
OPointsSchema &schema = m_points.getSchema();
|
||||
|
||||
int totpoint = cloth->numverts;
|
||||
ClothVertex *vert;
|
||||
int i;
|
||||
|
||||
/* XXX TODO only needed for the first frame/sample */
|
||||
std::vector<Util::uint64_t> ids;
|
||||
ids.reserve(totpoint);
|
||||
for (i = 0, vert = cloth->verts; i < totpoint; ++i, ++vert)
|
||||
ids.push_back(i);
|
||||
|
||||
std::vector<V3f> positions;
|
||||
positions.reserve(totpoint);
|
||||
for (i = 0, vert = cloth->verts; i < totpoint; ++i, ++vert) {
|
||||
float *co = vert->x;
|
||||
positions.push_back(V3f(co[0], co[1], co[2]));
|
||||
}
|
||||
|
||||
std::vector<V3f> velocities_buffer;
|
||||
std::vector<V3f> goal_positions_buffer;
|
||||
V3fArraySample velocities = create_sample_velocities(cloth, velocities_buffer);
|
||||
P3fArraySample goal_positions = create_sample_goal_positions(cloth, goal_positions_buffer);
|
||||
|
||||
OPointsSchema::Sample sample = OPointsSchema::Sample(V3fArraySample(positions), UInt64ArraySample(ids));
|
||||
schema.set(sample);
|
||||
|
||||
m_param_velocities.set(OV3fGeomParam::Sample(velocities, kVaryingScope));
|
||||
m_param_goal_positions.set(OP3fGeomParam::Sample(goal_positions, kVaryingScope));
|
||||
}
|
||||
|
||||
|
||||
AbcClothReader::AbcClothReader(const std::string &name, Object *ob, ClothModifierData *clmd) :
|
||||
ClothReader(ob, clmd, name)
|
||||
{
|
||||
set_error_handler(new ModifierErrorHandler(&clmd->modifier));
|
||||
}
|
||||
|
||||
AbcClothReader::~AbcClothReader()
|
||||
{
|
||||
}
|
||||
|
||||
void AbcClothReader::init_abc(IObject parent)
|
||||
{
|
||||
if (m_points)
|
||||
return;
|
||||
|
||||
if (parent.getChild(m_name)) {
|
||||
m_points = IPoints(parent, m_name);
|
||||
|
||||
IPointsSchema &schema = m_points.getSchema();
|
||||
ICompoundProperty geom_params = schema.getArbGeomParams();
|
||||
|
||||
m_param_velocities = IV3fGeomParam(geom_params, "velocities", 0);
|
||||
m_param_goal_positions= IP3fGeomParam(geom_params, "goal_positions", 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void apply_sample_positions(Cloth *cloth, P3fArraySamplePtr sample)
|
||||
{
|
||||
ClothVertex *vert;
|
||||
int i, totvert = cloth->numverts;
|
||||
|
||||
BLI_assert(sample->size() == totvert);
|
||||
|
||||
const V3f *data = sample->get();
|
||||
for (i = 0, vert = cloth->verts; i < totvert; ++i, ++vert) {
|
||||
const V3f &co = data[i];
|
||||
copy_v3_v3(vert->x, co.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
static void apply_sample_velocities(Cloth *cloth, V3fArraySamplePtr sample)
|
||||
{
|
||||
ClothVertex *vert;
|
||||
int i, totvert = cloth->numverts;
|
||||
|
||||
BLI_assert(sample->size() == totvert);
|
||||
|
||||
const V3f *data = sample->get();
|
||||
for (i = 0, vert = cloth->verts; i < totvert; ++i, ++vert) {
|
||||
const V3f &vel = data[i];
|
||||
copy_v3_v3(vert->v, vel.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
static void apply_sample_goal_positions(Cloth *cloth, P3fArraySamplePtr sample)
|
||||
{
|
||||
ClothVertex *vert;
|
||||
int i, totvert = cloth->numverts;
|
||||
|
||||
BLI_assert(sample->size() == totvert);
|
||||
|
||||
const V3f *data = sample->get();
|
||||
for (i = 0, vert = cloth->verts; i < totvert; ++i, ++vert) {
|
||||
const V3f &co = data[i];
|
||||
copy_v3_v3(vert->xconst, co.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
PTCReadSampleResult AbcClothReader::read_sample(float frame)
|
||||
{
|
||||
Cloth *cloth = m_clmd->clothObject;
|
||||
|
||||
if (!m_points)
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
|
||||
IPointsSchema &schema = m_points.getSchema();
|
||||
TimeSamplingPtr ts = schema.getTimeSampling();
|
||||
|
||||
ISampleSelector ss = abc_archive()->get_frame_sample_selector(frame);
|
||||
// chrono_t time = ss.getRequestedTime();
|
||||
|
||||
// std::pair<index_t, chrono_t> sres = ts->getFloorIndex(time, schema.getNumSamples());
|
||||
// chrono_t stime = sres.second;
|
||||
// float sframe = archive()->time_to_frame(stime);
|
||||
|
||||
IPointsSchema::Sample sample;
|
||||
schema.get(sample, ss);
|
||||
|
||||
P3fArraySamplePtr positions = sample.getPositions();
|
||||
|
||||
V3fArraySamplePtr velocities;
|
||||
if (m_param_velocities && m_param_velocities.getNumSamples() > 0) {
|
||||
IV3fGeomParam::Sample sample_velocities;
|
||||
m_param_velocities.getExpanded(sample_velocities, ss);
|
||||
velocities = sample_velocities.getVals();
|
||||
}
|
||||
|
||||
P3fArraySamplePtr goal_positions;
|
||||
if (m_param_goal_positions && m_param_goal_positions.getNumSamples() > 0) {
|
||||
IP3fGeomParam::Sample sample_goal_positions;
|
||||
m_param_goal_positions.getExpanded(sample_goal_positions, ss);
|
||||
goal_positions = sample_goal_positions.getVals();
|
||||
}
|
||||
|
||||
apply_sample_positions(cloth, positions);
|
||||
if (velocities)
|
||||
apply_sample_velocities(cloth, velocities);
|
||||
if (goal_positions)
|
||||
apply_sample_goal_positions(cloth, goal_positions);
|
||||
|
||||
return PTC_READ_SAMPLE_EXACT;
|
||||
}
|
||||
|
||||
} /* namespace PTC */
|
68
source/blender/pointcache/alembic/abc_cloth.h
Normal file
68
source/blender/pointcache/alembic/abc_cloth.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2013, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef PTC_ABC_CLOTH_H
|
||||
#define PTC_ABC_CLOTH_H
|
||||
|
||||
#include <Alembic/AbcGeom/IPoints.h>
|
||||
#include <Alembic/AbcGeom/OPoints.h>
|
||||
|
||||
#include "ptc_types.h"
|
||||
|
||||
#include "abc_reader.h"
|
||||
#include "abc_schema.h"
|
||||
#include "abc_writer.h"
|
||||
|
||||
struct Object;
|
||||
struct ClothModifierData;
|
||||
|
||||
namespace PTC {
|
||||
|
||||
class AbcClothWriter : public ClothWriter, public AbcWriter {
|
||||
public:
|
||||
AbcClothWriter(const std::string &name, Object *ob, ClothModifierData *clmd);
|
||||
~AbcClothWriter();
|
||||
|
||||
void init_abc(Abc::OObject parent);
|
||||
|
||||
void write_sample();
|
||||
|
||||
private:
|
||||
AbcGeom::OPoints m_points;
|
||||
AbcGeom::OV3fGeomParam m_param_velocities;
|
||||
AbcGeom::OP3fGeomParam m_param_goal_positions;
|
||||
};
|
||||
|
||||
class AbcClothReader : public ClothReader, public AbcReader {
|
||||
public:
|
||||
AbcClothReader(const std::string &name, Object *ob, ClothModifierData *clmd);
|
||||
~AbcClothReader();
|
||||
|
||||
void init_abc(Abc::IObject parent);
|
||||
|
||||
PTCReadSampleResult read_sample(float frame);
|
||||
|
||||
private:
|
||||
AbcGeom::IPoints m_points;
|
||||
AbcGeom::IV3fGeomParam m_param_velocities;
|
||||
AbcGeom::IP3fGeomParam m_param_goal_positions;
|
||||
};
|
||||
|
||||
} /* namespace PTC */
|
||||
|
||||
#endif /* PTC_CLOTH_H */
|
512
source/blender/pointcache/alembic/abc_customdata.cpp
Normal file
512
source/blender/pointcache/alembic/abc_customdata.cpp
Normal file
@@ -0,0 +1,512 @@
|
||||
/*
|
||||
* Copyright 2015, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <Alembic/AbcGeom/IGeomParam.h>
|
||||
#include <Alembic/AbcGeom/OGeomParam.h>
|
||||
|
||||
#include "abc_customdata.h"
|
||||
|
||||
extern "C" {
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_customdata_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
|
||||
#include "BKE_customdata.h"
|
||||
}
|
||||
|
||||
namespace PTC {
|
||||
|
||||
using namespace Abc;
|
||||
using namespace AbcGeom;
|
||||
|
||||
/* DEBUG */
|
||||
BLI_INLINE void print_writer_compound(OCompoundProperty &prop)
|
||||
{
|
||||
CompoundPropertyWriterPtr ptr = prop.getPtr()->asCompoundPtr();
|
||||
printf("compound %s: [%p] (%d)\n", ptr->getName().c_str(), ptr.get(), (int)ptr->getNumProperties());
|
||||
for (int i = 0; i < ptr->getNumProperties(); ++i) {
|
||||
printf(" %d: [%p]\n", i, prop.getProperty(i).getPtr().get());
|
||||
printf(" %s\n", prop.getProperty(i).getName().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
template <CustomDataType CDTYPE>
|
||||
static void write_sample(CustomDataWriter *writer, OCompoundProperty &parent, const std::string &name, void *data, int num_data)
|
||||
{
|
||||
/* no implementation available, should not happen */
|
||||
printf("ERROR: CustomData type %s has no write_sample implementation\n", CustomData_layertype_name((int)CDTYPE));
|
||||
}
|
||||
|
||||
template <>
|
||||
void write_sample<CD_MDEFORMVERT>(CustomDataWriter *writer, OCompoundProperty &parent, const std::string &name, void *data, int num_data)
|
||||
{
|
||||
OCompoundProperty prop = writer->add_compound_property<OCompoundProperty>(name, parent);
|
||||
|
||||
OInt32ArrayProperty totweight_prop = writer->add_array_property<OInt32ArrayProperty>(name+":totweight", prop);
|
||||
OInt32ArrayProperty flag_prop = writer->add_array_property<OInt32ArrayProperty>(name+":flag", prop);
|
||||
OInt32ArrayProperty def_nr_prop = writer->add_array_property<OInt32ArrayProperty>(name+":def_nr", prop);
|
||||
OFloatArrayProperty weight_prop = writer->add_array_property<OFloatArrayProperty>(name+":weight", prop);
|
||||
|
||||
MDeformVert *mdef = (MDeformVert *)data;
|
||||
|
||||
/* sum all totweight for the sample size */
|
||||
int num_mdefweight = 0;
|
||||
for (int i = 0; i < num_data; ++i)
|
||||
num_mdefweight += mdef[i].totweight;
|
||||
|
||||
std::vector<int32_t> totweight_data;
|
||||
std::vector<int32_t> flag_data;
|
||||
std::vector<int32_t> def_nr_data;
|
||||
std::vector<float> weight_data;
|
||||
totweight_data.reserve(num_data);
|
||||
flag_data.reserve(num_data);
|
||||
def_nr_data.reserve(num_mdefweight);
|
||||
weight_data.reserve(num_mdefweight);
|
||||
|
||||
for (int i = 0; i < num_data; ++i) {
|
||||
totweight_data.push_back(mdef->totweight);
|
||||
flag_data.push_back(mdef->flag);
|
||||
|
||||
MDeformWeight *mw = mdef->dw;
|
||||
for (int j = 0; j < mdef->totweight; ++j) {
|
||||
def_nr_data.push_back(mw->def_nr);
|
||||
weight_data.push_back(mw->weight);
|
||||
|
||||
++mw;
|
||||
}
|
||||
|
||||
++mdef;
|
||||
}
|
||||
|
||||
totweight_prop.set(Int32ArraySample(totweight_data));
|
||||
flag_prop.set(Int32ArraySample(flag_data));
|
||||
def_nr_prop.set(Int32ArraySample(def_nr_data));
|
||||
weight_prop.set(FloatArraySample(weight_data));
|
||||
}
|
||||
|
||||
template <>
|
||||
void write_sample<CD_MCOL>(CustomDataWriter *writer, OCompoundProperty &parent, const std::string &name, void *data, int num_data)
|
||||
{
|
||||
OC4fArrayProperty prop = writer->add_array_property<OC4fArrayProperty>(name, parent);
|
||||
|
||||
MCol *mcol = (MCol *)data;
|
||||
|
||||
std::vector<C4f> mcol_data;
|
||||
mcol_data.reserve(num_data);
|
||||
for (int i = 0; i < num_data; ++i) {
|
||||
mcol_data.push_back(C4f(mcol->r, mcol->g, mcol->b, mcol->a));
|
||||
|
||||
++mcol;
|
||||
}
|
||||
prop.set(OC4fArrayProperty::sample_type(mcol_data));
|
||||
}
|
||||
|
||||
template <>
|
||||
void write_sample<CD_ORIGINDEX>(CustomDataWriter *writer, OCompoundProperty &parent, const std::string &name, void *data, int num_data)
|
||||
{
|
||||
OInt32ArrayProperty prop = writer->add_array_property<OInt32ArrayProperty>(name, parent);
|
||||
|
||||
prop.set(OInt32ArrayProperty::sample_type((int *)data, num_data));
|
||||
}
|
||||
|
||||
template <>
|
||||
void write_sample<CD_NORMAL>(CustomDataWriter *writer, OCompoundProperty &parent, const std::string &name, void *data, int num_data)
|
||||
{
|
||||
ON3fArrayProperty prop = writer->add_array_property<ON3fArrayProperty>(name, parent);
|
||||
|
||||
prop.set(ON3fArrayProperty::sample_type((N3f *)data, num_data));
|
||||
}
|
||||
|
||||
template <>
|
||||
void write_sample<CD_ORIGSPACE>(CustomDataWriter *writer, OCompoundProperty &parent, const std::string &name, void *data, int num_data)
|
||||
{
|
||||
OCompoundProperty prop = writer->add_compound_property<OCompoundProperty>(name, parent);
|
||||
|
||||
OV2fArrayProperty uv_prop[4];
|
||||
uv_prop[0] = writer->add_array_property<OV2fArrayProperty>(name+":uv0", prop);
|
||||
uv_prop[1] = writer->add_array_property<OV2fArrayProperty>(name+":uv1", prop);
|
||||
uv_prop[2] = writer->add_array_property<OV2fArrayProperty>(name+":uv2", prop);
|
||||
uv_prop[3] = writer->add_array_property<OV2fArrayProperty>(name+":uv3", prop);
|
||||
|
||||
OrigSpaceFace *ospace = (OrigSpaceFace *)data;
|
||||
std::vector<V2f> uv_data[4];
|
||||
uv_data[0].reserve(num_data);
|
||||
uv_data[1].reserve(num_data);
|
||||
uv_data[2].reserve(num_data);
|
||||
uv_data[3].reserve(num_data);
|
||||
for (int i = 0; i < num_data; ++i) {
|
||||
uv_data[0].push_back(V2f(ospace[i].uv[0][0], ospace[i].uv[0][1]));
|
||||
uv_data[1].push_back(V2f(ospace[i].uv[1][0], ospace[i].uv[1][1]));
|
||||
uv_data[2].push_back(V2f(ospace[i].uv[2][0], ospace[i].uv[2][1]));
|
||||
uv_data[3].push_back(V2f(ospace[i].uv[3][0], ospace[i].uv[3][1]));
|
||||
}
|
||||
uv_prop[0].set(V2fArraySample(uv_data[0]));
|
||||
uv_prop[1].set(V2fArraySample(uv_data[1]));
|
||||
uv_prop[2].set(V2fArraySample(uv_data[2]));
|
||||
uv_prop[3].set(V2fArraySample(uv_data[3]));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
template <CustomDataType CDTYPE>
|
||||
static PTCReadSampleResult read_sample(CustomDataReader *reader, ICompoundProperty &parent, const ISampleSelector &ss, const std::string &name, void *data, int num_data)
|
||||
{
|
||||
/* no implementation available, should not happen */
|
||||
printf("ERROR: CustomData type %s has no read_sample implementation\n", CustomData_layertype_name((int)CDTYPE));
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
}
|
||||
|
||||
template <>
|
||||
PTCReadSampleResult read_sample<CD_MDEFORMVERT>(CustomDataReader *reader, ICompoundProperty &parent, const ISampleSelector &ss, const std::string &name, void *data, int num_data)
|
||||
{
|
||||
ICompoundProperty prop = reader->add_compound_property<ICompoundProperty>(name, parent);
|
||||
|
||||
IInt32ArrayProperty totweight_prop = reader->add_array_property<IInt32ArrayProperty>(name+":totweight", prop);
|
||||
IInt32ArrayProperty flag_prop = reader->add_array_property<IInt32ArrayProperty>(name+":flag", prop);
|
||||
IInt32ArrayProperty def_nr_prop = reader->add_array_property<IInt32ArrayProperty>(name+":def_nr", prop);
|
||||
IFloatArrayProperty weight_prop = reader->add_array_property<IFloatArrayProperty>(name+":weight", prop);
|
||||
|
||||
Int32ArraySamplePtr sample_totweight = totweight_prop.getValue(ss);
|
||||
Int32ArraySamplePtr sample_flag = flag_prop.getValue(ss);
|
||||
Int32ArraySamplePtr sample_def_nr = def_nr_prop.getValue(ss);
|
||||
FloatArraySamplePtr sample_weight = weight_prop.getValue(ss);
|
||||
|
||||
if (sample_totweight->size() != num_data ||
|
||||
sample_flag->size() != num_data)
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
|
||||
const int32_t *data_totweight = (const int32_t *)sample_totweight->getData();
|
||||
const int32_t *data_flag = (const int32_t *)sample_flag->getData();
|
||||
const int32_t *data_def_nr = (const int32_t *)sample_def_nr->getData();
|
||||
const float *data_weight = (const float *)sample_weight->getData();
|
||||
|
||||
MDeformVert *mdef = (MDeformVert *)data;
|
||||
for (int i = 0; i < num_data; ++i) {
|
||||
|
||||
mdef->totweight = *data_totweight;
|
||||
mdef->flag = *data_flag;
|
||||
|
||||
MDeformWeight *mw = mdef->dw = (MDeformWeight *)MEM_mallocN(sizeof(MDeformWeight) * mdef->totweight, "deformWeight");
|
||||
for (int j = 0; j < mdef->totweight; ++j) {
|
||||
mw->def_nr = *data_def_nr;
|
||||
mw->weight = *data_weight;
|
||||
|
||||
++data_def_nr;
|
||||
++data_weight;
|
||||
++mw;
|
||||
}
|
||||
|
||||
++data_totweight;
|
||||
++data_flag;
|
||||
++mdef;
|
||||
}
|
||||
|
||||
return PTC_READ_SAMPLE_EXACT;
|
||||
}
|
||||
|
||||
template <>
|
||||
PTCReadSampleResult read_sample<CD_MCOL>(CustomDataReader *reader, ICompoundProperty &parent, const ISampleSelector &ss, const std::string &name, void *data, int num_data)
|
||||
{
|
||||
IC4fArrayProperty prop = reader->add_array_property<IC4fArrayProperty>(name, parent);
|
||||
|
||||
C4fArraySamplePtr sample = prop.getValue(ss);
|
||||
|
||||
if (sample->size() != num_data)
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
|
||||
MCol *mcol = (MCol *)data;
|
||||
C4f *data_mcol = (C4f *)sample->getData();
|
||||
for (int i = 0; i < num_data; ++i) {
|
||||
mcol->r = data_mcol->r;
|
||||
mcol->g = data_mcol->g;
|
||||
mcol->b = data_mcol->b;
|
||||
mcol->a = data_mcol->a;
|
||||
|
||||
++data_mcol;
|
||||
++mcol;
|
||||
}
|
||||
return PTC_READ_SAMPLE_EXACT;
|
||||
}
|
||||
|
||||
template <>
|
||||
PTCReadSampleResult read_sample<CD_ORIGINDEX>(CustomDataReader *reader, ICompoundProperty &parent, const ISampleSelector &ss, const std::string &name, void *data, int num_data)
|
||||
{
|
||||
IInt32ArrayProperty prop = reader->add_array_property<IInt32ArrayProperty>(name, parent);
|
||||
|
||||
Int32ArraySamplePtr sample = prop.getValue(ss);
|
||||
|
||||
if (sample->size() != num_data)
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
|
||||
memcpy(data, sample->getData(), sizeof(int32_t) * num_data);
|
||||
return PTC_READ_SAMPLE_EXACT;
|
||||
}
|
||||
|
||||
template <>
|
||||
PTCReadSampleResult read_sample<CD_NORMAL>(CustomDataReader *reader, ICompoundProperty &parent, const ISampleSelector &ss, const std::string &name, void *data, int num_data)
|
||||
{
|
||||
IN3fArrayProperty prop = reader->add_array_property<IN3fArrayProperty>(name, parent);
|
||||
|
||||
N3fArraySamplePtr sample = prop.getValue(ss);
|
||||
|
||||
if (sample->size() != num_data)
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
|
||||
memcpy(data, sample->getData(), sizeof(N3f) * num_data);
|
||||
return PTC_READ_SAMPLE_EXACT;
|
||||
}
|
||||
|
||||
template <>
|
||||
PTCReadSampleResult read_sample<CD_ORIGSPACE>(CustomDataReader *reader, ICompoundProperty &parent, const ISampleSelector &ss, const std::string &name, void *data, int num_data)
|
||||
{
|
||||
ICompoundProperty prop = reader->add_compound_property<ICompoundProperty>(name, parent);
|
||||
|
||||
IV2fArrayProperty uv_prop[4];
|
||||
uv_prop[0] = reader->add_array_property<IV2fArrayProperty>(name+":uv0", prop);
|
||||
uv_prop[1] = reader->add_array_property<IV2fArrayProperty>(name+":uv1", prop);
|
||||
uv_prop[2] = reader->add_array_property<IV2fArrayProperty>(name+":uv2", prop);
|
||||
uv_prop[3] = reader->add_array_property<IV2fArrayProperty>(name+":uv3", prop);
|
||||
|
||||
V2fArraySamplePtr sample0 = uv_prop[0].getValue(ss);
|
||||
V2fArraySamplePtr sample1 = uv_prop[1].getValue(ss);
|
||||
V2fArraySamplePtr sample2 = uv_prop[2].getValue(ss);
|
||||
V2fArraySamplePtr sample3 = uv_prop[3].getValue(ss);
|
||||
|
||||
if (sample0->size() != num_data ||
|
||||
sample1->size() != num_data ||
|
||||
sample2->size() != num_data ||
|
||||
sample3->size() != num_data)
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
|
||||
OrigSpaceFace *ospace = (OrigSpaceFace *)data;
|
||||
const V2f *data0 = (const V2f *)sample0->getData();
|
||||
const V2f *data1 = (const V2f *)sample1->getData();
|
||||
const V2f *data2 = (const V2f *)sample2->getData();
|
||||
const V2f *data3 = (const V2f *)sample3->getData();
|
||||
for (int i = 0; i < num_data; ++i) {
|
||||
copy_v2_v2(ospace->uv[0], data0->getValue());
|
||||
copy_v2_v2(ospace->uv[1], data1->getValue());
|
||||
copy_v2_v2(ospace->uv[2], data2->getValue());
|
||||
copy_v2_v2(ospace->uv[3], data3->getValue());
|
||||
|
||||
++data0;
|
||||
++data1;
|
||||
++data2;
|
||||
++data3;
|
||||
++ospace;
|
||||
}
|
||||
|
||||
return PTC_READ_SAMPLE_EXACT;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
/* recursive template that handles dispatch by CD layer type */
|
||||
template <int CDTYPE>
|
||||
BLI_INLINE void write_sample_call(CustomDataWriter *writer, OCompoundProperty &parent, CustomDataType type, const std::string &name, void *data, int num_data)
|
||||
{
|
||||
if (type == CDTYPE)
|
||||
write_sample<(CustomDataType)CDTYPE>(writer, parent, name, data, num_data);
|
||||
else
|
||||
write_sample_call<CDTYPE+1>(writer, parent, type, name, data, num_data);
|
||||
}
|
||||
|
||||
/* terminator specialization */
|
||||
template <>
|
||||
void write_sample_call<CD_NUMTYPES>(CustomDataWriter *writer, OCompoundProperty &parent, CustomDataType type, const std::string &name, void *data, int num_data)
|
||||
{
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* recursive template that handles dispatch by CD layer type */
|
||||
template <int CDTYPE>
|
||||
BLI_INLINE PTCReadSampleResult read_sample_call(CustomDataReader *reader, ICompoundProperty &parent, const ISampleSelector &ss, CustomDataType type, const std::string &name, void *data, int num_data)
|
||||
{
|
||||
if (type == CDTYPE)
|
||||
return read_sample<(CustomDataType)CDTYPE>(reader, parent, ss, name, data, num_data);
|
||||
else
|
||||
return read_sample_call<CDTYPE+1>(reader, parent, ss, type, name, data, num_data);
|
||||
}
|
||||
|
||||
/* terminator specialization */
|
||||
template <>
|
||||
PTCReadSampleResult read_sample_call<CD_NUMTYPES>(CustomDataReader *reader, ICompoundProperty &parent, const ISampleSelector &ss, CustomDataType type, const std::string &name, void *data, int num_data)
|
||||
{
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
CustomDataWriter::CustomDataWriter(const std::string &name, CustomDataMask cdmask) :
|
||||
m_name(name),
|
||||
m_cdmask(cdmask)
|
||||
{
|
||||
}
|
||||
|
||||
CustomDataWriter::~CustomDataWriter()
|
||||
{
|
||||
for (LayerPropsMap::iterator it = m_layer_props.begin(); it != m_layer_props.end(); ++it) {
|
||||
BasePropertyWriterPtr prop = it->second;
|
||||
if (prop)
|
||||
prop.reset();
|
||||
}
|
||||
}
|
||||
|
||||
/* unique property name based on either layer name or index */
|
||||
std::string CustomDataWriter::cdtype_to_name(CustomData *cdata, CustomDataType type, int n)
|
||||
{
|
||||
const char *layertype_name = CustomData_layertype_name(type);
|
||||
const char *layer_name = CustomData_get_layer_name(cdata, type, n);
|
||||
std::string name;
|
||||
if (layer_name && layer_name[0] != '\0') {
|
||||
name = m_name + ":" + std::string(layertype_name) + ":S" + std::string(layer_name);
|
||||
}
|
||||
else {
|
||||
std::stringstream ss; ss << n;
|
||||
name = m_name + ":" + std::string(layertype_name) + ":N" + ss.str();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/* parse property name to CD layer name based on S or N prefix for named/unnamed layers */
|
||||
void CustomDataReader::cdtype_from_name(CustomData *cdata, const std::string &name, int type, int *n, char *layer_name, int max_layer_name)
|
||||
{
|
||||
const char *layertype_name = CustomData_layertype_name(type);
|
||||
/* We can safely assume all properties in the compound share the correct prefix
|
||||
* <m_name>:<layertype_name>:
|
||||
* The layertype_name is only prepended to avoid name collisions
|
||||
*/
|
||||
const size_t start = m_name.size() + 1 + strlen(layertype_name) + 1;
|
||||
|
||||
if (name.size() <= start) {
|
||||
printf("ERROR: invalid CustomData layer property name '%s'\n", name.c_str());
|
||||
*n = -1;
|
||||
layer_name[0] = '\0';
|
||||
}
|
||||
else if (name[start] == 'S') {
|
||||
/* named layer */
|
||||
*n = -1;
|
||||
BLI_strncpy(layer_name, name.c_str() + start + 1, max_layer_name);
|
||||
}
|
||||
else if (name[start] == 'N') {
|
||||
/* unnamed layer */
|
||||
std::istringstream ss(name.c_str() + start + 1);
|
||||
ss >> (*n);
|
||||
layer_name[0] = '\0';
|
||||
}
|
||||
else {
|
||||
*n = -1;
|
||||
layer_name[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
void CustomDataWriter::write_sample(CustomData *cdata, int num_data, OCompoundProperty &parent)
|
||||
{
|
||||
/* compound property for all CD layers in the CustomData instance */
|
||||
m_props = add_compound_property<OCompoundProperty>(m_name, parent);
|
||||
|
||||
for (int type = 0; type < CD_NUMTYPES; ++type) {
|
||||
CustomDataMask mask = (1 << type);
|
||||
/* only use specified types */
|
||||
if (!(mask & m_cdmask))
|
||||
continue;
|
||||
|
||||
const char *layertype_name = CustomData_layertype_name(type);
|
||||
int num = CustomData_number_of_layers(cdata, type);
|
||||
|
||||
bool has_props = false;
|
||||
OCompoundProperty layertype_props;
|
||||
for (int n = 0; n < num; ++n) {
|
||||
/* compound for all CD layers of the same type */
|
||||
if (!has_props) {
|
||||
has_props = true;
|
||||
layertype_props = add_compound_property<OCompoundProperty>(m_name+":"+layertype_name, m_props);
|
||||
}
|
||||
|
||||
std::string name = cdtype_to_name(cdata, (CustomDataType)type, n);
|
||||
void *data = CustomData_get_layer_n(cdata, type, n);
|
||||
write_sample_call<0>(this, layertype_props, (CustomDataType)type, name, data, num_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
CustomDataReader::CustomDataReader(const std::string &name, CustomDataMask cdmask) :
|
||||
m_name(name),
|
||||
m_cdmask(cdmask)
|
||||
{
|
||||
}
|
||||
|
||||
CustomDataReader::~CustomDataReader()
|
||||
{
|
||||
for (LayerPropsMap::iterator it = m_layer_props.begin(); it != m_layer_props.end(); ++it) {
|
||||
BasePropertyReaderPtr prop = it->second;
|
||||
if (prop)
|
||||
prop.reset();
|
||||
}
|
||||
}
|
||||
|
||||
PTCReadSampleResult CustomDataReader::read_sample(const ISampleSelector &ss, CustomData *cdata, int num_data, ICompoundProperty &parent)
|
||||
{
|
||||
m_props = add_compound_property<ICompoundProperty>(m_name, parent);
|
||||
|
||||
for (int type = 0; type < CD_NUMTYPES; ++type) {
|
||||
CustomDataMask mask = (1 << type);
|
||||
/* only use specified types */
|
||||
if (!(mask & m_cdmask))
|
||||
continue;
|
||||
|
||||
const char *layertype_name = CustomData_layertype_name(type);
|
||||
|
||||
BasePropertyReaderPtr ptr = m_props.getPtr()->asCompoundPtr()->getProperty(m_name+":"+layertype_name);
|
||||
if (!ptr) {
|
||||
/* no layer of this type stored */
|
||||
continue;
|
||||
}
|
||||
ICompoundProperty layertype_props(ptr->asCompoundPtr(), kWrapExisting);
|
||||
|
||||
for (int i = 0; i < layertype_props.getNumProperties(); ++i) {
|
||||
const std::string &name = layertype_props.getPropertyHeader(i).getName();
|
||||
char layer_name[MAX_CUSTOMDATA_LAYER_NAME];
|
||||
int n;
|
||||
void *data;
|
||||
|
||||
cdtype_from_name(cdata, name, type, &n, layer_name, sizeof(layer_name));
|
||||
if (layer_name[0] == '\0')
|
||||
data = CustomData_add_layer(cdata, type, CD_DEFAULT, NULL, num_data);
|
||||
else
|
||||
data = CustomData_add_layer_named(cdata, type, CD_DEFAULT, NULL, num_data, layer_name);
|
||||
|
||||
read_sample_call<0>(this, layertype_props, ss, (CustomDataType)type, name, data, num_data);
|
||||
}
|
||||
}
|
||||
|
||||
return PTC_READ_SAMPLE_EXACT;
|
||||
}
|
||||
|
||||
} /* namespace PTC */
|
144
source/blender/pointcache/alembic/abc_customdata.h
Normal file
144
source/blender/pointcache/alembic/abc_customdata.h
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2015, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef PTC_ABC_CUSTOMDATA_H
|
||||
#define PTC_ABC_CUSTOMDATA_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <Alembic/AbcGeom/IGeomParam.h>
|
||||
#include <Alembic/AbcGeom/OGeomParam.h>
|
||||
#include <Alembic/Abc/IBaseProperty.h>
|
||||
#include <Alembic/Abc/TypedPropertyTraits.h>
|
||||
|
||||
#include "abc_reader.h"
|
||||
#include "abc_writer.h"
|
||||
|
||||
extern "C" {
|
||||
#include "BKE_customdata.h"
|
||||
|
||||
#include "DNA_customdata_types.h"
|
||||
}
|
||||
|
||||
namespace PTC {
|
||||
|
||||
using namespace Alembic;
|
||||
|
||||
std::string abc_customdata_layer_name(CustomData *cdata, CustomDataType type, int n);
|
||||
|
||||
struct CustomDataWriter {
|
||||
typedef std::map<std::string, Abc::BasePropertyWriterPtr> LayerPropsMap;
|
||||
typedef std::pair<std::string, Abc::BasePropertyWriterPtr> LayerPropsPair;
|
||||
|
||||
CustomDataWriter(const std::string &name, CustomDataMask cdmask);
|
||||
~CustomDataWriter();
|
||||
|
||||
void write_sample(CustomData *cdata, int num_data, Abc::OCompoundProperty &parent);
|
||||
|
||||
Abc::OCompoundProperty &props() { return m_props; }
|
||||
|
||||
template <typename PropertyT, typename ParentT>
|
||||
PropertyT add_array_property(const std::string &name, ParentT &parent)
|
||||
{
|
||||
LayerPropsMap::iterator it = m_layer_props.find(name);
|
||||
if (it == m_layer_props.end()) {
|
||||
PropertyT prop = PropertyT(parent, name, 0);
|
||||
m_layer_props.insert(LayerPropsPair(name, prop.getPtr()));
|
||||
return prop;
|
||||
}
|
||||
else {
|
||||
return PropertyT(it->second->asArrayPtr(), Abc::kWrapExisting);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename PropertyT, typename ParentT>
|
||||
PropertyT add_compound_property(const std::string &name, ParentT &parent)
|
||||
{
|
||||
LayerPropsMap::iterator it = m_layer_props.find(name);
|
||||
if (it == m_layer_props.end()) {
|
||||
PropertyT prop = PropertyT(parent, name, 0);
|
||||
m_layer_props.insert(LayerPropsPair(name, prop.getPtr()));
|
||||
return prop;
|
||||
}
|
||||
else {
|
||||
return PropertyT(it->second->asCompoundPtr(), Abc::kWrapExisting);
|
||||
}
|
||||
}
|
||||
|
||||
std::string cdtype_to_name(CustomData *cdata, CustomDataType type, int n);
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
CustomDataMask m_cdmask;
|
||||
|
||||
Abc::OCompoundProperty m_props;
|
||||
LayerPropsMap m_layer_props;
|
||||
};
|
||||
|
||||
struct CustomDataReader {
|
||||
typedef std::map<std::string, Abc::BasePropertyReaderPtr> LayerPropsMap;
|
||||
typedef std::pair<std::string, Abc::BasePropertyReaderPtr> LayerPropsPair;
|
||||
|
||||
CustomDataReader(const std::string &name, CustomDataMask cdmask);
|
||||
~CustomDataReader();
|
||||
|
||||
PTCReadSampleResult read_sample(const Abc::ISampleSelector &ss, CustomData *cdata, int num_data, Abc::ICompoundProperty &parent);
|
||||
|
||||
Abc::ICompoundProperty &props() { return m_props; }
|
||||
|
||||
template <typename PropertyT, typename ParentT>
|
||||
PropertyT add_array_property(const std::string &name, ParentT &parent)
|
||||
{
|
||||
LayerPropsMap::iterator it = m_layer_props.find(name);
|
||||
if (it == m_layer_props.end()) {
|
||||
PropertyT prop = PropertyT(parent, name, 0);
|
||||
m_layer_props.insert(LayerPropsPair(name, prop.getPtr()));
|
||||
return prop;
|
||||
}
|
||||
else {
|
||||
return PropertyT(it->second->asArrayPtr(), Abc::kWrapExisting);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename PropertyT, typename ParentT>
|
||||
PropertyT add_compound_property(const std::string &name, ParentT &parent)
|
||||
{
|
||||
LayerPropsMap::iterator it = m_layer_props.find(name);
|
||||
if (it == m_layer_props.end()) {
|
||||
PropertyT prop = PropertyT(parent, name, 0);
|
||||
m_layer_props.insert(LayerPropsPair(name, prop.getPtr()));
|
||||
return prop;
|
||||
}
|
||||
else {
|
||||
return PropertyT(it->second->asCompoundPtr(), Abc::kWrapExisting);
|
||||
}
|
||||
}
|
||||
|
||||
void cdtype_from_name(CustomData *cdata, const std::string &name, int type, int *n, char *layer_name, int max_layer_name);
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
CustomDataMask m_cdmask;
|
||||
|
||||
Abc::ICompoundProperty m_props;
|
||||
LayerPropsMap m_layer_props;
|
||||
};
|
||||
|
||||
} /* namespace PTC */
|
||||
|
||||
#endif /* PTC_CLOTH_H */
|
60
source/blender/pointcache/alembic/abc_frame_mapper.cpp
Normal file
60
source/blender/pointcache/alembic/abc_frame_mapper.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2013, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "abc_frame_mapper.h"
|
||||
|
||||
extern "C" {
|
||||
#include "DNA_scene_types.h"
|
||||
}
|
||||
|
||||
namespace PTC {
|
||||
|
||||
#ifdef WITH_ALEMBIC
|
||||
|
||||
using namespace Abc;
|
||||
using namespace AbcCoreAbstract;
|
||||
|
||||
FrameMapper::FrameMapper(double fps, double start_time)
|
||||
{
|
||||
m_frames_per_sec = fps;
|
||||
m_sec_per_frame = (fps == 0.0 ? 0.0 : 1.0/fps);
|
||||
m_start_frame = start_time * fps;
|
||||
m_start_time = start_time;
|
||||
}
|
||||
|
||||
FrameMapper::FrameMapper(Scene *scene)
|
||||
{
|
||||
m_frames_per_sec = (scene->r.frs_sec_base == 0.0f ? 0.0 : (double)scene->r.frs_sec / (double)scene->r.frs_sec_base);
|
||||
m_sec_per_frame = (scene->r.frs_sec == 0.0f ? 0.0 : (double)scene->r.frs_sec_base / (double)scene->r.frs_sec);
|
||||
m_start_frame = ((double)scene->r.sfra);
|
||||
m_start_time = m_start_frame * m_sec_per_frame;
|
||||
}
|
||||
|
||||
chrono_t FrameMapper::frame_to_time(float frame) const
|
||||
{
|
||||
return (double)frame * m_sec_per_frame;
|
||||
}
|
||||
|
||||
float FrameMapper::time_to_frame(chrono_t time) const
|
||||
{
|
||||
return (float)(time * m_frames_per_sec);
|
||||
}
|
||||
|
||||
#endif /* WITH_ALEMBIC */
|
||||
|
||||
} /* namespace PTC */
|
58
source/blender/pointcache/alembic/abc_frame_mapper.h
Normal file
58
source/blender/pointcache/alembic/abc_frame_mapper.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2013, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef PTC_ABC_FRAME_MAPPER_H
|
||||
#define PTC_ABC_FRAME_MAPPER_H
|
||||
|
||||
#ifdef WITH_ALEMBIC
|
||||
#include <Alembic/AbcCoreAbstract/Foundation.h>
|
||||
#include <Alembic/Abc/ISampleSelector.h>
|
||||
#endif
|
||||
|
||||
struct Scene;
|
||||
|
||||
namespace PTC {
|
||||
|
||||
#ifdef WITH_ALEMBIC
|
||||
|
||||
using namespace Alembic;
|
||||
using Alembic::AbcCoreAbstract::chrono_t;
|
||||
|
||||
class FrameMapper {
|
||||
public:
|
||||
FrameMapper(double fps, double start_time);
|
||||
FrameMapper(Scene *scene);
|
||||
|
||||
double frames_per_second() const { return m_frames_per_sec; }
|
||||
double seconds_per_frame() const { return m_sec_per_frame; }
|
||||
double start_frame() const { return m_start_frame; }
|
||||
double start_time() const { return m_start_time; }
|
||||
|
||||
chrono_t frame_to_time(float frame) const;
|
||||
float time_to_frame(chrono_t time) const;
|
||||
|
||||
private:
|
||||
double m_frames_per_sec, m_sec_per_frame;
|
||||
double m_start_frame, m_start_time;
|
||||
};
|
||||
|
||||
#endif /* WITH_ALEMBIC */
|
||||
|
||||
} /* namespace PTC */
|
||||
|
||||
#endif /* PTC_UTIL_FRAME_MAPPER_H */
|
424
source/blender/pointcache/alembic/abc_group.cpp
Normal file
424
source/blender/pointcache/alembic/abc_group.cpp
Normal file
@@ -0,0 +1,424 @@
|
||||
/*
|
||||
* Copyright 2013, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include <Alembic/Abc/IObject.h>
|
||||
#include <Alembic/Abc/OObject.h>
|
||||
|
||||
#include "abc_mesh.h"
|
||||
#include "abc_group.h"
|
||||
#include "abc_object.h"
|
||||
|
||||
extern "C" {
|
||||
#include "BLI_math.h"
|
||||
|
||||
#include "DNA_group_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BKE_anim.h"
|
||||
#include "BKE_cache_library.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_group.h"
|
||||
#include "BKE_library.h"
|
||||
}
|
||||
|
||||
namespace PTC {
|
||||
|
||||
using namespace Abc;
|
||||
using namespace AbcGeom;
|
||||
|
||||
AbcGroupWriter::AbcGroupWriter(const std::string &name, Group *group) :
|
||||
GroupWriter(group, name)
|
||||
{
|
||||
}
|
||||
|
||||
void AbcGroupWriter::init_abc()
|
||||
{
|
||||
if (m_abc_object)
|
||||
return;
|
||||
|
||||
m_abc_object = abc_archive()->add_id_object<OObject>((ID *)m_group);
|
||||
}
|
||||
|
||||
void AbcGroupWriter::create_refs()
|
||||
{
|
||||
GroupObject *gob = (GroupObject *)m_group->gobject.first;
|
||||
int i = 0;
|
||||
for (; gob; gob = gob->next, ++i) {
|
||||
OObject abc_object = abc_archive()->get_id_object((ID *)gob->ob);
|
||||
if (abc_object) {
|
||||
std::stringstream ss;
|
||||
ss << i;
|
||||
m_abc_object.addChildInstance(abc_object, std::string("group_object")+ss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AbcGroupWriter::write_sample()
|
||||
{
|
||||
if (!m_abc_object)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
AbcGroupReader::AbcGroupReader(const std::string &name, Group *group) :
|
||||
GroupReader(group, name)
|
||||
{
|
||||
}
|
||||
|
||||
void AbcGroupReader::init_abc()
|
||||
{
|
||||
if (m_abc_object)
|
||||
return;
|
||||
m_abc_object = abc_archive()->get_id_object((ID *)m_group);
|
||||
}
|
||||
|
||||
PTCReadSampleResult AbcGroupReader::read_sample(float frame)
|
||||
{
|
||||
if (!m_abc_object)
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
|
||||
return PTC_READ_SAMPLE_EXACT;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
AbcDupligroupWriter::AbcDupligroupWriter(const std::string &name, EvaluationContext *eval_ctx, Scene *scene, Group *group, CacheLibrary *cachelib) :
|
||||
GroupWriter(group, name),
|
||||
m_eval_ctx(eval_ctx),
|
||||
m_scene(scene),
|
||||
m_cachelib(cachelib)
|
||||
{
|
||||
}
|
||||
|
||||
AbcDupligroupWriter::~AbcDupligroupWriter()
|
||||
{
|
||||
for (IDWriterMap::iterator it = m_id_writers.begin(); it != m_id_writers.end(); ++it) {
|
||||
if (it->second)
|
||||
delete it->second;
|
||||
}
|
||||
}
|
||||
|
||||
void AbcDupligroupWriter::init_abc()
|
||||
{
|
||||
if (m_abc_group)
|
||||
return;
|
||||
|
||||
m_abc_group = abc_archive()->add_id_object<OObject>((ID *)m_group);
|
||||
}
|
||||
|
||||
static bool do_cache_type(CacheLibrary *cachelib, Object *ob, int type, int index=-1)
|
||||
{
|
||||
CacheItem *item = BKE_cache_library_find_item(cachelib, ob, type, index);
|
||||
return item && (item->flag & CACHE_ITEM_ENABLED);
|
||||
}
|
||||
|
||||
void AbcDupligroupWriter::write_sample_object(Object *ob)
|
||||
{
|
||||
AbcWriter *ob_writer = find_id_writer((ID *)ob);
|
||||
if (!ob_writer) {
|
||||
bool do_mesh = do_cache_type(m_cachelib, ob, CACHE_TYPE_DERIVED_MESH);
|
||||
// bool do_hair = do_cache_type(m_cachelib, ob, CACHE_TYPE_HAIR, ); // TODO
|
||||
bool do_hair = false;
|
||||
|
||||
ob_writer = new AbcObjectWriter(ob->id.name, m_scene, ob, do_mesh, do_hair);
|
||||
ob_writer->init(abc_archive());
|
||||
m_id_writers.insert(IDWriterPair((ID *)ob, ob_writer));
|
||||
}
|
||||
|
||||
ob_writer->write_sample();
|
||||
}
|
||||
|
||||
void AbcDupligroupWriter::write_sample_dupli(DupliObject *dob, int index)
|
||||
{
|
||||
OObject abc_object = abc_archive()->get_id_object((ID *)dob->ob);
|
||||
if (!abc_object)
|
||||
return;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "DupliObject" << index;
|
||||
std::string name = ss.str();
|
||||
|
||||
OObject abc_dupli = m_abc_group.getChild(name);
|
||||
OCompoundProperty props;
|
||||
OM44fProperty prop_matrix;
|
||||
if (!abc_dupli) {
|
||||
abc_dupli = OObject(m_abc_group, name, 0);
|
||||
m_object_writers.push_back(abc_dupli.getPtr());
|
||||
props = abc_dupli.getProperties();
|
||||
|
||||
abc_dupli.addChildInstance(abc_object, "object");
|
||||
|
||||
prop_matrix = OM44fProperty(props, "matrix", 0);
|
||||
m_property_writers.push_back(prop_matrix.getPtr());
|
||||
}
|
||||
else {
|
||||
props = abc_dupli.getProperties();
|
||||
|
||||
prop_matrix = OM44fProperty(props.getProperty("matrix").getPtr()->asScalarPtr(), kWrapExisting);
|
||||
}
|
||||
|
||||
prop_matrix.set(M44f(dob->mat));
|
||||
}
|
||||
|
||||
void AbcDupligroupWriter::write_sample()
|
||||
{
|
||||
if (!m_abc_group)
|
||||
return;
|
||||
|
||||
ListBase *duplilist = group_duplilist_ex(m_eval_ctx, m_scene, m_group, true);
|
||||
DupliObject *dob;
|
||||
int i;
|
||||
|
||||
/* LIB_DOIT is used to mark handled objects, clear first */
|
||||
for (dob = (DupliObject *)duplilist->first; dob; dob = dob->next) {
|
||||
if (dob->ob)
|
||||
dob->ob->id.flag &= ~LIB_DOIT;
|
||||
}
|
||||
|
||||
/* write actual object data: duplicator itself + all instanced objects */
|
||||
for (dob = (DupliObject *)duplilist->first; dob; dob = dob->next) {
|
||||
if (dob->ob->id.flag & LIB_DOIT)
|
||||
continue;
|
||||
dob->ob->id.flag |= LIB_DOIT;
|
||||
|
||||
write_sample_object(dob->ob);
|
||||
}
|
||||
|
||||
/* write dupli instances */
|
||||
for (dob = (DupliObject *)duplilist->first, i = 0; dob; dob = dob->next, ++i) {
|
||||
write_sample_dupli(dob, i);
|
||||
}
|
||||
|
||||
free_object_duplilist(duplilist);
|
||||
}
|
||||
|
||||
AbcWriter *AbcDupligroupWriter::find_id_writer(ID *id) const
|
||||
{
|
||||
IDWriterMap::const_iterator it = m_id_writers.find(id);
|
||||
if (it == m_id_writers.end())
|
||||
return NULL;
|
||||
else
|
||||
return it->second;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
AbcDupliCacheReader::AbcDupliCacheReader(const std::string &name, Group *group, DupliCache *dupli_cache) :
|
||||
GroupReader(group, name),
|
||||
dupli_cache(dupli_cache)
|
||||
{
|
||||
/* XXX this mapping allows fast lookup of existing objects in Blender data
|
||||
* to associate with duplis. Later i may be possible to create instances of
|
||||
* non-DNA data, but for the time being this is a requirement due to other code parts (drawing, rendering)
|
||||
*/
|
||||
build_object_map(G.main, group);
|
||||
}
|
||||
|
||||
AbcDupliCacheReader::~AbcDupliCacheReader()
|
||||
{
|
||||
}
|
||||
|
||||
void AbcDupliCacheReader::init_abc()
|
||||
{
|
||||
}
|
||||
|
||||
void AbcDupliCacheReader::read_dupligroup_object(IObject object, float frame)
|
||||
{
|
||||
if (GS(object.getName().c_str()) == ID_OB) {
|
||||
/* instances are handled later, we create true object data here */
|
||||
if (object.isInstanceDescendant())
|
||||
return;
|
||||
|
||||
Object *b_ob = find_object(object.getName());
|
||||
if (!b_ob)
|
||||
return;
|
||||
|
||||
AbcDerivedMeshReader dm_reader("mesh", b_ob);
|
||||
dm_reader.init(abc_archive());
|
||||
dm_reader.init_abc(object);
|
||||
if (dm_reader.read_sample(frame) != PTC_READ_SAMPLE_INVALID) {
|
||||
DerivedMesh *dm = dm_reader.acquire_result();
|
||||
DupliObjectData *data = BKE_dupli_cache_add_mesh(dupli_cache, b_ob, dm);
|
||||
insert_dupli_data(object.getPtr(), data);
|
||||
}
|
||||
else
|
||||
dm_reader.discard_result();
|
||||
}
|
||||
}
|
||||
|
||||
void AbcDupliCacheReader::read_dupligroup_group(IObject abc_group, const ISampleSelector &ss)
|
||||
{
|
||||
if (GS(abc_group.getName().c_str()) == ID_GR) {
|
||||
size_t num_child = abc_group.getNumChildren();
|
||||
|
||||
for (size_t i = 0; i < num_child; ++i) {
|
||||
IObject abc_dupli = abc_group.getChild(i);
|
||||
ICompoundProperty props = abc_dupli.getProperties();
|
||||
|
||||
IM44fProperty prop_matrix(props, "matrix", 0);
|
||||
M44f abc_matrix = prop_matrix.getValue(ss);
|
||||
float matrix[4][4];
|
||||
memcpy(matrix, abc_matrix.getValue(), sizeof(float)*4*4);
|
||||
|
||||
IObject abc_dupli_object = abc_dupli.getChild("object");
|
||||
if (abc_dupli_object.isInstanceRoot()) {
|
||||
DupliObjectData *dupli_data = find_dupli_data(abc_dupli_object.getPtr());
|
||||
if (dupli_data) {
|
||||
BKE_dupli_cache_add_instance(dupli_cache, matrix, dupli_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PTCReadSampleResult AbcDupliCacheReader::read_sample(float frame)
|
||||
{
|
||||
ISampleSelector ss = abc_archive()->get_frame_sample_selector(frame);
|
||||
|
||||
IObject abc_top = abc_archive()->root();
|
||||
IObject abc_group = abc_archive()->get_id_object((ID *)m_group);
|
||||
if (!abc_group)
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
|
||||
/* first create shared object data */
|
||||
for (size_t i = 0; i < abc_top.getNumChildren(); ++i) {
|
||||
read_dupligroup_object(abc_top.getChild(i), frame);
|
||||
}
|
||||
|
||||
/* now generate dupli instances for the group */
|
||||
read_dupligroup_group(abc_group, ss);
|
||||
|
||||
return PTC_READ_SAMPLE_EXACT;
|
||||
}
|
||||
|
||||
DupliObjectData *AbcDupliCacheReader::find_dupli_data(ObjectReaderPtr ptr) const
|
||||
{
|
||||
DupliMap::const_iterator it = dupli_map.find(ptr);
|
||||
if (it == dupli_map.end())
|
||||
return NULL;
|
||||
else
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void AbcDupliCacheReader::insert_dupli_data(ObjectReaderPtr ptr, DupliObjectData *data)
|
||||
{
|
||||
dupli_map.insert(DupliPair(ptr, data));
|
||||
}
|
||||
|
||||
void AbcDupliCacheReader::build_object_map(Main *bmain, Group *group)
|
||||
{
|
||||
BKE_main_id_tag_idcode(bmain, ID_OB, false);
|
||||
BKE_main_id_tag_idcode(bmain, ID_GR, false);
|
||||
object_map.clear();
|
||||
|
||||
build_object_map_add_group(group);
|
||||
}
|
||||
|
||||
Object *AbcDupliCacheReader::find_object(const std::string &name) const
|
||||
{
|
||||
ObjectMap::const_iterator it = object_map.find(name);
|
||||
if (it == object_map.end())
|
||||
return NULL;
|
||||
else
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void AbcDupliCacheReader::build_object_map_add_group(Group *group)
|
||||
{
|
||||
if (group->id.flag & LIB_DOIT)
|
||||
return;
|
||||
group->id.flag |= LIB_DOIT;
|
||||
|
||||
for (GroupObject *gob = (GroupObject *)group->gobject.first; gob; gob = gob->next) {
|
||||
Object *ob = gob->ob;
|
||||
if (ob->id.flag & LIB_DOIT)
|
||||
continue;
|
||||
ob->id.flag |= LIB_DOIT;
|
||||
object_map.insert(ObjectPair(ob->id.name, ob));
|
||||
|
||||
if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
|
||||
build_object_map_add_group(ob->dup_group);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
AbcDupliObjectReader::AbcDupliObjectReader(const std::string &name, Object *ob, DupliObjectData *dupli_data) :
|
||||
ObjectReader(ob, name),
|
||||
dupli_data(dupli_data)
|
||||
{
|
||||
}
|
||||
|
||||
AbcDupliObjectReader::~AbcDupliObjectReader()
|
||||
{
|
||||
}
|
||||
|
||||
void AbcDupliObjectReader::init_abc()
|
||||
{
|
||||
}
|
||||
|
||||
void AbcDupliObjectReader::read_dupligroup_object(IObject object, float frame)
|
||||
{
|
||||
if (GS(object.getName().c_str()) == ID_OB) {
|
||||
/* instances are handled later, we create true object data here */
|
||||
if (object.isInstanceDescendant())
|
||||
return;
|
||||
|
||||
AbcDerivedMeshReader dm_reader("mesh", m_ob);
|
||||
dm_reader.init(abc_archive());
|
||||
dm_reader.init_abc(object);
|
||||
if (dm_reader.read_sample(frame) != PTC_READ_SAMPLE_INVALID) {
|
||||
DerivedMesh *dm = dm_reader.acquire_result();
|
||||
BKE_dupli_object_data_init(dupli_data, m_ob, dm);
|
||||
}
|
||||
else
|
||||
dm_reader.discard_result();
|
||||
}
|
||||
}
|
||||
|
||||
PTCReadSampleResult AbcDupliObjectReader::read_sample(float frame)
|
||||
{
|
||||
IObject abc_object = abc_archive()->get_id_object((ID *)m_ob);
|
||||
if (!abc_object)
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
|
||||
read_dupligroup_object(abc_object, frame);
|
||||
|
||||
return PTC_READ_SAMPLE_EXACT;
|
||||
}
|
||||
|
||||
DupliObjectData *AbcDupliObjectReader::find_dupli_data(ObjectReaderPtr ptr) const
|
||||
{
|
||||
DupliMap::const_iterator it = dupli_map.find(ptr);
|
||||
if (it == dupli_map.end())
|
||||
return NULL;
|
||||
else
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void AbcDupliObjectReader::insert_dupli_data(ObjectReaderPtr ptr, DupliObjectData *data)
|
||||
{
|
||||
dupli_map.insert(DupliPair(ptr, data));
|
||||
}
|
||||
|
||||
} /* namespace PTC */
|
155
source/blender/pointcache/alembic/abc_group.h
Normal file
155
source/blender/pointcache/alembic/abc_group.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright 2013, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef PTC_ABC_GROUP_H
|
||||
#define PTC_ABC_GROUP_H
|
||||
|
||||
#include "ptc_types.h"
|
||||
|
||||
#include "abc_reader.h"
|
||||
#include "abc_schema.h"
|
||||
#include "abc_writer.h"
|
||||
|
||||
struct CacheLibrary;
|
||||
struct DupliCache;
|
||||
struct DupliObject;
|
||||
struct DupliObjectData;
|
||||
struct Group;
|
||||
struct Object;
|
||||
struct Scene;
|
||||
|
||||
namespace PTC {
|
||||
|
||||
class AbcGroupWriter : public GroupWriter, public AbcWriter {
|
||||
public:
|
||||
AbcGroupWriter(const std::string &name, Group *group);
|
||||
|
||||
void init_abc();
|
||||
void create_refs();
|
||||
|
||||
void write_sample();
|
||||
|
||||
private:
|
||||
Abc::OObject m_abc_object;
|
||||
};
|
||||
|
||||
class AbcGroupReader : public GroupReader, public AbcReader {
|
||||
public:
|
||||
AbcGroupReader(const std::string &name, Group *group);
|
||||
|
||||
void init_abc();
|
||||
|
||||
PTCReadSampleResult read_sample(float frame);
|
||||
|
||||
private:
|
||||
Abc::IObject m_abc_object;
|
||||
};
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
class AbcDupligroupWriter : public GroupWriter, public AbcWriter {
|
||||
public:
|
||||
typedef std::vector<Abc::ObjectWriterPtr> ObjectWriterList;
|
||||
typedef std::vector<Abc::BasePropertyWriterPtr> PropertyWriterList;
|
||||
|
||||
typedef std::map<ID*, AbcWriter*> IDWriterMap;
|
||||
typedef std::pair<ID*, AbcWriter*> IDWriterPair;
|
||||
|
||||
AbcDupligroupWriter(const std::string &name, EvaluationContext *eval_ctx, Scene *scene, Group *group, CacheLibrary *cachelib);
|
||||
~AbcDupligroupWriter();
|
||||
|
||||
void init_abc();
|
||||
|
||||
void write_sample();
|
||||
void write_sample_object(Object *ob);
|
||||
void write_sample_dupli(DupliObject *dob, int index);
|
||||
|
||||
AbcWriter *find_id_writer(ID *id) const;
|
||||
|
||||
private:
|
||||
EvaluationContext *m_eval_ctx;
|
||||
Scene *m_scene;
|
||||
CacheLibrary *m_cachelib;
|
||||
|
||||
Abc::OObject m_abc_group;
|
||||
ObjectWriterList m_object_writers;
|
||||
PropertyWriterList m_property_writers;
|
||||
IDWriterMap m_id_writers;
|
||||
};
|
||||
|
||||
class AbcDupliCacheReader : public GroupReader, public AbcReader {
|
||||
public:
|
||||
typedef std::map<Abc::ObjectReaderPtr, DupliObjectData*> DupliMap;
|
||||
typedef std::pair<Abc::ObjectReaderPtr, DupliObjectData*> DupliPair;
|
||||
|
||||
typedef std::map<std::string, Object*> ObjectMap;
|
||||
typedef std::pair<std::string, Object*> ObjectPair;
|
||||
|
||||
public:
|
||||
AbcDupliCacheReader(const std::string &name, Group *group, DupliCache *dupcache);
|
||||
~AbcDupliCacheReader();
|
||||
|
||||
void init_abc();
|
||||
|
||||
PTCReadSampleResult read_sample(float frame);
|
||||
|
||||
protected:
|
||||
void read_dupligroup_object(Abc::IObject object, float frame);
|
||||
void read_dupligroup_group(Abc::IObject abc_group, const Abc::ISampleSelector &ss);
|
||||
|
||||
DupliObjectData *find_dupli_data(Abc::ObjectReaderPtr ptr) const;
|
||||
void insert_dupli_data(Abc::ObjectReaderPtr ptr, DupliObjectData *data);
|
||||
|
||||
void build_object_map(Main *bmain, Group *group);
|
||||
void build_object_map_add_group(Group *group);
|
||||
Object *find_object(const std::string &name) const;
|
||||
|
||||
private:
|
||||
DupliMap dupli_map;
|
||||
DupliCache *dupli_cache;
|
||||
|
||||
ObjectMap object_map;
|
||||
};
|
||||
|
||||
class AbcDupliObjectReader : public ObjectReader, public AbcReader {
|
||||
public:
|
||||
typedef std::map<Abc::ObjectReaderPtr, DupliObjectData*> DupliMap;
|
||||
typedef std::pair<Abc::ObjectReaderPtr, DupliObjectData*> DupliPair;
|
||||
|
||||
public:
|
||||
AbcDupliObjectReader(const std::string &name, Object *ob, DupliObjectData *dupli_data);
|
||||
~AbcDupliObjectReader();
|
||||
|
||||
void init_abc();
|
||||
|
||||
PTCReadSampleResult read_sample(float frame);
|
||||
|
||||
protected:
|
||||
void read_dupligroup_object(Abc::IObject object, float frame);
|
||||
|
||||
DupliObjectData *find_dupli_data(Abc::ObjectReaderPtr ptr) const;
|
||||
void insert_dupli_data(Abc::ObjectReaderPtr ptr, DupliObjectData *data);
|
||||
|
||||
private:
|
||||
DupliMap dupli_map;
|
||||
DupliObjectData *dupli_data;
|
||||
};
|
||||
|
||||
} /* namespace PTC */
|
||||
|
||||
#endif /* PTC_OBJECT_H */
|
259
source/blender/pointcache/alembic/abc_info.cpp
Normal file
259
source/blender/pointcache/alembic/abc_info.cpp
Normal file
@@ -0,0 +1,259 @@
|
||||
//-*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2009-2013,
|
||||
// Sony Pictures Imageworks, Inc. and
|
||||
// Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Sony Pictures Imageworks, nor
|
||||
// Industrial Light & Magic nor the names of their contributors may be used
|
||||
// to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//-*****************************************************************************
|
||||
|
||||
/*
|
||||
* Copyright 2015, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <Alembic/AbcGeom/All.h>
|
||||
#include <Alembic/AbcCoreAbstract/All.h>
|
||||
#include <Alembic/AbcCoreFactory/All.h>
|
||||
#include <Alembic/Util/All.h>
|
||||
#include <Alembic/Abc/TypedPropertyTraits.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "alembic.h"
|
||||
|
||||
extern "C" {
|
||||
#include "BLI_utildefines.h"
|
||||
}
|
||||
|
||||
using namespace ::Alembic::AbcGeom;
|
||||
|
||||
namespace PTC {
|
||||
|
||||
static const std::string g_sep(";");
|
||||
|
||||
static void visitProperties(std::stringstream &ss, ICompoundProperty, std::string &);
|
||||
|
||||
template <class PROP>
|
||||
static void visitSimpleArrayProperty(std::stringstream &ss, PROP iProp, const std::string &iIndent)
|
||||
{
|
||||
std::string ptype = "ArrayProperty ";
|
||||
size_t asize = 0;
|
||||
|
||||
AbcA::ArraySamplePtr samp;
|
||||
index_t maxSamples = iProp.getNumSamples();
|
||||
for (index_t i = 0 ; i < maxSamples; ++i) {
|
||||
iProp.get(samp, ISampleSelector( i ));
|
||||
asize = samp->size();
|
||||
};
|
||||
|
||||
std::string mdstring = "interpretation=";
|
||||
mdstring += iProp.getMetaData().get("interpretation");
|
||||
|
||||
std::stringstream dtype;
|
||||
dtype << "datatype=";
|
||||
dtype << iProp.getDataType();
|
||||
|
||||
std::stringstream asizestr;
|
||||
asizestr << ";arraysize=";
|
||||
asizestr << asize;
|
||||
|
||||
mdstring += g_sep;
|
||||
|
||||
mdstring += dtype.str();
|
||||
|
||||
mdstring += asizestr.str();
|
||||
|
||||
ss << iIndent << " " << ptype << "name=" << iProp.getName()
|
||||
<< g_sep << mdstring << g_sep << "numsamps="
|
||||
<< iProp.getNumSamples() << std::endl;
|
||||
}
|
||||
|
||||
template <class PROP>
|
||||
static void visitSimpleScalarProperty(std::stringstream &ss, PROP iProp, const std::string &iIndent)
|
||||
{
|
||||
std::string ptype = "ScalarProperty ";
|
||||
size_t asize = 0;
|
||||
|
||||
const AbcA::DataType &dt = iProp.getDataType();
|
||||
const Alembic::Util ::uint8_t extent = dt.getExtent();
|
||||
Alembic::Util::Dimensions dims(extent);
|
||||
AbcA::ArraySamplePtr samp = AbcA::AllocateArraySample( dt, dims );
|
||||
index_t maxSamples = iProp.getNumSamples();
|
||||
for (index_t i = 0 ; i < maxSamples; ++i) {
|
||||
iProp.get(const_cast<void*>(samp->getData()), ISampleSelector( i ));
|
||||
asize = samp->size();
|
||||
};
|
||||
|
||||
std::string mdstring = "interpretation=";
|
||||
mdstring += iProp.getMetaData().get("interpretation");
|
||||
|
||||
std::stringstream dtype;
|
||||
dtype << "datatype=";
|
||||
dtype << dt;
|
||||
|
||||
std::stringstream asizestr;
|
||||
asizestr << ";arraysize=";
|
||||
asizestr << asize;
|
||||
|
||||
mdstring += g_sep;
|
||||
|
||||
mdstring += dtype.str();
|
||||
|
||||
mdstring += asizestr.str();
|
||||
|
||||
ss << iIndent << " " << ptype << "name=" << iProp.getName()
|
||||
<< g_sep << mdstring << g_sep << "numsamps="
|
||||
<< iProp.getNumSamples() << std::endl;
|
||||
}
|
||||
|
||||
static void visitCompoundProperty(std::stringstream &ss, ICompoundProperty iProp, std::string &ioIndent)
|
||||
{
|
||||
std::string oldIndent = ioIndent;
|
||||
ioIndent += " ";
|
||||
|
||||
std::string interp = "schema=";
|
||||
interp += iProp.getMetaData().get("schema");
|
||||
|
||||
ss << ioIndent << "CompoundProperty " << "name=" << iProp.getName()
|
||||
<< g_sep << interp << std::endl;
|
||||
|
||||
visitProperties(ss, iProp, ioIndent);
|
||||
|
||||
ioIndent = oldIndent;
|
||||
}
|
||||
|
||||
static void visitProperties(std::stringstream &ss, ICompoundProperty iParent, std::string &ioIndent )
|
||||
{
|
||||
std::string oldIndent = ioIndent;
|
||||
for (size_t i = 0 ; i < iParent.getNumProperties() ; i++) {
|
||||
PropertyHeader header = iParent.getPropertyHeader(i);
|
||||
|
||||
if (header.isCompound()) {
|
||||
visitCompoundProperty(ss, ICompoundProperty(iParent, header.getName()), ioIndent);
|
||||
}
|
||||
else if (header.isScalar()) {
|
||||
visitSimpleScalarProperty(ss, IScalarProperty(iParent, header.getName()), ioIndent);
|
||||
}
|
||||
else {
|
||||
BLI_assert(header.isArray());
|
||||
visitSimpleArrayProperty(ss, IArrayProperty(iParent, header.getName()), ioIndent);
|
||||
}
|
||||
}
|
||||
|
||||
ioIndent = oldIndent;
|
||||
}
|
||||
|
||||
static void visitObject(std::stringstream &ss, IObject iObj, std::string iIndent)
|
||||
{
|
||||
// Object has a name, a full name, some meta data,
|
||||
// and then it has a compound property full of properties.
|
||||
std::string path = iObj.getFullName();
|
||||
|
||||
if (iObj.isInstanceRoot()) {
|
||||
if (path != "/") {
|
||||
ss << "Object " << "name=" << path
|
||||
<< " [Instance " << iObj.instanceSourcePath() << "]"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
else if (iObj.isInstanceDescendant()) {
|
||||
/* skip non-root instances to avoid repetition */
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (path != "/") {
|
||||
ss << "Object " << "name=" << path << std::endl;
|
||||
}
|
||||
|
||||
// Get the properties.
|
||||
ICompoundProperty props = iObj.getProperties();
|
||||
visitProperties(ss, props, iIndent);
|
||||
|
||||
// now the child objects
|
||||
for (size_t i = 0 ; i < iObj.getNumChildren() ; i++) {
|
||||
visitObject(ss, IObject(iObj, iObj.getChildHeader(i).getName()), iIndent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string abc_archive_info(IArchive &archive)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "Alembic Archive Info for "
|
||||
<< Alembic::AbcCoreAbstract::GetLibraryVersion()
|
||||
<< std::endl;;
|
||||
|
||||
std::string appName;
|
||||
std::string libraryVersionString;
|
||||
Alembic::Util::uint32_t libraryVersion;
|
||||
std::string whenWritten;
|
||||
std::string userDescription;
|
||||
GetArchiveInfo(archive,
|
||||
appName,
|
||||
libraryVersionString,
|
||||
libraryVersion,
|
||||
whenWritten,
|
||||
userDescription);
|
||||
|
||||
if (appName != "") {
|
||||
ss << " file written by: " << appName << std::endl;
|
||||
ss << " using Alembic : " << libraryVersionString << std::endl;
|
||||
ss << " written on : " << whenWritten << std::endl;
|
||||
ss << " user description : " << userDescription << std::endl;
|
||||
ss << std::endl;
|
||||
}
|
||||
else {
|
||||
// ss << argv[1] << std::endl;
|
||||
ss << " (file doesn't have any ArchiveInfo)"
|
||||
<< std::endl;
|
||||
ss << std::endl;
|
||||
}
|
||||
|
||||
visitObject(ss, archive.getTop(), "");
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} /* namespace PTC */
|
638
source/blender/pointcache/alembic/abc_mesh.cpp
Normal file
638
source/blender/pointcache/alembic/abc_mesh.cpp
Normal file
@@ -0,0 +1,638 @@
|
||||
/*
|
||||
* Copyright 2014, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "abc_mesh.h"
|
||||
|
||||
extern "C" {
|
||||
#include "BLI_math.h"
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_cdderivedmesh.h"
|
||||
#include "BKE_mesh.h"
|
||||
|
||||
#include "PIL_time.h"
|
||||
}
|
||||
|
||||
#include "PTC_api.h"
|
||||
|
||||
//#define USE_TIMING
|
||||
|
||||
namespace PTC {
|
||||
|
||||
using namespace Abc;
|
||||
using namespace AbcGeom;
|
||||
|
||||
/* CD layers that are stored in generic customdata arrays created with CD_ALLOC */
|
||||
static CustomDataMask CD_MASK_CACHE = ~(CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE | CD_MASK_MPOLY | CD_MASK_MLOOP | CD_MASK_BMESH | CD_MASK_MTFACE);
|
||||
|
||||
struct MVertSample {
|
||||
std::vector<V3f> co;
|
||||
std::vector<N3f> no;
|
||||
std::vector<int8_t> flag;
|
||||
std::vector<int8_t> bweight;
|
||||
};
|
||||
|
||||
struct MEdgeSample {
|
||||
std::vector<uint32_t> verts;
|
||||
std::vector<int16_t> flag;
|
||||
std::vector<int8_t> crease;
|
||||
std::vector<int8_t> bweight;
|
||||
};
|
||||
|
||||
struct MPolySample {
|
||||
/*std::vector<int32_t> loopstart;*/ /* loopstart is not stored explicitly */
|
||||
std::vector<int32_t> totloop;
|
||||
std::vector<int16_t> mat_nr;
|
||||
std::vector<int8_t> flag;
|
||||
};
|
||||
|
||||
struct MLoopSample {
|
||||
/* XXX these are unsigned int in DNA, but Alembic expects signed int */
|
||||
std::vector<int32_t> verts;
|
||||
std::vector<int32_t> edges;
|
||||
};
|
||||
|
||||
AbcDerivedMeshWriter::AbcDerivedMeshWriter(const std::string &name, Object *ob, DerivedMesh **dm_ptr) :
|
||||
DerivedMeshWriter(ob, dm_ptr, name),
|
||||
m_vert_data_writer("vertex_data", CD_MASK_CACHE),
|
||||
m_edge_data_writer("edge_data", CD_MASK_CACHE),
|
||||
m_face_data_writer("face_data", CD_MASK_CACHE),
|
||||
m_poly_data_writer("poly_data", CD_MASK_CACHE),
|
||||
m_loop_data_writer("loop_data", CD_MASK_CACHE)
|
||||
{
|
||||
}
|
||||
|
||||
AbcDerivedMeshWriter::~AbcDerivedMeshWriter()
|
||||
{
|
||||
}
|
||||
|
||||
void AbcDerivedMeshWriter::init_abc(OObject parent)
|
||||
{
|
||||
if (m_mesh)
|
||||
return;
|
||||
|
||||
m_mesh = OPolyMesh(parent, m_name, abc_archive()->frame_sampling_index());
|
||||
|
||||
OPolyMeshSchema &schema = m_mesh.getSchema();
|
||||
// OCompoundProperty geom_props = schema.getArbGeomParams();
|
||||
OCompoundProperty user_props = schema.getUserProperties();
|
||||
|
||||
m_prop_vert_normals = ON3fArrayProperty(user_props, "vertex_normals", 0);
|
||||
m_prop_vert_flag = OCharArrayProperty(user_props, "vertex_flag", 0);
|
||||
m_prop_vert_bweight = OCharArrayProperty(user_props, "vertex_bweight", 0);
|
||||
|
||||
m_prop_edge_verts = OUInt32ArrayProperty(user_props, "edge_verts", 0);
|
||||
m_prop_edge_flag = OInt16ArrayProperty(user_props, "edge_flag", 0);
|
||||
m_prop_edge_crease = OCharArrayProperty(user_props, "edge_crease", 0);
|
||||
m_prop_edge_bweight = OCharArrayProperty(user_props, "edge_bweight", 0);
|
||||
|
||||
m_prop_poly_mat_nr = OInt16ArrayProperty(user_props, "poly_mat_nr", 0);
|
||||
m_prop_poly_flag = OCharArrayProperty(user_props, "poly_flag", 0);
|
||||
|
||||
m_prop_loop_verts = OInt32ArrayProperty(user_props, "loop_verts", 0);
|
||||
m_prop_loop_edges = OInt32ArrayProperty(user_props, "loop_edges", 0);
|
||||
}
|
||||
|
||||
/* XXX modifiers are not allowed to generate poly normals on their own!
|
||||
* see assert in DerivedMesh.c : dm_ensure_display_normals
|
||||
*/
|
||||
#if 0
|
||||
static void ensure_normal_data(DerivedMesh *dm)
|
||||
{
|
||||
MVert *mverts = dm->getVertArray(dm);
|
||||
MLoop *mloops = dm->getLoopArray(dm);
|
||||
MPoly *mpolys = dm->getPolyArray(dm);
|
||||
CustomData *cdata = dm->getPolyDataLayout(dm);
|
||||
float (*polynors)[3];
|
||||
int totvert = dm->getNumVerts(dm);
|
||||
int totloop = dm->getNumLoops(dm);
|
||||
int totpoly = dm->getNumPolys(dm);
|
||||
|
||||
if (CustomData_has_layer(cdata, CD_NORMAL))
|
||||
polynors = (float (*)[3])CustomData_get_layer(cdata, CD_NORMAL);
|
||||
else
|
||||
polynors = (float (*)[3])CustomData_add_layer(cdata, CD_NORMAL, CD_CALLOC, NULL, totpoly);
|
||||
|
||||
BKE_mesh_calc_normals_poly(mverts, totvert, mloops, mpolys, totloop, totpoly, polynors, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void create_sample_verts(DerivedMesh *dm, MVertSample &sample)
|
||||
{
|
||||
MVert *mv, *mverts = dm->getVertArray(dm);
|
||||
int i, totvert = dm->getNumVerts(dm);
|
||||
|
||||
sample.co.reserve(totvert);
|
||||
sample.no.reserve(totvert);
|
||||
sample.flag.reserve(totvert);
|
||||
sample.bweight.reserve(totvert);
|
||||
for (i = 0, mv = mverts; i < totvert; ++i, ++mv) {
|
||||
float nor[3];
|
||||
|
||||
sample.co.push_back(V3f(mv->co[0], mv->co[1], mv->co[2]));
|
||||
|
||||
normal_short_to_float_v3(nor, mv->no);
|
||||
sample.no.push_back(N3f(nor[0], nor[1], nor[2]));
|
||||
|
||||
sample.flag.push_back(mv->flag);
|
||||
sample.bweight.push_back(mv->bweight);
|
||||
}
|
||||
}
|
||||
|
||||
static void create_sample_edges(DerivedMesh *dm, MEdgeSample &sample)
|
||||
{
|
||||
MEdge *me, *medges = dm->getEdgeArray(dm);
|
||||
int i, totedge = dm->getNumEdges(dm);
|
||||
|
||||
sample.verts.reserve(totedge * 2);
|
||||
sample.flag.reserve(totedge);
|
||||
sample.crease.reserve(totedge);
|
||||
sample.bweight.reserve(totedge);
|
||||
|
||||
for (i = 0, me = medges; i < totedge; ++i, ++me) {
|
||||
sample.verts.push_back(me->v1);
|
||||
sample.verts.push_back(me->v2);
|
||||
sample.flag.push_back(me->flag);
|
||||
sample.crease.push_back(me->crease);
|
||||
sample.bweight.push_back(me->bweight);
|
||||
}
|
||||
}
|
||||
|
||||
static void create_sample_polys(DerivedMesh *dm, MPolySample &sample)
|
||||
{
|
||||
MPoly *mp, *mpolys = dm->getPolyArray(dm);
|
||||
int i, totpoly = dm->getNumPolys(dm);
|
||||
|
||||
sample.totloop.reserve(totpoly);
|
||||
sample.mat_nr.reserve(totpoly);
|
||||
sample.flag.reserve(totpoly);
|
||||
|
||||
for (i = 0, mp = mpolys; i < totpoly; ++i, ++mp) {
|
||||
sample.totloop.push_back(mp->totloop);
|
||||
sample.mat_nr.push_back(mp->mat_nr);
|
||||
sample.flag.push_back(mp->flag);
|
||||
}
|
||||
}
|
||||
|
||||
static void create_sample_loops(DerivedMesh *dm, MLoopSample &sample)
|
||||
{
|
||||
MLoop *ml, *mloops = dm->getLoopArray(dm);
|
||||
int i, totloop = dm->getNumLoops(dm);
|
||||
|
||||
sample.verts.reserve(totloop);
|
||||
sample.edges.reserve(totloop);
|
||||
|
||||
for (i = 0, ml = mloops; i < totloop; ++i, ++ml) {
|
||||
sample.verts.push_back(ml->v);
|
||||
sample.edges.push_back(ml->e);
|
||||
}
|
||||
}
|
||||
|
||||
static N3fArraySample create_sample_loop_normals(DerivedMesh *dm, std::vector<N3f> &data)
|
||||
{
|
||||
CustomData *cdata = dm->getLoopDataLayout(dm);
|
||||
float (*nor)[3], (*loopnors)[3];
|
||||
int i, totloop = dm->getNumLoops(dm);
|
||||
|
||||
if (!CustomData_has_layer(cdata, CD_NORMAL))
|
||||
return N3fArraySample();
|
||||
|
||||
loopnors = (float (*)[3])CustomData_get_layer(cdata, CD_NORMAL);
|
||||
|
||||
data.reserve(totloop);
|
||||
for (i = 0, nor = loopnors; i < totloop; ++i, ++nor) {
|
||||
float *vec = *nor;
|
||||
data.push_back(N3f(vec[0], vec[1], vec[2]));
|
||||
}
|
||||
|
||||
return N3fArraySample(data);
|
||||
}
|
||||
|
||||
void AbcDerivedMeshWriter::write_sample()
|
||||
{
|
||||
if (!m_mesh)
|
||||
return;
|
||||
|
||||
DerivedMesh *output_dm = *m_dm_ptr;
|
||||
if (!output_dm)
|
||||
return;
|
||||
|
||||
/* TODO make this optional by a flag? */
|
||||
/* XXX does not work atm, see comment above */
|
||||
/*ensure_normal_data(output_dm);*/
|
||||
|
||||
OPolyMeshSchema &schema = m_mesh.getSchema();
|
||||
OCompoundProperty user_props = schema.getUserProperties();
|
||||
|
||||
MVertSample vert_sample;
|
||||
MEdgeSample edge_sample;
|
||||
MPolySample poly_sample;
|
||||
MLoopSample loop_sample;
|
||||
|
||||
std::vector<N3f> loop_normals_buffer;
|
||||
|
||||
// TODO decide how to handle vertex/face normals, in caching vs. export ...
|
||||
|
||||
create_sample_verts(output_dm, vert_sample);
|
||||
create_sample_edges(output_dm, edge_sample);
|
||||
create_sample_polys(output_dm, poly_sample);
|
||||
create_sample_loops(output_dm, loop_sample);
|
||||
|
||||
N3fArraySample lnormals = create_sample_loop_normals(output_dm, loop_normals_buffer);
|
||||
|
||||
OPolyMeshSchema::Sample sample = OPolyMeshSchema::Sample(
|
||||
P3fArraySample(vert_sample.co),
|
||||
Int32ArraySample(loop_sample.verts),
|
||||
Int32ArraySample(poly_sample.totloop),
|
||||
OV2fGeomParam::Sample(), /* XXX define how/which UV map should be considered primary for the alembic schema */
|
||||
ON3fGeomParam::Sample(lnormals, kFacevaryingScope)
|
||||
);
|
||||
schema.set(sample);
|
||||
|
||||
m_prop_vert_normals.set(N3fArraySample(vert_sample.no));
|
||||
m_prop_vert_flag.set(CharArraySample(vert_sample.flag));
|
||||
m_prop_vert_bweight.set(CharArraySample(vert_sample.bweight));
|
||||
|
||||
m_prop_edge_verts.set(UInt32ArraySample(edge_sample.verts));
|
||||
m_prop_edge_flag.set(Int16ArraySample(edge_sample.flag));
|
||||
m_prop_edge_crease.set(CharArraySample(edge_sample.crease));
|
||||
m_prop_edge_bweight.set(CharArraySample(edge_sample.bweight));
|
||||
|
||||
m_prop_poly_mat_nr.set(Int16ArraySample(poly_sample.mat_nr));
|
||||
m_prop_poly_flag.set(CharArraySample(poly_sample.flag));
|
||||
|
||||
m_prop_loop_verts.set(Int32ArraySample(loop_sample.verts));
|
||||
m_prop_loop_edges.set(Int32ArraySample(loop_sample.edges));
|
||||
|
||||
CustomData *vdata = output_dm->getVertDataLayout(output_dm);
|
||||
int num_vdata = output_dm->getNumVerts(output_dm);
|
||||
m_vert_data_writer.write_sample(vdata, num_vdata, user_props);
|
||||
|
||||
CustomData *edata = output_dm->getEdgeDataLayout(output_dm);
|
||||
int num_edata = output_dm->getNumEdges(output_dm);
|
||||
m_edge_data_writer.write_sample(edata, num_edata, user_props);
|
||||
|
||||
DM_ensure_tessface(output_dm);
|
||||
CustomData *fdata = output_dm->getTessFaceDataLayout(output_dm);
|
||||
int num_fdata = output_dm->getNumTessFaces(output_dm);
|
||||
m_face_data_writer.write_sample(fdata, num_fdata, user_props);
|
||||
|
||||
CustomData *pdata = output_dm->getPolyDataLayout(output_dm);
|
||||
int num_pdata = output_dm->getNumPolys(output_dm);
|
||||
m_poly_data_writer.write_sample(pdata, num_pdata, user_props);
|
||||
|
||||
CustomData *ldata = output_dm->getLoopDataLayout(output_dm);
|
||||
int num_ldata = output_dm->getNumLoops(output_dm);
|
||||
m_loop_data_writer.write_sample(ldata, num_ldata, user_props);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
AbcDerivedMeshReader::AbcDerivedMeshReader(const std::string &name, Object *ob) :
|
||||
DerivedMeshReader(ob, name),
|
||||
m_vert_data_reader("vertex_data", CD_MASK_CACHE),
|
||||
m_edge_data_reader("edge_data", CD_MASK_CACHE),
|
||||
m_face_data_reader("face_data", CD_MASK_CACHE),
|
||||
m_poly_data_reader("poly_data", CD_MASK_CACHE),
|
||||
m_loop_data_reader("loop_data", CD_MASK_CACHE)
|
||||
{
|
||||
}
|
||||
|
||||
AbcDerivedMeshReader::~AbcDerivedMeshReader()
|
||||
{
|
||||
}
|
||||
|
||||
void AbcDerivedMeshReader::init_abc(IObject parent)
|
||||
{
|
||||
if (m_mesh)
|
||||
return;
|
||||
if (parent.getChild(m_name)) {
|
||||
m_mesh = IPolyMesh(parent, m_name);
|
||||
|
||||
IPolyMeshSchema &schema = m_mesh.getSchema();
|
||||
ICompoundProperty geom_props = schema.getArbGeomParams();
|
||||
ICompoundProperty user_props = schema.getUserProperties();
|
||||
|
||||
m_prop_vert_normals = IN3fArrayProperty(user_props, "vertex_normals", 0);
|
||||
m_prop_vert_flag = ICharArrayProperty(user_props, "vertex_flag", 0);
|
||||
m_prop_vert_bweight = ICharArrayProperty(user_props, "vertex_bweight", 0);
|
||||
|
||||
m_prop_edge_verts = IUInt32ArrayProperty(user_props, "edge_verts", 0);
|
||||
m_prop_edge_flag = IInt16ArrayProperty(user_props, "edge_flag", 0);
|
||||
m_prop_edge_crease = ICharArrayProperty(user_props, "edge_crease", 0);
|
||||
m_prop_edge_bweight = ICharArrayProperty(user_props, "edge_bweight", 0);
|
||||
|
||||
m_prop_poly_mat_nr = IInt16ArrayProperty(user_props, "poly_mat_nr", 0);
|
||||
m_prop_poly_flag = ICharArrayProperty(user_props, "poly_flag", 0);
|
||||
|
||||
m_prop_loop_verts = IInt32ArrayProperty(user_props, "loop_verts", 0);
|
||||
m_prop_loop_edges = IInt32ArrayProperty(user_props, "loop_edges", 0);
|
||||
}
|
||||
}
|
||||
|
||||
static PTCReadSampleResult apply_sample_verts(DerivedMesh *dm, P3fArraySamplePtr sample_co, N3fArraySamplePtr sample_no,
|
||||
CharArraySamplePtr sample_flag, CharArraySamplePtr sample_bweight)
|
||||
{
|
||||
int totvert = dm->getNumVerts(dm);
|
||||
|
||||
if (sample_co->size() != totvert ||
|
||||
sample_no->size() != totvert ||
|
||||
sample_flag->size() != totvert ||
|
||||
sample_bweight->size() != totvert)
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
|
||||
MVert *mv = dm->getVertArray(dm);
|
||||
for (int i = 0; i < totvert; ++i) {
|
||||
copy_v3_v3(mv->co, (*sample_co)[i].getValue());
|
||||
normal_float_to_short_v3(mv->no, (*sample_no)[i].getValue());
|
||||
mv->flag = (*sample_flag)[i];
|
||||
mv->bweight = (*sample_bweight)[i];
|
||||
|
||||
++mv;
|
||||
}
|
||||
|
||||
return PTC_READ_SAMPLE_EXACT;
|
||||
}
|
||||
|
||||
static PTCReadSampleResult apply_sample_edges(DerivedMesh *dm, UInt32ArraySamplePtr sample_verts, Int16ArraySamplePtr sample_flag,
|
||||
CharArraySamplePtr sample_crease, CharArraySamplePtr sample_bweight, bool &has_edges)
|
||||
{
|
||||
int totedge = dm->getNumEdges(dm);
|
||||
if (sample_verts->size() != totedge * 2 ||
|
||||
sample_flag->size() != totedge ||
|
||||
sample_crease->size() != totedge ||
|
||||
sample_bweight->size() != totedge)
|
||||
{
|
||||
has_edges = false;
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
}
|
||||
|
||||
const uint32_t *data_verts = sample_verts->get();
|
||||
const int16_t *data_flag = sample_flag->get();
|
||||
const int8_t *data_crease = sample_crease->get();
|
||||
const int8_t *data_bweight = sample_bweight->get();
|
||||
|
||||
MEdge *me = dm->getEdgeArray(dm);
|
||||
for (int i = 0; i < totedge; ++i) {
|
||||
me->v1 = data_verts[0];
|
||||
me->v2 = data_verts[1];
|
||||
me->flag = *data_flag;
|
||||
me->crease = *data_crease;
|
||||
me->bweight = *data_bweight;
|
||||
|
||||
++me;
|
||||
data_verts += 2;
|
||||
++data_flag;
|
||||
++data_crease;
|
||||
++data_bweight;
|
||||
}
|
||||
|
||||
return PTC_READ_SAMPLE_EXACT;
|
||||
}
|
||||
|
||||
static PTCReadSampleResult apply_sample_polys(DerivedMesh *dm, Int32ArraySamplePtr sample_totloop, Int16ArraySamplePtr sample_mat_nr, CharArraySamplePtr sample_flag)
|
||||
{
|
||||
int totpoly = dm->getNumPolys(dm);
|
||||
if (sample_totloop->size() != totpoly ||
|
||||
sample_mat_nr->size() != totpoly ||
|
||||
sample_flag->size() != totpoly)
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
|
||||
const int32_t *data_totloop = sample_totloop->get();
|
||||
const int16_t *data_mat_nr = sample_mat_nr->get();
|
||||
const int8_t *data_flag = sample_flag->get();
|
||||
|
||||
int loopstart = 0;
|
||||
MPoly *mp = dm->getPolyArray(dm);
|
||||
for (int i = 0; i < totpoly; ++i) {
|
||||
mp->totloop = *data_totloop;
|
||||
mp->loopstart = loopstart;
|
||||
mp->mat_nr = *data_mat_nr;
|
||||
mp->flag = *data_flag;
|
||||
|
||||
loopstart += mp->totloop;
|
||||
|
||||
++mp;
|
||||
++data_totloop;
|
||||
++data_mat_nr;
|
||||
++data_flag;
|
||||
}
|
||||
|
||||
return PTC_READ_SAMPLE_EXACT;
|
||||
}
|
||||
|
||||
static PTCReadSampleResult apply_sample_loops(DerivedMesh *dm, Int32ArraySamplePtr sample_verts, Int32ArraySamplePtr sample_edges, bool &has_edges)
|
||||
{
|
||||
int totloop = dm->getNumLoops(dm);
|
||||
if (sample_verts->size() != totloop)
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
|
||||
const int32_t *data_verts = sample_verts->get();
|
||||
|
||||
MLoop *ml = dm->getLoopArray(dm);
|
||||
for (int i = 0; i < totloop; ++i) {
|
||||
ml->v = *data_verts;
|
||||
|
||||
++ml;
|
||||
++data_verts;
|
||||
}
|
||||
|
||||
/* edge data is optional, if not available the edges must be recalculated */
|
||||
if (sample_edges->size() == totloop) {
|
||||
const int32_t *data_edges = sample_edges->get();
|
||||
|
||||
MLoop *ml = dm->getLoopArray(dm);
|
||||
for (int i = 0; i < totloop; ++i) {
|
||||
ml->e = *data_edges;
|
||||
|
||||
++ml;
|
||||
++data_edges;
|
||||
}
|
||||
}
|
||||
else {
|
||||
has_edges = false;
|
||||
}
|
||||
|
||||
return PTC_READ_SAMPLE_EXACT;
|
||||
}
|
||||
|
||||
PTCReadSampleResult AbcDerivedMeshReader::read_sample(float frame)
|
||||
{
|
||||
#ifdef USE_TIMING
|
||||
double start_time;
|
||||
double time_get_sample, time_build_mesh, time_calc_edges, time_calc_normals;
|
||||
|
||||
#define PROFILE_START \
|
||||
start_time = PIL_check_seconds_timer();
|
||||
#define PROFILE_END(var) \
|
||||
var = PIL_check_seconds_timer() - start_time;
|
||||
#else
|
||||
#define PROFILE_START ;
|
||||
#define PROFILE_END(var) ;
|
||||
#endif
|
||||
|
||||
/* discard existing result data */
|
||||
discard_result();
|
||||
|
||||
if (!m_mesh)
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
|
||||
IPolyMeshSchema &schema = m_mesh.getSchema();
|
||||
if (!schema.valid() || schema.getPositionsProperty().getNumSamples() == 0)
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
ICompoundProperty user_props = schema.getUserProperties();
|
||||
|
||||
ISampleSelector ss = abc_archive()->get_frame_sample_selector(frame);
|
||||
|
||||
PROFILE_START;
|
||||
IPolyMeshSchema::Sample sample;
|
||||
schema.get(sample, ss);
|
||||
|
||||
P3fArraySamplePtr vert_co = sample.getPositions();
|
||||
Int32ArraySamplePtr loop_verts = sample.getFaceIndices();
|
||||
Int32ArraySamplePtr poly_totloop = sample.getFaceCounts();
|
||||
|
||||
N3fArraySamplePtr vnormals;
|
||||
bool has_normals = false;
|
||||
if (m_prop_vert_normals && m_prop_vert_normals.getNumSamples() > 0) {
|
||||
vnormals = m_prop_vert_normals.getValue(ss);
|
||||
has_normals = vnormals->valid();
|
||||
}
|
||||
|
||||
UInt32ArraySamplePtr edge_verts = m_prop_edge_verts.getValue(ss);
|
||||
Int32ArraySamplePtr loop_edges = m_prop_loop_edges.getValue(ss);
|
||||
PROFILE_END(time_get_sample);
|
||||
|
||||
PROFILE_START;
|
||||
bool has_edges = true; // XXX do we have to check for existing sample in advance?
|
||||
int totverts = vert_co->size();
|
||||
int totloops = loop_verts->size();
|
||||
int totpolys = poly_totloop->size();
|
||||
int totedges = has_edges ? edge_verts->size() >> 1 : 0;
|
||||
m_result = CDDM_new(totverts, totedges, 0, totloops, totpolys);
|
||||
|
||||
apply_sample_verts(m_result, vert_co, vnormals, m_prop_vert_flag.getValue(ss), m_prop_vert_bweight.getValue(ss));
|
||||
apply_sample_edges(m_result, edge_verts, m_prop_edge_flag.getValue(ss), m_prop_edge_crease.getValue(ss), m_prop_edge_bweight.getValue(ss), has_edges);
|
||||
apply_sample_polys(m_result, poly_totloop, m_prop_poly_mat_nr.getValue(ss), m_prop_poly_flag.getValue(ss));
|
||||
apply_sample_loops(m_result, loop_verts, loop_edges, has_edges);
|
||||
PROFILE_END(time_build_mesh);
|
||||
|
||||
CustomData *vdata = m_result->getVertDataLayout(m_result);
|
||||
int num_vdata = totverts;
|
||||
m_vert_data_reader.read_sample(ss, vdata, num_vdata, user_props);
|
||||
|
||||
CustomData *edata = m_result->getEdgeDataLayout(m_result);
|
||||
int num_edata = totedges;
|
||||
m_edge_data_reader.read_sample(ss, edata, num_edata, user_props);
|
||||
|
||||
DM_ensure_tessface(m_result);
|
||||
CustomData *fdata = m_result->getTessFaceDataLayout(m_result);
|
||||
int num_fdata = m_result->getNumTessFaces(m_result);
|
||||
m_face_data_reader.read_sample(ss, fdata, num_fdata, user_props);
|
||||
|
||||
CustomData *pdata = m_result->getPolyDataLayout(m_result);
|
||||
int num_pdata = totpolys;
|
||||
m_poly_data_reader.read_sample(ss, pdata, num_pdata, user_props);
|
||||
|
||||
CustomData *ldata = m_result->getLoopDataLayout(m_result);
|
||||
int num_ldata = totloops;
|
||||
m_loop_data_reader.read_sample(ss, ldata, num_ldata, user_props);
|
||||
|
||||
PROFILE_START;
|
||||
if (!has_edges)
|
||||
CDDM_calc_edges(m_result);
|
||||
PROFILE_END(time_calc_edges);
|
||||
|
||||
PROFILE_START;
|
||||
/* we need all normal properties defined, otherwise have to recalculate */
|
||||
has_normals &= CustomData_has_layer(pdata, CD_NORMAL);
|
||||
if (!has_normals) {
|
||||
/* make sure normals are recalculated if there is no sample data */
|
||||
m_result->dirty = (DMDirtyFlag)((int)m_result->dirty | DM_DIRTY_NORMALS);
|
||||
}
|
||||
DM_ensure_normals(m_result); /* only recalculates normals if no valid samples were found (has_normals == false) */
|
||||
PROFILE_END(time_calc_normals);
|
||||
|
||||
// BLI_assert(DM_is_valid(m_result));
|
||||
|
||||
#ifdef USE_TIMING
|
||||
printf("-------- Point Cache Timing --------\n");
|
||||
printf("read sample: %f seconds\n", time_get_sample);
|
||||
printf("build mesh: %f seconds\n", time_build_mesh);
|
||||
printf("calculate edges: %f seconds\n", time_calc_edges);
|
||||
printf("calculate normals: %f seconds\n", time_calc_normals);
|
||||
printf("------------------------------------\n");
|
||||
#endif
|
||||
|
||||
return PTC_READ_SAMPLE_EXACT;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
AbcDerivedFinalRealtimeWriter::AbcDerivedFinalRealtimeWriter(const std::string &name, Object *ob) :
|
||||
AbcDerivedMeshWriter(name, ob, &ob->derivedFinal)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AbcCacheModifierRealtimeWriter::AbcCacheModifierRealtimeWriter(const std::string &name, Object *ob, CacheModifierData *cmd) :
|
||||
AbcDerivedMeshWriter(name, ob, &cmd->output_dm),
|
||||
m_cmd(cmd)
|
||||
{
|
||||
m_cmd->flag |= MOD_CACHE_USE_OUTPUT_REALTIME;
|
||||
}
|
||||
|
||||
AbcCacheModifierRealtimeWriter::~AbcCacheModifierRealtimeWriter()
|
||||
{
|
||||
m_cmd->flag &= ~MOD_CACHE_USE_OUTPUT_REALTIME;
|
||||
if (m_cmd->output_dm) {
|
||||
m_cmd->output_dm->release(m_cmd->output_dm);
|
||||
m_cmd->output_dm = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AbcDerivedFinalRenderWriter::AbcDerivedFinalRenderWriter(const std::string &name, Scene *scene, Object *ob, DerivedMesh **render_dm_ptr) :
|
||||
AbcDerivedMeshWriter(name, ob, render_dm_ptr),
|
||||
m_scene(scene)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AbcCacheModifierRenderWriter::AbcCacheModifierRenderWriter(const std::string &name, Scene *scene, Object *ob, CacheModifierData *cmd) :
|
||||
AbcDerivedMeshWriter(name, ob, &cmd->output_dm),
|
||||
m_scene(scene),
|
||||
m_cmd(cmd)
|
||||
{
|
||||
}
|
||||
|
||||
AbcCacheModifierRenderWriter::~AbcCacheModifierRenderWriter()
|
||||
{
|
||||
m_cmd->flag &= ~MOD_CACHE_USE_OUTPUT_RENDER;
|
||||
if (m_cmd->output_dm) {
|
||||
m_cmd->output_dm->release(m_cmd->output_dm);
|
||||
m_cmd->output_dm = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace PTC */
|
175
source/blender/pointcache/alembic/abc_mesh.h
Normal file
175
source/blender/pointcache/alembic/abc_mesh.h
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright 2014, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef PTC_ABC_MESH_H
|
||||
#define PTC_ABC_MESH_H
|
||||
|
||||
#include <Alembic/AbcGeom/IPolyMesh.h>
|
||||
#include <Alembic/AbcGeom/OPolyMesh.h>
|
||||
|
||||
#include "ptc_types.h"
|
||||
|
||||
#include "abc_customdata.h"
|
||||
#include "abc_reader.h"
|
||||
#include "abc_schema.h"
|
||||
#include "abc_writer.h"
|
||||
|
||||
extern "C" {
|
||||
#include "DNA_modifier_types.h"
|
||||
|
||||
#include "BKE_DerivedMesh.h"
|
||||
}
|
||||
|
||||
struct Object;
|
||||
struct CacheModifierData;
|
||||
struct DerivedMesh;
|
||||
|
||||
namespace PTC {
|
||||
|
||||
class AbcDerivedMeshWriter : public DerivedMeshWriter, public AbcWriter {
|
||||
public:
|
||||
AbcDerivedMeshWriter(const std::string &name, Object *ob, DerivedMesh **dm_ptr);
|
||||
~AbcDerivedMeshWriter();
|
||||
|
||||
void init_abc(Abc::OObject parent);
|
||||
|
||||
void write_sample();
|
||||
|
||||
private:
|
||||
AbcGeom::OPolyMesh m_mesh;
|
||||
|
||||
/* MVert attributes */
|
||||
AbcGeom::ON3fArrayProperty m_prop_vert_normals;
|
||||
AbcGeom::OCharArrayProperty m_prop_vert_flag;
|
||||
AbcGeom::OCharArrayProperty m_prop_vert_bweight;
|
||||
|
||||
/* MEdge attributes */
|
||||
AbcGeom::OUInt32ArrayProperty m_prop_edge_verts;
|
||||
AbcGeom::OInt16ArrayProperty m_prop_edge_flag;
|
||||
AbcGeom::OCharArrayProperty m_prop_edge_crease;
|
||||
AbcGeom::OCharArrayProperty m_prop_edge_bweight;
|
||||
|
||||
/* MPoly attributes */
|
||||
AbcGeom::OInt16ArrayProperty m_prop_poly_mat_nr;
|
||||
AbcGeom::OCharArrayProperty m_prop_poly_flag;
|
||||
|
||||
/* MLoop attributes */
|
||||
AbcGeom::OInt32ArrayProperty m_prop_loop_verts;
|
||||
AbcGeom::OInt32ArrayProperty m_prop_loop_edges;
|
||||
|
||||
CustomDataWriter m_vert_data_writer;
|
||||
CustomDataWriter m_edge_data_writer;
|
||||
CustomDataWriter m_face_data_writer;
|
||||
CustomDataWriter m_poly_data_writer;
|
||||
CustomDataWriter m_loop_data_writer;
|
||||
};
|
||||
|
||||
class AbcDerivedMeshReader : public DerivedMeshReader, public AbcReader {
|
||||
public:
|
||||
AbcDerivedMeshReader(const std::string &name, Object *ob);
|
||||
~AbcDerivedMeshReader();
|
||||
|
||||
void init_abc(Abc::IObject parent);
|
||||
|
||||
PTCReadSampleResult read_sample(float frame);
|
||||
|
||||
private:
|
||||
AbcGeom::IPolyMesh m_mesh;
|
||||
|
||||
/* MVert attributes */
|
||||
AbcGeom::IN3fArrayProperty m_prop_vert_normals;
|
||||
AbcGeom::ICharArrayProperty m_prop_vert_flag;
|
||||
AbcGeom::ICharArrayProperty m_prop_vert_bweight;
|
||||
|
||||
/* MEdge attributes */
|
||||
AbcGeom::IUInt32ArrayProperty m_prop_edge_verts;
|
||||
AbcGeom::IInt16ArrayProperty m_prop_edge_flag;
|
||||
AbcGeom::ICharArrayProperty m_prop_edge_crease;
|
||||
AbcGeom::ICharArrayProperty m_prop_edge_bweight;
|
||||
|
||||
/* MPoly attributes */
|
||||
AbcGeom::IInt16ArrayProperty m_prop_poly_mat_nr;
|
||||
AbcGeom::ICharArrayProperty m_prop_poly_flag;
|
||||
|
||||
/* MLoop attributes */
|
||||
AbcGeom::IInt32ArrayProperty m_prop_loop_verts;
|
||||
AbcGeom::IInt32ArrayProperty m_prop_loop_edges;
|
||||
|
||||
CustomDataReader m_vert_data_reader;
|
||||
CustomDataReader m_edge_data_reader;
|
||||
CustomDataReader m_face_data_reader;
|
||||
CustomDataReader m_poly_data_reader;
|
||||
CustomDataReader m_loop_data_reader;
|
||||
};
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Writing derived mesh results requires different variants
|
||||
* depending on viewport/render output and whether a cache modifier is used.
|
||||
*
|
||||
* Render DMs are constructed on-the-fly for each sample write, since they
|
||||
* are not constructed immediately during scene frame updates. The writer is
|
||||
* expected to only be called once per frame and object.
|
||||
*
|
||||
* If a cache modifier is used it must be have be activate at the time when
|
||||
* the DM is built. For viewport output this means it should activate the
|
||||
* modifier during it's whole lifetime, so that it caches meshes during the
|
||||
* scene frame update. For render output the modifier should only be active
|
||||
* during the render DM construction.
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
class AbcDerivedFinalRealtimeWriter : public AbcDerivedMeshWriter {
|
||||
public:
|
||||
AbcDerivedFinalRealtimeWriter(const std::string &name, Object *ob);
|
||||
};
|
||||
|
||||
|
||||
class AbcCacheModifierRealtimeWriter : public AbcDerivedMeshWriter {
|
||||
public:
|
||||
AbcCacheModifierRealtimeWriter(const std::string &name, Object *ob, CacheModifierData *cmd);
|
||||
~AbcCacheModifierRealtimeWriter();
|
||||
|
||||
private:
|
||||
CacheModifierData *m_cmd;
|
||||
};
|
||||
|
||||
|
||||
class AbcDerivedFinalRenderWriter : public AbcDerivedMeshWriter {
|
||||
public:
|
||||
AbcDerivedFinalRenderWriter(const std::string &name, Scene *scene, Object *ob, DerivedMesh **render_dm_ptr);
|
||||
|
||||
private:
|
||||
Scene *m_scene;
|
||||
};
|
||||
|
||||
|
||||
class AbcCacheModifierRenderWriter : public AbcDerivedMeshWriter {
|
||||
public:
|
||||
AbcCacheModifierRenderWriter(const std::string &name, Scene *scene, Object *ob, CacheModifierData *cmd);
|
||||
~AbcCacheModifierRenderWriter();
|
||||
|
||||
private:
|
||||
Scene *m_scene;
|
||||
CacheModifierData *m_cmd;
|
||||
};
|
||||
|
||||
|
||||
} /* namespace PTC */
|
||||
|
||||
#endif /* PTC_MESH_H */
|
122
source/blender/pointcache/alembic/abc_object.cpp
Normal file
122
source/blender/pointcache/alembic/abc_object.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2013, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "abc_object.h"
|
||||
|
||||
extern "C" {
|
||||
#include "BLI_math.h"
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BKE_object.h"
|
||||
}
|
||||
|
||||
namespace PTC {
|
||||
|
||||
using namespace Abc;
|
||||
using namespace AbcGeom;
|
||||
|
||||
AbcObjectWriter::AbcObjectWriter(const std::string &name, Scene *scene, Object *ob, bool do_mesh, bool do_hair) :
|
||||
ObjectWriter(ob, name),
|
||||
m_scene(scene),
|
||||
m_final_dm(NULL),
|
||||
m_dm_writer("mesh", ob, &m_final_dm),
|
||||
m_do_mesh(do_mesh),
|
||||
m_do_hair(do_hair)
|
||||
{
|
||||
m_do_mesh &= m_ob->type == OB_MESH;
|
||||
}
|
||||
|
||||
void AbcObjectWriter::init_abc()
|
||||
{
|
||||
if (m_abc_object)
|
||||
return;
|
||||
|
||||
m_abc_object = abc_archive()->add_id_object<OObject>((ID *)m_ob);
|
||||
|
||||
if (m_do_mesh) {
|
||||
/* XXX not nice */
|
||||
m_dm_writer.init(abc_archive());
|
||||
m_dm_writer.init_abc(m_abc_object);
|
||||
}
|
||||
|
||||
if (m_do_hair) {
|
||||
/* TODO */
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void AbcObjectWriter::create_refs()
|
||||
{
|
||||
if ((m_ob->transflag & OB_DUPLIGROUP) && m_ob->dup_group) {
|
||||
OObject abc_group = abc_archive()->get_id_object((ID *)m_ob->dup_group);
|
||||
if (abc_group)
|
||||
m_abc_object.addChildInstance(abc_group, "dup_group");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void AbcObjectWriter::write_sample()
|
||||
{
|
||||
if (!m_abc_object)
|
||||
return;
|
||||
|
||||
if (m_do_mesh) {
|
||||
if (abc_archive()->use_render()) {
|
||||
m_final_dm = mesh_create_derived_render(m_scene, m_ob, CD_MASK_BAREMESH);
|
||||
|
||||
if (m_final_dm) {
|
||||
m_dm_writer.write_sample();
|
||||
|
||||
m_final_dm->release(m_final_dm);
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_final_dm = m_ob->derivedFinal;
|
||||
if (!m_final_dm)
|
||||
m_final_dm = mesh_get_derived_final(m_scene, m_ob, CD_MASK_BAREMESH);
|
||||
|
||||
if (m_final_dm) {
|
||||
m_dm_writer.write_sample();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AbcObjectReader::AbcObjectReader(const std::string &name, Object *ob) :
|
||||
ObjectReader(ob, name)
|
||||
{
|
||||
}
|
||||
|
||||
void AbcObjectReader::init_abc()
|
||||
{
|
||||
if (m_abc_object)
|
||||
return;
|
||||
m_abc_object = abc_archive()->get_id_object((ID *)m_ob);
|
||||
}
|
||||
|
||||
PTCReadSampleResult AbcObjectReader::read_sample(float frame)
|
||||
{
|
||||
if (!m_abc_object)
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
|
||||
return PTC_READ_SAMPLE_EXACT;
|
||||
}
|
||||
|
||||
} /* namespace PTC */
|
75
source/blender/pointcache/alembic/abc_object.h
Normal file
75
source/blender/pointcache/alembic/abc_object.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2013, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef PTC_ABC_OBJECT_H
|
||||
#define PTC_ABC_OBJECT_H
|
||||
|
||||
#include <Alembic/Abc/IObject.h>
|
||||
#include <Alembic/Abc/OObject.h>
|
||||
#include <Alembic/AbcGeom/IXform.h>
|
||||
#include <Alembic/AbcGeom/OXform.h>
|
||||
|
||||
#include "ptc_types.h"
|
||||
|
||||
#include "abc_reader.h"
|
||||
#include "abc_schema.h"
|
||||
#include "abc_writer.h"
|
||||
#include "abc_mesh.h"
|
||||
|
||||
struct DerivedMesh;
|
||||
struct Object;
|
||||
struct Scene;
|
||||
|
||||
namespace PTC {
|
||||
|
||||
class AbcObjectWriter : public ObjectWriter, public AbcWriter {
|
||||
public:
|
||||
AbcObjectWriter(const std::string &name, Scene *scene, Object *ob, bool do_mesh, bool do_hair);
|
||||
|
||||
void init_abc();
|
||||
#if 0
|
||||
void create_refs();
|
||||
#endif
|
||||
|
||||
void write_sample();
|
||||
|
||||
private:
|
||||
Scene *m_scene;
|
||||
DerivedMesh *m_final_dm;
|
||||
|
||||
Abc::OObject m_abc_object;
|
||||
AbcDerivedMeshWriter m_dm_writer;
|
||||
|
||||
bool m_do_mesh, m_do_hair;
|
||||
};
|
||||
|
||||
class AbcObjectReader : public ObjectReader, public AbcReader {
|
||||
public:
|
||||
AbcObjectReader(const std::string &name, Object *ob);
|
||||
|
||||
void init_abc();
|
||||
|
||||
PTCReadSampleResult read_sample(float frame);
|
||||
|
||||
private:
|
||||
Abc::IObject m_abc_object;
|
||||
};
|
||||
|
||||
} /* namespace PTC */
|
||||
|
||||
#endif /* PTC_OBJECT_H */
|
499
source/blender/pointcache/alembic/abc_particles.cpp
Normal file
499
source/blender/pointcache/alembic/abc_particles.cpp
Normal file
@@ -0,0 +1,499 @@
|
||||
/*
|
||||
* Copyright 2013, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "abc_cloth.h"
|
||||
#include "abc_mesh.h"
|
||||
#include "abc_particles.h"
|
||||
|
||||
extern "C" {
|
||||
#include "BLI_math.h"
|
||||
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_particle_types.h"
|
||||
|
||||
#include "BKE_particle.h"
|
||||
}
|
||||
|
||||
namespace PTC {
|
||||
|
||||
using namespace Abc;
|
||||
using namespace AbcGeom;
|
||||
|
||||
AbcParticlesWriter::AbcParticlesWriter(const std::string &name, Object *ob, ParticleSystem *psys) :
|
||||
ParticlesWriter(ob, psys, name)
|
||||
{
|
||||
}
|
||||
|
||||
AbcParticlesWriter::~AbcParticlesWriter()
|
||||
{
|
||||
}
|
||||
|
||||
void AbcParticlesWriter::init_abc(OObject parent)
|
||||
{
|
||||
if (m_points)
|
||||
return;
|
||||
m_points = OPoints(parent, m_name, abc_archive()->frame_sampling_index());
|
||||
}
|
||||
|
||||
void AbcParticlesWriter::write_sample()
|
||||
{
|
||||
if (!m_points)
|
||||
return;
|
||||
|
||||
OPointsSchema &schema = m_points.getSchema();
|
||||
|
||||
int totpart = m_psys->totpart;
|
||||
ParticleData *pa;
|
||||
int i;
|
||||
|
||||
/* XXX TODO only needed for the first frame/sample */
|
||||
std::vector<Util::uint64_t> ids;
|
||||
ids.reserve(totpart);
|
||||
for (i = 0, pa = m_psys->particles; i < totpart; ++i, ++pa)
|
||||
ids.push_back(i);
|
||||
|
||||
std::vector<V3f> positions;
|
||||
positions.reserve(totpart);
|
||||
for (i = 0, pa = m_psys->particles; i < totpart; ++i, ++pa) {
|
||||
float *co = pa->state.co;
|
||||
positions.push_back(V3f(co[0], co[1], co[2]));
|
||||
}
|
||||
|
||||
OPointsSchema::Sample sample = OPointsSchema::Sample(V3fArraySample(positions), UInt64ArraySample(ids));
|
||||
|
||||
schema.set(sample);
|
||||
}
|
||||
|
||||
|
||||
AbcParticlesReader::AbcParticlesReader(const std::string &name, Object *ob, ParticleSystem *psys) :
|
||||
ParticlesReader(ob, psys, name)
|
||||
{
|
||||
}
|
||||
|
||||
AbcParticlesReader::~AbcParticlesReader()
|
||||
{
|
||||
}
|
||||
|
||||
void AbcParticlesReader::init_abc(IObject parent)
|
||||
{
|
||||
if (m_points)
|
||||
return;
|
||||
|
||||
if (parent.getChild(m_name)) {
|
||||
m_points = IPoints(parent, m_name);
|
||||
}
|
||||
|
||||
/* XXX TODO read first sample for info on particle count and times */
|
||||
m_totpoint = 0;
|
||||
}
|
||||
|
||||
PTCReadSampleResult AbcParticlesReader::read_sample(float frame)
|
||||
{
|
||||
ISampleSelector ss = abc_archive()->get_frame_sample_selector(frame);
|
||||
|
||||
if (!m_points.valid())
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
|
||||
IPointsSchema &schema = m_points.getSchema();
|
||||
|
||||
IPointsSchema::Sample sample;
|
||||
schema.get(sample, ss);
|
||||
|
||||
const V3f *positions = sample.getPositions()->get();
|
||||
int /*totpart = m_psys->totpart,*/ i;
|
||||
ParticleData *pa;
|
||||
for (i = 0, pa = m_psys->particles; i < sample.getPositions()->size(); ++i, ++pa) {
|
||||
pa->state.co[0] = positions[i].x;
|
||||
pa->state.co[1] = positions[i].y;
|
||||
pa->state.co[2] = positions[i].z;
|
||||
}
|
||||
|
||||
return PTC_READ_SAMPLE_EXACT;
|
||||
}
|
||||
|
||||
|
||||
AbcHairDynamicsWriter::AbcHairDynamicsWriter(const std::string &name, Object *ob, ParticleSystem *psys) :
|
||||
ParticlesWriter(ob, psys, name),
|
||||
m_cloth_writer(name+"__cloth", ob, psys->clmd)
|
||||
{
|
||||
}
|
||||
|
||||
void AbcHairDynamicsWriter::init_abc(OObject parent)
|
||||
{
|
||||
m_cloth_writer.init_abc(parent);
|
||||
}
|
||||
|
||||
void AbcHairDynamicsWriter::write_sample()
|
||||
{
|
||||
m_cloth_writer.write_sample();
|
||||
}
|
||||
|
||||
AbcHairDynamicsReader::AbcHairDynamicsReader(const std::string &name, Object *ob, ParticleSystem *psys) :
|
||||
ParticlesReader(ob, psys, name),
|
||||
m_cloth_reader(name+"__cloth", ob, psys->clmd)
|
||||
{
|
||||
}
|
||||
|
||||
void AbcHairDynamicsReader::init_abc(IObject parent)
|
||||
{
|
||||
m_cloth_reader.init_abc(parent);
|
||||
}
|
||||
|
||||
PTCReadSampleResult AbcHairDynamicsReader::read_sample(float frame)
|
||||
{
|
||||
return m_cloth_reader.read_sample(frame);
|
||||
}
|
||||
|
||||
|
||||
AbcParticlePathcacheWriter::AbcParticlePathcacheWriter(const std::string &name, Object *ob, ParticleSystem *psys, ParticleCacheKey ***pathcache, int *totpath, const std::string &suffix) :
|
||||
ParticlesWriter(ob, psys, name),
|
||||
m_pathcache(pathcache),
|
||||
m_totpath(totpath),
|
||||
m_suffix(suffix)
|
||||
{
|
||||
}
|
||||
|
||||
AbcParticlePathcacheWriter::~AbcParticlePathcacheWriter()
|
||||
{
|
||||
}
|
||||
|
||||
void AbcParticlePathcacheWriter::init_abc(OObject parent)
|
||||
{
|
||||
if (m_curves)
|
||||
return;
|
||||
|
||||
/* XXX non-escaped string construction here ... */
|
||||
m_curves = OCurves(parent, m_name + m_suffix, abc_archive()->frame_sampling_index());
|
||||
|
||||
OCurvesSchema &schema = m_curves.getSchema();
|
||||
OCompoundProperty geom_props = schema.getArbGeomParams();
|
||||
|
||||
m_param_velocities = OV3fGeomParam(geom_props, "velocities", false, kVertexScope, 1, 0);
|
||||
m_param_rotations = OQuatfGeomParam(geom_props, "rotations", false, kVertexScope, 1, 0);
|
||||
m_param_colors = OV3fGeomParam(geom_props, "colors", false, kVertexScope, 1, 0);
|
||||
m_param_times = OFloatGeomParam(geom_props, "times", false, kVertexScope, 1, 0);
|
||||
}
|
||||
|
||||
static int paths_count_totkeys(ParticleCacheKey **pathcache, int totpart)
|
||||
{
|
||||
int p;
|
||||
int totkeys = 0;
|
||||
|
||||
for (p = 0; p < totpart; ++p) {
|
||||
ParticleCacheKey *keys = pathcache[p];
|
||||
totkeys += keys->segments + 1;
|
||||
}
|
||||
|
||||
return totkeys;
|
||||
}
|
||||
|
||||
static Int32ArraySample paths_create_sample_nvertices(ParticleCacheKey **pathcache, int totpart, std::vector<int32_t> &data)
|
||||
{
|
||||
int p;
|
||||
|
||||
data.reserve(totpart);
|
||||
|
||||
for (p = 0; p < totpart; ++p) {
|
||||
ParticleCacheKey *keys = pathcache[p];
|
||||
|
||||
data.push_back(keys->segments + 1);
|
||||
}
|
||||
|
||||
return Int32ArraySample(data);
|
||||
}
|
||||
|
||||
static P3fArraySample paths_create_sample_positions(ParticleCacheKey **pathcache, int totpart, int totkeys, std::vector<V3f> &data)
|
||||
{
|
||||
int p, k;
|
||||
|
||||
data.reserve(totkeys);
|
||||
|
||||
for (p = 0; p < totpart; ++p) {
|
||||
ParticleCacheKey *keys = pathcache[p];
|
||||
int numkeys = keys->segments + 1;
|
||||
|
||||
for (k = 0; k < numkeys; ++k) {
|
||||
float *co = keys[k].co;
|
||||
data.push_back(V3f(co[0], co[1], co[2]));
|
||||
}
|
||||
}
|
||||
|
||||
return P3fArraySample(data);
|
||||
}
|
||||
|
||||
static OV3fGeomParam::Sample paths_create_sample_velocities(ParticleCacheKey **pathcache, int totpart, int totkeys, std::vector<V3f> &data)
|
||||
{
|
||||
int p, k;
|
||||
|
||||
data.reserve(totkeys);
|
||||
|
||||
for (p = 0; p < totpart; ++p) {
|
||||
ParticleCacheKey *keys = pathcache[p];
|
||||
int numkeys = keys->segments + 1;
|
||||
|
||||
for (k = 0; k < numkeys; ++k) {
|
||||
float *vel = keys[k].vel;
|
||||
data.push_back(V3f(vel[0], vel[1], vel[2]));
|
||||
}
|
||||
}
|
||||
|
||||
OV3fGeomParam::Sample sample;
|
||||
sample.setVals(V3fArraySample(data));
|
||||
sample.setScope(kVertexScope);
|
||||
return sample;
|
||||
}
|
||||
|
||||
static OQuatfGeomParam::Sample paths_create_sample_rotations(ParticleCacheKey **pathcache, int totpart, int totkeys, std::vector<Quatf> &data)
|
||||
{
|
||||
int p, k;
|
||||
|
||||
data.reserve(totkeys);
|
||||
|
||||
for (p = 0; p < totpart; ++p) {
|
||||
ParticleCacheKey *keys = pathcache[p];
|
||||
int numkeys = keys->segments + 1;
|
||||
|
||||
for (k = 0; k < numkeys; ++k) {
|
||||
float *rot = keys[k].rot;
|
||||
data.push_back(Quatf(rot[0], rot[1], rot[2], rot[3]));
|
||||
}
|
||||
}
|
||||
|
||||
OQuatfGeomParam::Sample sample;
|
||||
sample.setVals(QuatfArraySample(data));
|
||||
sample.setScope(kVertexScope);
|
||||
return sample;
|
||||
}
|
||||
|
||||
static OV3fGeomParam::Sample paths_create_sample_colors(ParticleCacheKey **pathcache, int totpart, int totkeys, std::vector<V3f> &data)
|
||||
{
|
||||
int p, k;
|
||||
|
||||
data.reserve(totkeys);
|
||||
|
||||
for (p = 0; p < totpart; ++p) {
|
||||
ParticleCacheKey *keys = pathcache[p];
|
||||
int numkeys = keys->segments + 1;
|
||||
|
||||
for (k = 0; k < numkeys; ++k) {
|
||||
float *col = keys[k].col;
|
||||
data.push_back(V3f(col[0], col[1], col[2]));
|
||||
}
|
||||
}
|
||||
|
||||
OV3fGeomParam::Sample sample;
|
||||
sample.setVals(V3fArraySample(data));
|
||||
sample.setScope(kVertexScope);
|
||||
return sample;
|
||||
}
|
||||
|
||||
static OFloatGeomParam::Sample paths_create_sample_times(ParticleCacheKey **pathcache, int totpart, int totkeys, std::vector<float32_t> &data)
|
||||
{
|
||||
int p, k;
|
||||
|
||||
data.reserve(totkeys);
|
||||
|
||||
for (p = 0; p < totpart; ++p) {
|
||||
ParticleCacheKey *keys = pathcache[p];
|
||||
int numkeys = keys->segments + 1;
|
||||
|
||||
for (k = 0; k < numkeys; ++k) {
|
||||
data.push_back(keys[k].time);
|
||||
}
|
||||
}
|
||||
|
||||
OFloatGeomParam::Sample sample;
|
||||
sample.setVals(FloatArraySample(data));
|
||||
sample.setScope(kVertexScope);
|
||||
return sample;
|
||||
}
|
||||
|
||||
void AbcParticlePathcacheWriter::write_sample()
|
||||
{
|
||||
if (!m_curves)
|
||||
return;
|
||||
if (!(*m_pathcache))
|
||||
return;
|
||||
|
||||
int totkeys = paths_count_totkeys(*m_pathcache, *m_totpath);
|
||||
if (totkeys == 0)
|
||||
return;
|
||||
|
||||
OCurvesSchema &schema = m_curves.getSchema();
|
||||
|
||||
std::vector<V3f> positions_buffer;
|
||||
std::vector<V3f> velocities_buffer;
|
||||
std::vector<Quatf> rotations_buffer;
|
||||
std::vector<V3f> colors_buffer;
|
||||
std::vector<float32_t> times_buffer;
|
||||
V3fArraySample positions = paths_create_sample_positions(*m_pathcache, *m_totpath, totkeys, positions_buffer);
|
||||
OV3fGeomParam::Sample velocities = paths_create_sample_velocities(*m_pathcache, *m_totpath, totkeys, velocities_buffer);
|
||||
OQuatfGeomParam::Sample rotations = paths_create_sample_rotations(*m_pathcache, *m_totpath, totkeys, rotations_buffer);
|
||||
OV3fGeomParam::Sample colors = paths_create_sample_colors(*m_pathcache, *m_totpath, totkeys, colors_buffer);
|
||||
OFloatGeomParam::Sample times = paths_create_sample_times(*m_pathcache, *m_totpath, totkeys, times_buffer);
|
||||
|
||||
OCurvesSchema::Sample sample;
|
||||
if (schema.getNumSamples() == 0) {
|
||||
/* write curve sizes only first time, assuming they are constant! */
|
||||
std::vector<int32_t> nvertices_buffer;
|
||||
Int32ArraySample nvertices = paths_create_sample_nvertices(*m_pathcache, *m_totpath, nvertices_buffer);
|
||||
|
||||
sample = OCurvesSchema::Sample(positions, nvertices);
|
||||
}
|
||||
else {
|
||||
sample = OCurvesSchema::Sample(positions);
|
||||
}
|
||||
|
||||
schema.set(sample);
|
||||
|
||||
m_param_velocities.set(velocities);
|
||||
m_param_rotations.set(rotations);
|
||||
m_param_colors.set(colors);
|
||||
m_param_times.set(times);
|
||||
}
|
||||
|
||||
|
||||
AbcParticlePathcacheReader::AbcParticlePathcacheReader(const std::string &name, Object *ob, ParticleSystem *psys, ParticleCacheKey ***pathcache, int *totpath, const std::string &suffix) :
|
||||
ParticlesReader(ob, psys, name),
|
||||
m_pathcache(pathcache),
|
||||
m_totpath(totpath),
|
||||
m_suffix(suffix)
|
||||
{
|
||||
}
|
||||
|
||||
void AbcParticlePathcacheReader::init_abc(IObject parent)
|
||||
{
|
||||
if (m_curves)
|
||||
return;
|
||||
|
||||
/* XXX non-escaped string construction here ... */
|
||||
std::string curves_name = m_name + m_suffix;
|
||||
if (parent.getChild(curves_name)) {
|
||||
m_curves = ICurves(parent, curves_name);
|
||||
ICurvesSchema &schema = m_curves.getSchema();
|
||||
ICompoundProperty geom_props = schema.getArbGeomParams();
|
||||
|
||||
m_param_velocities = IV3fGeomParam(geom_props, "velocities", 0);
|
||||
m_param_rotations = IQuatfGeomParam(geom_props, "rotations", 0);
|
||||
m_param_colors = IV3fGeomParam(geom_props, "colors", 0);
|
||||
m_param_times = IFloatGeomParam(geom_props, "times", 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void paths_apply_sample_nvertices(ParticleCacheKey **pathcache, int totpart, Int32ArraySamplePtr sample)
|
||||
{
|
||||
int p, k;
|
||||
|
||||
BLI_assert(sample->size() == totpart);
|
||||
|
||||
const int32_t *data = sample->get();
|
||||
|
||||
for (p = 0; p < totpart; ++p) {
|
||||
ParticleCacheKey *keys = pathcache[p];
|
||||
int num_keys = data[p];
|
||||
int segments = num_keys - 1;
|
||||
|
||||
for (k = 0; k < num_keys; ++k) {
|
||||
keys[k].segments = segments;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Warning: apply_sample_nvertices has to be called before this! */
|
||||
static void paths_apply_sample_data(ParticleCacheKey **pathcache, int totpart,
|
||||
P3fArraySamplePtr sample_pos,
|
||||
V3fArraySamplePtr sample_vel,
|
||||
QuatfArraySamplePtr sample_rot,
|
||||
V3fArraySamplePtr sample_col,
|
||||
FloatArraySamplePtr sample_time)
|
||||
{
|
||||
int p, k;
|
||||
|
||||
// BLI_assert(sample->size() == totvert);
|
||||
|
||||
const V3f *data_pos = sample_pos->get();
|
||||
const V3f *data_vel = sample_vel->get();
|
||||
const Quatf *data_rot = sample_rot->get();
|
||||
const V3f *data_col = sample_col->get();
|
||||
const float32_t *data_time = sample_time->get();
|
||||
ParticleCacheKey **pkeys = pathcache;
|
||||
|
||||
for (p = 0; p < totpart; ++p) {
|
||||
ParticleCacheKey *key = *pkeys;
|
||||
int num_keys = key->segments + 1;
|
||||
|
||||
for (k = 0; k < num_keys; ++k) {
|
||||
copy_v3_v3(key->co, data_pos->getValue());
|
||||
copy_v3_v3(key->vel, data_vel->getValue());
|
||||
key->rot[0] = (*data_rot)[0];
|
||||
key->rot[1] = (*data_rot)[1];
|
||||
key->rot[2] = (*data_rot)[2];
|
||||
key->rot[3] = (*data_rot)[3];
|
||||
copy_v3_v3(key->col, data_col->getValue());
|
||||
key->time = *data_time;
|
||||
|
||||
++key;
|
||||
++data_pos;
|
||||
++data_vel;
|
||||
++data_rot;
|
||||
++data_col;
|
||||
++data_time;
|
||||
}
|
||||
|
||||
++pkeys;
|
||||
}
|
||||
}
|
||||
|
||||
PTCReadSampleResult AbcParticlePathcacheReader::read_sample(float frame)
|
||||
{
|
||||
if (!(*m_pathcache))
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
|
||||
if (!m_curves)
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
|
||||
ISampleSelector ss = abc_archive()->get_frame_sample_selector(frame);
|
||||
|
||||
ICurvesSchema &schema = m_curves.getSchema();
|
||||
if (!schema.valid() || schema.getPositionsProperty().getNumSamples() == 0)
|
||||
return PTC_READ_SAMPLE_INVALID;
|
||||
|
||||
ICurvesSchema::Sample sample;
|
||||
schema.get(sample, ss);
|
||||
|
||||
P3fArraySamplePtr positions = sample.getPositions();
|
||||
Int32ArraySamplePtr nvertices = sample.getCurvesNumVertices();
|
||||
IV3fGeomParam::Sample sample_vel = m_param_velocities.getExpandedValue(ss);
|
||||
IQuatfGeomParam::Sample sample_rot = m_param_rotations.getExpandedValue(ss);
|
||||
IV3fGeomParam::Sample sample_col = m_param_colors.getExpandedValue(ss);
|
||||
IFloatGeomParam::Sample sample_time = m_param_times.getExpandedValue(ss);
|
||||
|
||||
// int totkeys = positions->size();
|
||||
|
||||
if (nvertices->valid()) {
|
||||
BLI_assert(nvertices->size() == *m_totpath);
|
||||
paths_apply_sample_nvertices(*m_pathcache, *m_totpath, nvertices);
|
||||
}
|
||||
|
||||
paths_apply_sample_data(*m_pathcache, *m_totpath, positions, sample_vel.getVals(), sample_rot.getVals(), sample_col.getVals(), sample_time.getVals());
|
||||
|
||||
return PTC_READ_SAMPLE_EXACT;
|
||||
}
|
||||
|
||||
} /* namespace PTC */
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user