Merged changes in the trunk up to revision 53280.

This commit is contained in:
Tamito Kajiyama 2012-12-23 00:23:11 +00:00
commit 40449b1994
254 changed files with 20966 additions and 42617 deletions

@ -1787,33 +1787,57 @@ print_info() {
INFO ""
INFO "If you're using CMake add this to your configuration flags:"
_buildargs=""
if $ALL_STATIC; then
INFO " -D WITH_STATIC_LIBS=ON"
_1="-D WITH_STATIC_LIBS=ON"
INFO " $_1"
_buildargs="$_buildargs $_1"
fi
if [ -d $INST/boost ]; then
INFO " -D BOOST_ROOT=$INST/boost"
INFO " -D Boost_NO_SYSTEM_PATHS=ON"
_1="-D BOOST_ROOT=$INST/boost"
_2="-D Boost_NO_SYSTEM_PATHS=ON"
INFO " $_1"
INFO " $_2"
_buildargs="$_buildargs $_1 $_2"
elif $ALL_STATIC; then
INFO " -D Boost_USE_ICU=ON"
_1="-D Boost_USE_ICU=ON"
INFO " $_1"
_buildargs="$_buildargs $_1"
fi
if [ -d $INST/osl -a $WITH_OSL == true ]; then
INFO " -D CYCLES_OSL=$INST/osl"
INFO " -D WITH_CYCLES_OSL=ON"
INFO " -D LLVM_VERSION=$LLVM_VERSION_FOUND"
_1="-D CYCLES_OSL=$INST/osl"
_2="-D WITH_CYCLES_OSL=ON"
_3="-D LLVM_VERSION=$LLVM_VERSION_FOUND"
INFO " $_1"
INFO " $_2"
INFO " $_3"
_buildargs="$_buildargs $_1 $_2 $_3"
if [ -d $INST/llvm ]; then
INFO " -D LLVM_DIRECTORY=$INST/llvm"
INFO " -D LLVM_STATIC=ON"
_1="-D LLVM_DIRECTORY=$INST/llvm"
_2="-D LLVM_STATIC=ON"
INFO " $_1"
INFO " $_2"
_buildargs="$_buildargs $_1 $_2"
fi
fi
if [ -d $INST/ffmpeg ]; then
INFO " -D WITH_CODEC_FFMPEG=ON"
INFO " -D FFMPEG=$INST/ffmpeg"
INFO " -D FFMPEG_LIBRARIES='avformat;avcodec;avutil;avdevice;swscale;rt;`print_info_ffmpeglink`'"
_1="-D WITH_CODEC_FFMPEG=ON"
_2="-D FFMPEG=$INST/ffmpeg"
_3="-D FFMPEG_LIBRARIES='avformat;avcodec;avutil;avdevice;swscale;rt;`print_info_ffmpeglink`'"
INFO " $_1"
INFO " $_2"
INFO " $_3"
_buildargs="$_buildargs $_1 $_2 $_3"
fi
INFO ""
INFO "Or even simpler, just run (in your build dir):"
INFO " make -j$THREADS BUILD_CMAKE_ARGS=\"$_buildargs\""
INFO ""
INFO "If you're using SCons add this to your user-config:"
@ -1832,6 +1856,7 @@ print_info() {
if [ -d $INST/boost ]; then
INFO "BF_BOOST = '$INST/boost'"
INFO "WITH_BF_BOOST = True"
fi
if [ -d $INST/ffmpeg ]; then

@ -103,7 +103,7 @@ WITH_BF_FFTW3 = True
WITH_BF_STATICFFTW3 = True
# JACK
WITH_BF_JACK = True
WITH_BF_JACK = False
WITH_BF_STATICJACK = True
BF_JACK_LIB_STATIC = '${BF_ZLIB}/lib/libjack.a'

@ -103,7 +103,7 @@ WITH_BF_FFTW3 = True
WITH_BF_STATICFFTW3 = True
# JACK
WITH_BF_JACK = True
WITH_BF_JACK = False
WITH_BF_STATICJACK = True
BF_JACK_LIB_STATIC = '${BF_ZLIB}/lib/libjack.a'

@ -92,7 +92,7 @@ WITH_BF_FFTW3 = True
WITH_BF_STATICFFTW3 = True
# JACK
WITH_BF_JACK = True
WITH_BF_JACK = False
# Cycles
WITH_BF_CYCLES = True

@ -92,7 +92,7 @@ WITH_BF_FFTW3 = True
WITH_BF_STATICFFTW3 = True
# JACK
WITH_BF_JACK = True
WITH_BF_JACK = False
# Cycles
WITH_BF_CYCLES = True

@ -103,7 +103,7 @@ BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBP
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
# JACK
WITH_BF_JACK = True
WITH_BF_JACK = False
WITH_BF_STATICJACK = True
BF_JACK_LIB_STATIC = '${BF_ZLIB}/lib/libjack.a'

@ -103,7 +103,7 @@ BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBP
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
# JACK
WITH_BF_JACK = True
WITH_BF_JACK = False
WITH_BF_STATICJACK = True
BF_JACK_LIB_STATIC = '${BF_ZLIB}/lib/libjack.a'

@ -98,7 +98,7 @@ BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBP
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
# JACK
WITH_BF_JACK = True
WITH_BF_JACK = False
# Motion Tracking
WITH_BF_LIBMV = False

@ -98,7 +98,7 @@ BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBP
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
# JACK
WITH_BF_JACK = True
WITH_BF_JACK = False
# Motion Tracking
WITH_BF_LIBMV = False

@ -47,10 +47,10 @@ def get_version():
if (ver_base is not None) and (ver_char is not None) and (ver_cycle is not None):
# eg '2.56a-beta'
if ver_cycle:
if ver_cycle != "release":
ver_display = "%s%s-%s" % (ver_base, ver_char, ver_cycle)
else:
ver_display = "%s%s" % (ver_base, ver_char) # assume release
ver_display = "%s%s" % (ver_base, ver_char)
return ver_base, ver_display, ver_cycle

@ -125,6 +125,10 @@ Variables
The current mouse wrapped in an :class:`~bge.types.SCA_PythonMouse` object.
.. data:: joysticks
A list of attached joysticks. The list size it he maximum number of supported joysticks. If no joystick is available for a given slot, the slot is set to None.
*****************
General functions
*****************
@ -172,7 +176,7 @@ General functions
Restarts the current game by reloading the .blend file (the last saved version, not what is currently running).
.. function:: LibLoad(blend, type, data, load_actions=False, verbose=False, load_scripts=True)
.. function:: LibLoad(blend, type, data, load_actions=False, verbose=False, load_scripts=True, async=False)
Converts the all of the datablocks of the given type from the given blend.
@ -187,7 +191,13 @@ General functions
:arg verbose: Whether or not to print debugging information (e.g., "SceneName: Scene")
:type verbose: bool
:arg load_scripts: Whether or not to load text datablocks as well (can be disabled for some extra security)
:type load_scripts: bool
:type load_scripts: bool
:arg async: Whether or not to do the loading asynchronously (in another thread). Only the "Scene" type is currently supported for this feature.
:type async: bool
:rtype: :class:`bge.types.KX_LibLoadStatus`
.. note:: Asynchronously loaded libraries will not be available immediately after LibLoad() returns. Use the returned KX_LibLoadStatus to figure out when the libraries are ready.
.. function:: LibNew(name, type, data)

@ -141,6 +141,74 @@ Types
:type: boolean
.. class:: SCA_PythonJoystick(PyObjectPlus)
A Python interface to a joystick.
.. attribute:: name
The name assigned to the joystick by the operating system. (read-only)
:type: string
.. attribute:: activeButtons
A list of active button values. (read-only)
:type: list
.. attribute:: axisValues
The state of the joysticks axis as a list of values :data:`numAxis` long. (read-only).
:type: list of ints.
Each specifying the value of an axis between -1.0 and 1.0 depending on how far the axis is pushed, 0 for nothing.
The first 2 values are used by most joysticks and gamepads for directional control. 3rd and 4th values are only on some joysticks and can be used for arbitary controls.
* left:[-1.0, 0.0, ...]
* right:[1.0, 0.0, ...]
* up:[0.0, -1.0, ...]
* down:[0.0, 1.0, ...]
.. attribute:: hatValues
The state of the joysticks hats as a list of values :data:`numHats` long. (read-only).
:type: list of ints
Each specifying the direction of the hat from 1 to 12, 0 when inactive.
Hat directions are as follows...
* 0:None
* 1:Up
* 2:Right
* 4:Down
* 8:Left
* 3:Up - Right
* 6:Down - Right
* 12:Down - Left
* 9:Up - Left
.. attribute:: numAxis
The number of axes for the joystick at this index. (read-only).
:type: integer
.. attribute:: numButtons
The number of buttons for the joystick at this index. (read-only).
:type: integer
.. attribute:: numHats
The number of hats for the joystick at this index. (read-only).
:type: integer
.. class:: SCA_IObject(CValue)
This class has no python functions
@ -1861,6 +1929,44 @@ Types
:type: boolean
.. class:: KX_LibLoadStatus(PyObjectPlus)
An object providing information about a LibLoad() operation.
.. code-block:: python
# Print a message when an async LibLoad is done
import bge
def finished_cb(status):
print("Library (%s) loaded in %.2fms." % (status.libraryName, status.timeTaken))
bge.logic.LibLoad('myblend.blend', 'Scene', async=True).onFinish = finished_cb
.. attribute:: onFinish
A callback that gets called when the lib load is done.
:type: callable
.. attribute:: progress
The current progress of the lib load as a normalized value from 0.0 to 1.0.
:type: float
.. attribute:: libraryName
The name of the library being loaded (the first argument to LibLoad).
:type: string
.. attribute:: timeTaken
The amount of time, in seconds, the lib load took (0 until the operation is complete).
:type: float
.. class:: KX_LightObject(KX_GameObject)
A Light object.
@ -3977,7 +4083,7 @@ Types
:type: list of ints.
Each spesifying the value of an axis between -32767 and 32767 depending on how far the axis is pushed, 0 for nothing.
Each specifying the value of an axis between -32767 and 32767 depending on how far the axis is pushed, 0 for nothing.
The first 2 values are used by most joysticks and gamepads for directional control. 3rd and 4th values are only on some joysticks and can be used for arbitary controls.
* left:[-32767, 0, ...]
@ -4001,7 +4107,7 @@ Types
:type: list of ints
Each spesifying the direction of the hat from 1 to 12, 0 when inactive.
Each specifying the direction of the hat from 1 to 12, 0 when inactive.
Hat directions are as follows...

@ -47,9 +47,9 @@ set(SRC
libmv/multiview/conditioning.cc
libmv/multiview/euclidean_resection.cc
libmv/multiview/fundamental.cc
libmv/multiview/homography.cc
libmv/multiview/projection.cc
libmv/multiview/triangulation.cc
libmv/multiview/homography.cc
libmv/numeric/numeric.cc
libmv/numeric/poly.cc
libmv/simple_pipeline/bundle.cc
@ -71,8 +71,8 @@ set(SRC
libmv/tracking/lmicklt_region_tracker.cc
libmv/tracking/pyramid_region_tracker.cc
libmv/tracking/retrack_region_tracker.cc
libmv/tracking/trklt_region_tracker.cc
libmv/tracking/track_region.cc
libmv/tracking/trklt_region_tracker.cc
third_party/fast/fast_10.c
third_party/fast/fast_11.c

800
extern/libmv/ChangeLog vendored

@ -1,3 +1,487 @@
commit cfabdfe48df2add3d1f30cf4370efd0b31990ab0
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Dec 20 05:46:53 2012 +0600
Assorted fixes for keyframe selection:
- Biggest error was in cost functors used for F and H refirement,
they were just wrong.
- Use natural logarithms, since it's actually makes sense from
math papers point of view and error is somewhere else.
- Disabled rho for GRIC, for now use non-clamped error for tests.
- Made SymmetricEpipolarDistance returning non-squared distance
Keyframe selection is currently the only used of this function
and it seems using non-squared distance makes much more sense.
Also would think to append suffix "Squared" to functions which
returns squared distances.
- Removed templated version of SymmetricEpipolarDistance, since
it's not needed actually.
This is actually even worse working than previous implementation,
but commit it needed for further review.
commit 35d8c57626ad74818f155e6e5960c663ea84e032
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Dec 20 03:00:40 2012 +0600
Euclidean resection cost function didn't use correct constructor
It was storing a reference to initial rotation passed by value,
leading to pointer being pointing to a stack variable, leading to
wrong memory access in residuals computing.
Apparently was visible in optimized builds only with inline
substitution allowed.
commit 0798d3162bb49cee7e1c423ceccbca1326ad5650
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Dec 20 02:50:52 2012 +0600
Automatic keyframe selection based on Pollefeys's criteria
This commit implements automatic keyframe selection algorithm
based on Pollefeys's criteria (F-GRIC is smaller than H-GRIC
and correspondence ratio is more then 90%).
It is implemented as a part of simple pipeline and returns
vector of keyframe images for a given Tracks structure.
For simple pipeline reconstruction two best keyframes are
expected to be selected from all detected candidates.
Criteria for this selection could be reprojection error of
solution from two candidate keyfames.
Unfortunately, it's not fully workable yet, hopefully would
be fixed soon.
commit e943985552f0598ae122252876f305d72c25c2f9
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Dec 6 17:47:11 2012 +0600
Camera Tracking: allow fallback to reprojection resection
by user demand
This fixes some "regressions" introduced in previous commit
which lead to much worse solution in some cases. Now it's
possible to bring old behavior back.
Perhaps it's more like temporal solution for time being smarter
solution is found. But finding such a solution isn't so fast,
so let's bring manual control over reprojection usage.
But anyway, imo it's now nice to have a structure which could
be used to pass different settings to the solver.
commit 5a23d01dd531d1e0798298d17ba42a3397effb82
Author: Keir Mierle <mierle@gmail.com>
Date: Thu Sep 20 18:55:44 2012 +0000
Make Euclidean resection "always" succeed.
The Euclidean resection code had a magical constant, 1e-3, used to
compare the results of solving an equation. This failure detection
was well-intended, trying to prevent poor solutions from getting
made without notifying the caller. Unfortunately in practice, this
threshold is too conservative. Furthermore, it is not clear the
threshold should exist at all; the purpose of the Euclidean
resection is to come up with the best solution it can; other
methods (e.g. reprojection error) should be used to compare
whether the method succeeded.
This commit changes the Euclidean EPnP code to always succeed,
causing the previous fallback to projective resection to never
run. In most cases, this will result in better reconstructions.
This should, in most cases, fix the dreaded "flipping" problem.
commit 57dad861d2a7f9d058c6d8edde1a2d51d7225a51
Author: Keir Mierle <mierle@gmail.com>
Date: Thu Sep 20 02:27:34 2012 +0000
Fix variable naming in the planar tracker.
commit e9392fd3b46f5668662935696e7d9afac3390ca4
Author: Keir Mierle <mierle@gmail.com>
Date: Thu Sep 20 02:10:33 2012 +0000
Add smarter tolerance checking in the planar tracker.
The planar tracker uses Ceres for the refinement stage. During
refinement, Ceres iteratively updates the parameters with the
latest best guess. If the change in the parameters falls below a
threshold, Ceres will abort successfully ("converged").
For the case of pure translation tracking, the parameters are
exactly the two pixel shifts (dx, dy), and measuring the change in
these parameters gives a meaningful termination criterion.
However, for all the other parameterizations like affine, where
the parameterization involves affine parameters that have no
physical interpretation, Ceres is left with no way to terminate
the solver early. With the existing code, often many iterations
are run long after Ceres has found a solution sufficiently
accurate for all tracking needs. No one needs tracking with
a quadrillionth of a pixel accuracy; that time is wasted.
This patch extends the existing iteration callback that is passed
in to Ceres to check if the pattern has fallen out of the search
window, to also check if the optimizer has made a tiny step. In
particular, if the maximum shift of any patch corner between two
successful optimizer steps is less than a threshold (currently
0.005 pixels), the track is declared successful and tracking
is terminated.
This leads to dramatic speed increases in some cases, with little
to no loss in track quality. This is especially apparent when
tracking patches with affine or perspective motion models. For
example, on some tracking cases I tried, the iterations Ceres took
went from 50 to 3.
commit 36729c19bf90cb767e9adb96ba7dd48a5ace2be1
Author: Keir Mierle <mierle@gmail.com>
Date: Wed Sep 19 22:25:02 2012 +0000
Detect too-small planar tracking patches.
The planar tracker did not detect very skinny patches which have
effectively zero area and are untrackable. This adds detection and
rejection of patterns with zero area. This fixes a crash found by
during Mango production.
commit 5cf2bae255a5a0f2e36ea0516670782cb88b589d
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Dec 6 17:33:53 2012 +0600
Real fix for previous commit from Keir. He's comment;
Cleanup for when trackers fall out of the search window.
Sergey originally left a TODO() here, but his fix is the correct
one. I removed the TODO and fixed some comment issues.
commit a11533918720e5b43dc1e95895db0eb36c8c06aa
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Dec 6 17:31:16 2012 +0600
Fix crash when tracking in planar motion model (and maybe some other)
It was an Abort() caused by check for solver result not equal to USER_ABORT.
In some cases solver returns USER_ABORT due to BoundaryCheckingCallback
detects coordinates does not belong to image.
Somehow this callback wasn't called in previous version of Ceres and
in the same case marker was jumping. Now when the callback is called
it seems we could simply return failure of tracking without aborting
Blender.
Probably this is in fact some issue somewhere else, would double
check with Keir about this.
commit 4be2306bcc664b259aaf7068b9f32ab60124a509
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Dec 6 17:29:39 2012 +0600
Resolved some compilation warnings (missed prototypes)
In some cases it was missed include of header file, in some other
cases symbol could be static.
commit bef729ba5c12683d13584d2a728b8b6506b7ca90
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Dec 6 17:27:17 2012 +0600
Code cleanup: silence some -Wnarrowing warnings from C++11
commit add1415d896818367087c784a3013dd8f1bb2095
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Dec 6 17:25:18 2012 +0600
Changes to SamplePlanarPatch to support mask input and
added output for pattern center.
commit daa354c0735b954b0cd7725626e9a3d67416d46b
Author: Keir Mierle <mierle@gmail.com>
Date: Sat Jun 9 19:22:39 2012 +0000
Change libmv's bilinear sampling to assume the same
pixel conventions as Blender. This fixes the preview
widget in Blender, and should make tracking slightly
more accurate.
commit 99b6222873fbfbe248316316956720376a58f438
Author: Keir Mierle <mierle@gmail.com>
Date: Sat Jun 9 18:58:51 2012 +0000
Add new warp regularization scheme for planar tracking.
This adds a new term to the tracking cost function that
restricts how much the optimizer can warp the patch (as
opposed to merely adjusting the translation). This should
reduce the "jumpiness" that is sometimes seen when doing
non-"Loc" tracks.
It is disabled in this commit; a subsequent commit will add
controls to the tracking dialog for this.
commit a1c5a70badd11cba0470700bad2eac2b2bd30c86
Author: Keir Mierle <mierle@gmail.com>
Date: Sat Jun 9 06:55:21 2012 +0000
Planar tracker polish.
- Fixes the correlation checking code that was broken in the
previous commit. The bug was a transpose error.
- Fixes a memory leak of the warp functor, found by Sameer.
- Various cleanups done at Sameer's suggestion.
Thanks to Sameer Agarwal for a code review.
commit 2cb784caa854a77cdd43620ab133f26b87ed0d83
Author: Keir Mierle <mierle@gmail.com>
Date: Fri Jun 8 17:42:17 2012 +0000
Make planar tracking much faster.
- This makes planar tracking around 2-3x or more faster than
before, by rearranging how the sampling is done.
Previously, the source patch was sampled repeatedly on
every optimizer iteration; this was done for
implementation speed, but was wasteful in computation.
- This also contains some additions to Ceres to help
deailing with mixed numeric / automatic differentation. In
particular, there is now a "Chain::Rule" operator that
facilitates calling a function that takes Jet arguments,
yet does numeric derivatives internally. This is used to
mix the numeric differentation of the images with the warp
parameters, passed as jets by Ceres to the warp functor.
There is also a new "JetOps" object for doing operations
on types which may or may not be jets, such as scaling
the derivative part only, or extracting the scalar part
of a jet.
This patche is aimed at Ceres upstream.
- A new function for sampling a patch is now part of the
track_region.h API; this will get used to make the preview
widget properly show what is getting tracked. Currently
the preview widget does not handle perspective tracks.
Known issues:
This patch introduces a bug such that the "Minimum
Correlation" flag does not work; if it is enabled, tracking
aborts immediately. The workaround for now is to disable the
correlation checking, and examine your tracks carefully. A
fix will get added shortly.
commit 81d028f13738ebe2304287dfce90e91bc782e2cf
Author: Keir Mierle <mierle@gmail.com>
Date: Fri May 18 20:04:43 2012 +0000
Remove an unnecessary template<> line in libmv. Convert debug logs to LG.
commit 238aaba241ef99995d254aadc974db719da04b96
Author: Keir Mierle <mierle@gmail.com>
Date: Fri May 18 12:05:10 2012 +0000
Support normalization in the tracking prepass
The last tracker commit added normalized tracking. This makes
tracking patches undergoing uniform illumination change easier.
However, the prepass which computes a quick translation-only
estimate of the warp did not take this into account. This commit
fixes that.
This works reasonably well but in some examples the brute
initialization fails. I suspect this is due to the warped template
estimate in the current frame being too different from the
original, so there are multiple peaks in the normalized-SAD
correlation function.
The solution is to use the previous frame for the brute
initialization and the keyframe for refinement, but that requires
architecture changes.
commit 981ca4f6a679cd9ac3d086eae3cd946ce72ca8a5
Author: Keir Mierle <mierle@gmail.com>
Date: Fri May 18 02:12:47 2012 +0000
Add light-normalized tracking to the planar tracker
This commit adds the ability to normalize patterns by their
average value while tracking, to make them invariant to global
illumination changes.
To see this in action, check out the "Lobby" scene from Hollywood
VFX. If you track the markers that are shadowed by the actress,
previously they would not track. With the scale adaption on, the
tracker would shrink the area to compensate for the changed
illumination, losing the track. With "Normalize" turned on, the
patch is correctly tracked and scale is maintained.
A remaining problem is that only the Ceres cost function is
updated to handle the normalization. The brute translation search
does not take this into account. Perhaps "Prepass" (see below)
should get disabled if normalization is enabled until I fix the
prepass to normalize as well.
There are a few other changes:
- Bail out of the sampling loop early if the mask is zero; this
saves expensive samples of the image derivatives.
- Fix a bug where the mask was ignored when sampling in the cost
functor.
commit e9384b15fb2a6a5b81346d5758fa136f0911e945
Author: Keir Mierle <mierle@gmail.com>
Date: Thu May 17 23:53:32 2012 +0000
Implement support for affine tracking in the planar tracker; cleanups.
commit 021d41eed8b4ce6a4e37786ccd357ed5dc83a13f
Author: Keir Mierle <mierle@gmail.com>
Date: Thu May 17 21:26:06 2012 +0000
For the planar tracker, initialize the warp from the four correspondences
after brute force translation search.
commit 003d1bf6145cfd30938b35f6e10d43708dbf916c
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Dec 6 16:56:01 2012 +0600
Correction to region tracker options initialization.
Based on patch from Keir to Blender:
https://svn.blender.org/svnroot/bf-blender/branches/soc-2011-tomato@46743
commit 6af47b218cfdf5219f0ebb3cb95459817cf9abf2
Author: Keir Mierle <mierle@gmail.com>
Date: Thu May 17 02:31:52 2012 +0000
Add new planar tracker features and use the new planar API
This commit removes the use of the legacy RegionTracker API from
Blender, and replaces it with the new TrackRegion API. This also
adds several features to the planar tracker in libmv:
- Do a brute-force initialization of tracking similar to "Hybrid"
mode in the stable release, but using all floats. This is slower
but more accurate. It is still necessary to evaluate if the
performance loss is worth it. In particular, this change is
necessary to support high bit depth imagery.
- Add support for masks over the search window. This is a step
towards supporting user-defined tracker masks. The tracker masks
will make it easy for users to make a mask for e.g. a ball.
- Add Pearson product moment correlation coefficient checking (aka
"Correlation" in the UI. This causes tracking failure if the
tracked patch is not linearly related to the template.
- Add support for warping a few points in addition to the supplied
points. This is useful because the tracking code deliberately
does not expose the underlying warp representation. Instead,
warps are specified in an aparametric way via the correspondences.
- Remove the "num_samples_xy" concept and replace it with
automatic determination of the number of samples. This makes the
API easier for users.
- Fix various bugs in the parameterizations.
There remains a bug with subpixel precision tracking when in
"keyframe" mode; this will get fixed shortly.
commit 16a46db104468cec80bd31ca9d5f8bffbe3e003e
Author: Keir Mierle <mierle@gmail.com>
Date: Mon May 14 12:15:38 2012 +0000
"Efficient Second-order Minimization" for the planar tracker
This implements the "Efficient Second-order Minimization"
scheme, as supported by the existing translation tracker.
This increases the amount of per-iteration work, but
decreases the number of iterations required to converge and
also increases the size of the basin of attraction for the
optimization.
commit 23243b1b1f3e1ab3ef862b47bca06ee876ac2cf4
Author: Keir Mierle <mierle@gmail.com>
Date: Sun May 13 23:08:56 2012 +0000
Add a planar tracking implementation to libmv
This adds a new planar tracking implementation to libmv. The
tracker is based on Ceres[1], the new nonlinear minimizer that
myself and Sameer released from Google as open source. Since
the motion model is more involved, the interface is
different than the RegionTracker interface used previously
in Blender.
The ESM tracker, also known as the KLT tracker in the UI, is
temporarily changed to use the new Ceres-based planar
tracker in translation-only mode. Currently it is a bit
slower than ESM and also doesn't have all the bells and
whistles implemented. Those will come soon. Longer term,
both trackers will remain since Ceres is unlikely to be as
fast as ESM for pure translation solving, due to its
generality.
The next step is to implement a new tracking UI. The current
UI assumes a translational motion model; the new one must
support arbitrary perspective transforms of the pattern
regions.
[1] http://code.google.com/p/ceres-solver
commit 52be92b53eb4decb1a316690b162196f227cc441
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Dec 6 16:06:08 2012 +0600
Initial Ceres integration
Currently only put sources to src/third_party/ceres and made sure they're
not giving compilation issues.
Used Ceres upstream version 1.3.0.
Needed to make some modifications to it's CMakeLists.txt also to glog and
fglags. They're described in README.libmv of this libraries.
Basically:
- Added -fPIC to glog/gflags, so shared ceres library could be linked
statically against this libraries.
- Tweaked Ceres's build rules to use needed libraries from libmv's
third_party folder.
commit b13f9d13122e091cb85855c2094386ccdef6e5a4
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed Dec 5 19:05:34 2012 +0600
Update Eigen to version 3.1.2
Mainly because of lots of warnings generating by gcc-4.7 which are
resolved in newer eigen version.
commit 1f0dd94e8e37d3fe2df89282ec16a6a685fdde0b
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri May 25 16:36:44 2012 +0600
- Added avutil to qt-tracker linking when building with FFmpeg support.
On some platforms it seems to be required
- Synchronized QT Creator project for qt-tracker with changes in sources,
so no it might be compiled from QT Creator.
commit b813dbe3f46bbbc7e73ac791d4665622e4fc7ba5
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed May 9 19:01:10 2012 +0600
@ -238,319 +722,3 @@ Date: Fri Feb 17 20:08:01 2012 +0600
SAD tracker now can deal with pattern size any size,
Very quick implementation came from Blender before Hybrid tracker was added.
Better to be replaced with brute tracker.
commit d547c9cfe37d5d3397d33c8b0e58471e1e1c1634
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Feb 17 20:03:52 2012 +0600
Just convert end of lines to unix style.
commit eb73ddbaec5b9e1ad30331bbf858a6ebc266c4aa
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Feb 17 20:02:20 2012 +0600
Made some function static. Resolves possible linking issues when building with MinGW.
commit 2930681fafd86e4f4a958054b1db8bfff29623d1
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Feb 17 19:59:45 2012 +0600
Missed this in commit with improvements in camera intrinsics.
commit 8d31bc767019b05c5bf8c9f309f9545b3428afa1
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Feb 17 19:57:51 2012 +0600
Another step of syncing codebase with Blender.
Mainly fixes for freebsd/osx compilation and aligned memory allocation.
commit 3214a2df5bfd98021f25d0f1a626a86318bb245f
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Feb 17 19:48:02 2012 +0600
Support compilation on FreeBSD platform
commit 0e5abe96f543687ccfb3a923ec639cb8f45d54f8
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Feb 17 19:44:18 2012 +0600
Implementation of basic system for progress reporting into callee stuff
Implemented by using simple callbacks classes which are getting invoked from
places where lots of calculation happens, so applications which are using
libmv may display nice progress bar.
commit c5e18fe35464618055e0e9761be8d22fae56db49
Author: Keir Mierle <mierle@gmail.com>
Date: Fri Feb 17 19:25:45 2012 +0600
Add support for detecting tracking failure in the ESM tracker component of
libmv. Since both KLT and Hybrid rely on ESM underneath, KLT and Hybrid now
have a minimum correlation setting to match. With this fix, track failures
should get detected quicker, with the issue that sometimes the tracker will
give up too easily. That is fixable by reducing the required correlation (in
the track properties).
commit ea0fed736ecdcc8c020227aeef8ef4cd3be5e63d
Author: Keir Mierle <mierle@gmail.com>
Date: Fri Feb 17 19:23:50 2012 +0600
Add a new hybrid region tracker for motion tracking to libmv, and
add it as an option (under "Hybrid") in the tracking settings. The
region tracker is a combination of brute force tracking for coarse
alignment, then refinement with the ESM/KLT algorithm already in
libmv that gives excellent subpixel precision (typically 1/50'th
of a pixel)
This also adds a new "brute force" region tracker which does a
brute force search through every pixel position in the destination
for the pattern in the first frame. It leverages SSE if available,
similar to the SAD tracker, to do this quickly. Currently it does
some unnecessary conversions to/from floating point that will get
fixed later.
The hybrid tracker glues the two trackers (brute & ESM) together
to get an overall better tracker. The algorithm is simple:
1. Track from frame 1 to frame 2 with the brute force tracker.
This tries every possible pixel position for the pattern from
frame 1 in frame 2. The position with the smallest
sum-of-absolute-differences is chosen. By definition, this
position is only accurate up to 1 pixel or so.
2. Using the result from 1, initialize a track with ESM. This does
a least-squares fit with subpixel precision.
3. If the ESM shift was more than 2 pixels, report failure.
4. If the ESM track shifted less than 2 pixels, then the track is
good and we're done. The rationale here is that if the
refinement stage shifts more than 1 pixel, then the brute force
result likely found some random position that's not a good fit.
commit a07fff8431621c01d81ae52595d8dd91a295a776
Author: Keir Mierle <mierle@gmail.com>
Date: Fri Feb 17 19:19:58 2012 +0600
Assorted camera tracker improvements
- Add support for refining the camera's intrinsic parameters
during a solve. Currently, refining supports only the following
combinations of intrinsic parameters:
f
f, cx, cy
f, cx, cy, k1, k2
f, k1
f, k1, k2
This is not the same as autocalibration, since the user must
still make a reasonable initial guess about the focal length and
other parameters, whereas true autocalibration would eliminate
the need for the user specify intrinsic parameters at all.
However, the solver works well with only rough guesses for the
focal length, so perhaps full autocalibation is not that
important.
Adding support for the last two combinations, (f, k1) and (f,
k1, k2) required changes to the library libmv depends on for
bundle adjustment, SSBA. These changes should get ported
upstream not just to libmv but to SSBA as well.
- Improved the region of convergence for bundle adjustment by
increasing the number of Levenberg-Marquardt iterations from 50
to 500. This way, the solver is able to crawl out of the bad
local minima it gets stuck in when changing from, for example,
bundling k1 and k2 to just k1 and resetting k2 to 0.
- Add several new region tracker implementations. A region tracker
is a libmv concept, which refers to tracking a template image
pattern through frames. The impact to end users is that tracking
should "just work better". I am reserving a more detailed
writeup, and maybe a paper, for later.
- Other libmv tweaks, such as detecting that a tracker is headed
outside of the image bounds.
This includes several changes made directly to the libmv extern
code rather expecting to get those changes through normal libmv
channels, because I, the libmv BDFL, decided it was faster to work
on libmv directly in Blender, then later reverse-port the libmv
changes from Blender back into libmv trunk. The interesting part
is that I added a full Levenberg-Marquardt loop to the region
tracking code, which should lead to a more stable solutions. I
also added a hacky implementation of "Efficient Second-Order
Minimization" for tracking, which works nicely. A more detailed
quantitative evaluation will follow.
commit 0bf66c009d5022eacfc473d247884a73ffeefa8f
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Feb 17 19:13:49 2012 +0600
Rest of compilation fix with FAST library.
commit 71b578ca2ba34c528363c514cd1fcc85791d01f3
Author: Keir Mierle <mierle@gmail.com>
Date: Fri Feb 17 19:00:28 2012 +0600
Improve the KLT tracking behaviour and UI
- Remove the overly-conservative use of libmv's re-track tracker. The re-track
tracker would take a normal tracker such as TRKLT or KLT or pyramid KLT, and
track from frame 1 to 2, then back from the position found in 2 back to 1.
Then, when the reverse-track doesn't match the original track with high
precision, the track is considered "failed". This is a good approach for
fully automatic reconstruction, but is too conservative for supervised
tracking.
The retrack-tracker will return when fully automatic tracking is added.
- Always solve for (dx, dy) in the TRKLT loop even if the linear system is
ill-conditioned. The client (Blender in this case) can still use the solved
position, even though it is less reliable.
commit 7d8a8762f2bc2e36f95b0b6f4fb4ca996f9f0db7
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Feb 17 18:46:24 2012 +0600
Changes in camera intrinsics distortion/undistortion:
- Distortion/undistortion of scaled images wasn't happening right,
because camera intrinsics are calibrated on an original frame which
has got some particular resolution and trying to apply this model on
an image with another resolution gives totally wrong result.
This is needed to be able to do post-prccessing of render, running
distortion on a scene which might be rendered with higher resolution
than footage itself and then be scaled down.
- Fixed incorrect calculation/applying of precomputed grid when
distortion is high high enough and produces pixel offset higher
than 127 pixels. This might be still not very distorted image,
but if it's a 4K footage "normal" camera will easily give such
a distortion.
- Added support of overscan distortion/undistortion.
commit ed080785d63bb8e3a13dde51a2dc94fe59b059bb
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Feb 17 18:38:51 2012 +0600
Fast headers now can be included from C++ sources.
Was needed to make it working fine when bundling in Blender but might also
be needed to bundle into another applications.
commit 5f5a7aa46a2d87b96c8098dfc8682f4d01b5cd40
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Feb 17 18:36:16 2012 +0600
Bring back FAST detector which seems to be working much nicer than Morravec.
Both of them are available in API.
commit 2cab13c18216fb684b270cec077f7300262584af
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Feb 17 18:27:36 2012 +0600
Revert "Make CameraIntrinsics (and thus Qt tracker) compilable without linking libmv."
This reverts commit 81613ee0cc94b315f333c9632b18b95d426aad05.
That commit made inverting intrinsics totally unworkable, so reverted this and
made needed tweaks to qt-tracker project file to make it compilable (was needed
to make it linking together with glog).
Conflicts:
src/ui/tracker/tracker.cc
src/ui/tracker/tracker.pro
commit ec46cae041401b17afb4fe4d9c9343d10797090f
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Feb 17 17:59:55 2012 +0600
Fix compilation error using official MinGW
commit 6fbc370e922c47cfa35381662b6c439f4891ed74
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Feb 17 17:38:20 2012 +0600
Fix compilation error with MSVC 2010 which is more picky for "missed" STL headers
commit be9e6b63691d83b551a085f0766878bd84220767
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Feb 17 17:36:18 2012 +0600
Fix compilation with MSVC where snprintf function is declared as unsafe and _snprintf should be used instead.
Better to switch to own implementation will ensure string is correctly NULL-terminated.
commit 1847d9e414ed763cd80668775d7d9f79575fc8ca
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Feb 17 17:34:45 2012 +0600
Fix compilation error on OSX caused by incorrect access to ucontext
commit 90579b6ffad07672172a1c240499615b30b25549
Merge: b9aac30 531c79b
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Feb 17 18:32:52 2012 +0600
Merge remote-tracking branch 'Matthias-Fauconneau/master' into devel
Conflicts:
src/libmv/tracking/CMakeLists.txt
commit b9aac30a9ca6bc8362c09a0e191040964f7c6de2
Merge: 198894e 6969e1a
Author: Keir Mierle <mierle@gmail.com>
Date: Sat Nov 5 17:38:30 2011 -0700
Merge pull request #3 from nathanwiegand/master
Just a few tiny cleanups
commit 6969e1a9534291a982749baa5a3672c97bfa506d
Author: Nathan Wiegand <nathanwiegand@gmail.com>
Date: Sat Nov 5 14:26:54 2011 -0700
I've added cleaned up a few style issues here an there. Also, I've updated the CMakeLists.txt file so that it can build the image_io library. Note, it's only been tested on OSX 10.6
commit 4763f851299050140757bfaa069107a0cf639e56
Author: Nathan Wiegand <nathanwiegand@gmail.com>
Date: Fri Nov 4 23:59:08 2011 -0700
Removed a superfulous comment
commit a44577c0162e273681e4a9a3cc5f5b37d4315b67
Author: Nathan Wiegand <nathanwiegand@gmail.com>
Date: Fri Nov 4 23:55:52 2011 -0700
Removed a duplicate entry for an author.
commit 198894e4c4f51c2c1784ad7c02eb45d2d1ada9bc
Merge: c4c67db 6e797d6
Author: Keir Mierle <mierle@gmail.com>
Date: Fri Nov 4 21:47:05 2011 -0700
Merge pull request #2 from nathanwiegand/master
CMake changes for OSX
commit 6e797d678c4c19f6a9e21657d66183f412cc995b
Author: Nathan Wiegand <nathanwiegand@gmail.com>
Date: Fri Nov 4 21:43:28 2011 -0700
Uncomment the GUI part of the CMake file
commit 33ef88a33860345d8906f3c9dd22d8dbce3df53e
Author: Nathan Wiegand <nathanwiegand@gmail.com>
Date: Fri Nov 4 21:31:22 2011 -0700
Fixed build error on OSX by adding 'glog' to the dependencies in the tracker CMake
commit 531c79bf95fddaaa70707d1abcd4fdafda16bbf0
Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
Date: Sat Aug 20 00:00:42 2011 +0200
Display warped pattern in marker preview.
commit bb5c27e671b6f8eb56ddf490f0795d59bede591b
Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
Date: Fri Aug 19 18:37:48 2011 +0200
Fix CMake build.

@ -136,19 +136,6 @@ set(INC_SYS
\${ZLIB_INCLUDE_DIRS}
)
# XXX - FIXME
# this is a momentary hack to find unwind.h in 10.6.sdk
if(APPLE)
if(\${CMAKE_OSX_DEPLOYMENT_TARGET} STREQUAL "10.6")
list(APPEND INC_SYS
\${CMAKE_OSX_SYSROOT}/Developer/usr/llvm-gcc-4.2/lib/gcc/i686-apple-darwin10/4.2.1/include
)
endif()
endif()
# XXX - END
set(SRC
libmv-capi.cpp
${sources}

@ -17,6 +17,9 @@ libmv/multiview/euclidean_resection.cc
libmv/multiview/euclidean_resection.h
libmv/multiview/fundamental.cc
libmv/multiview/fundamental.h
libmv/multiview/homography.cc
libmv/multiview/homography.h
libmv/multiview/homography_parameterization.h
libmv/multiview/nviewtriangulation.h
libmv/multiview/projection.cc
libmv/multiview/projection.h
@ -69,6 +72,8 @@ libmv/tracking/pyramid_region_tracker.h
libmv/tracking/region_tracker.h
libmv/tracking/retrack_region_tracker.cc
libmv/tracking/retrack_region_tracker.h
libmv/tracking/track_region.cc
libmv/tracking/track_region.h
libmv/tracking/trklt_region_tracker.cc
libmv/tracking/trklt_region_tracker.h
third_party/fast/fast_10.c

@ -254,8 +254,8 @@ double SymmetricEpipolarDistance(const Mat &F, const Vec2 &x1, const Vec2 &x2) {
Vec3 Ft_y = F.transpose() * y;
double y_F_x = y.dot(F_x);
return Square(y_F_x) * ( 1 / F_x.head<2>().squaredNorm()
+ 1 / Ft_y.head<2>().squaredNorm());
return y_F_x * ( 1 / F_x.head<2>().norm()
+ 1 / Ft_y.head<2>().norm());
}
// HZ 9.6 pag 257 (formula 9.12)

@ -31,22 +31,6 @@
namespace libmv {
namespace {
void CoordinatesForMarkersInImage(const vector<Marker> &markers,
int image,
Mat *coordinates) {
vector<Vec2> coords;
for (int i = 0; i < markers.size(); ++i) {
const Marker &marker = markers[i];
if (markers[i].image == image) {
coords.push_back(Vec2(marker.x, marker.y));
}
}
coordinates->resize(2, coords.size());
for (int i = 0; i < coords.size(); i++) {
coordinates->col(i) = coords[i];
}
}
void GetImagesInMarkers(const vector<Marker> &markers,
int *image1, int *image2) {
if (markers.size() < 2) {

@ -72,6 +72,16 @@ vector<Marker> Tracks::MarkersForTrack(int track) const {
return markers;
}
vector<Marker> Tracks::MarkersInBothImages(int image1, int image2) const {
vector<Marker> markers;
for (int i = 0; i < markers_.size(); ++i) {
int image = markers_[i].image;
if (image == image1 || image == image2)
markers.push_back(markers_[i]);
}
return markers;
}
vector<Marker> Tracks::MarkersForTracksInBothImages(int image1, int image2) const {
std::vector<int> image1_tracks;
std::vector<int> image2_tracks;
@ -156,4 +166,20 @@ int Tracks::NumMarkers() const {
return markers_.size();
}
void CoordinatesForMarkersInImage(const vector<Marker> &markers,
int image,
Mat *coordinates) {
vector<Vec2> coords;
for (int i = 0; i < markers.size(); ++i) {
const Marker &marker = markers[i];
if (markers[i].image == image) {
coords.push_back(Vec2(marker.x, marker.y));
}
}
coordinates->resize(2, coords.size());
for (int i = 0; i < coords.size(); i++) {
coordinates->col(i) = coords[i];
}
}
} // namespace libmv

@ -22,6 +22,7 @@
#define LIBMV_SIMPLE_PIPELINE_TRACKS_H_
#include "libmv/base/vector.h"
#include "libmv/numeric/numeric.h"
namespace libmv {
@ -84,6 +85,9 @@ class Tracks {
/// Returns all the markers visible in \a image.
vector<Marker> MarkersInImage(int image) const;
/// Returns all the markers visible in \a image1 and \a image2.
vector<Marker> MarkersInBothImages(int image1, int image2) const;
/*!
Returns the markers in \a image1 and \a image2 which have a common track.
@ -114,6 +118,10 @@ class Tracks {
vector<Marker> markers_;
};
void CoordinatesForMarkersInImage(const vector<Marker> &markers,
int image,
Mat *coordinates);
} // namespace libmv
#endif // LIBMV_SIMPLE_PIPELINE_MARKERS_H_

@ -11,4 +11,6 @@ Local modifications:
- Added a poor-man's version of upstream's port.cc/h to make gflags compile on
windows. This isn't sufficient but is a stopgap for now.
- Added -fPIC flag, so shared libraries from Ceres could be linked against static glog
TODO(keir): Import and use gflags for Windows from upstream.

@ -22,3 +22,4 @@ Upgrading Notes
* Do not define va_copy for MinGW platforms (it's already defined there).
* Patch localtime_r to be working fine with MinGW, disable strerror_r for MinGW because
of lack of needed functions.
* Added -fPIC flag, so shared libraries from Ceres could be linked against static glog

@ -68,7 +68,7 @@ if(WITH_CYCLES_BLENDER)
add_subdirectory(blender)
endif()
if(WITH_CYCLES_TEST)
if(WITH_CYCLES_TEST OR WITH_CYCLES_NETWORK)
add_subdirectory(app)
endif()

@ -23,7 +23,9 @@
#include "util_args.h"
#include "util_foreach.h"
#include "util_path.h"
#include "util_stats.h"
#include "util_string.h"
#include "util_task.h"
using namespace ccl;
@ -32,29 +34,29 @@ int main(int argc, const char **argv)
path_init();
/* device types */
string devices = "";
string devicelist = "";
string devicename = "cpu";
bool list = false;
vector<DeviceType>& types = Device::available_types();
foreach(DeviceType type, types) {
if(devices != "")
devices += ", ";
if(devicelist != "")
devicelist += ", ";
devices += Device::string_from_type(type);
devicelist += Device::string_from_type(type);
}
/* parse options */
ArgParse ap;
ap.options ("Usage: cycles_server [options]",
"--device %s", &devicename, ("Devices to use: " + devices).c_str(),
"--device %s", &devicename, ("Devices to use: " + devicelist).c_str(),
"--list-devices", &list, "List information about all available devices",
NULL);
if(ap.parse(argc, argv) < 0) {
fprintf(stderr, "%s\n", ap.error_message().c_str());
fprintf(stderr, "%s\n", ap.geterror().c_str());
ap.usage();
exit(EXIT_FAILURE);
}
@ -84,13 +86,18 @@ int main(int argc, const char **argv)
}
}
TaskScheduler::init();
while(1) {
Device *device = Device::create(device_info);
printf("Cycles Server with device: %s\n", device->description().c_str());
Stats stats;
Device *device = Device::create(device_info, stats);
printf("Cycles Server with device: %s\n", device->info.description.c_str());
device->server_run();
delete device;
}
TaskScheduler::exit();
return 0;
}

@ -331,7 +331,13 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use
/* device default CPU */
params.device = devices[0];
if(RNA_enum_get(&cscene, "device") != 0) {
if(RNA_enum_get(&cscene, "device") == 2) {
/* find network device */
foreach(DeviceInfo& info, devices)
if(info.type == DEVICE_NETWORK)
params.device = info;
}
else if(RNA_enum_get(&cscene, "device") == 1) {
/* find GPU device with given id */
PointerRNA systemptr = b_userpref.system().ptr;
PropertyRNA *deviceprop = RNA_struct_find_property(&systemptr, "compute_device");

@ -31,6 +31,8 @@ class NetworkDevice : public Device
public:
boost::asio::io_service io_service;
tcp::socket socket;
device_ptr mem_counter;
DeviceTask the_task; /* todo: handle multiple tasks */
NetworkDevice(Stats &stats, const char *address)
: Device(stats), socket(io_service)
@ -49,75 +51,72 @@ public:
socket.close();
socket.connect(*endpoint_iterator++, error);
}
if(error)
throw boost::system::system_error(error);
mem_counter = 0;
}
~NetworkDevice()
{
RPCSend snd(socket, "stop");
snd.write();
}
void mem_alloc(device_memory& mem, MemoryType type)
{
#if 0
mem.device_pointer = ++mem_counter;
RPCSend snd(socket, "mem_alloc");
snd.archive & size & type;
snd.add(mem);
snd.add(type);
snd.write();
RPCReceive rcv(socket);
device_ptr mem;
*rcv.archive & mem;
return mem;
#endif
}
void mem_copy_to(device_memory& mem)
{
#if 0
RPCSend snd(socket, "mem_copy_to");
snd.archive & mem & size;
snd.add(mem);
snd.write();
snd.write_buffer(host, size);
#endif
snd.write_buffer((void*)mem.data_pointer, mem.memory_size());
}
void mem_copy_from(device_memory& mem, int y, int w, int h, int elem)
{
#if 0
RPCSend snd(socket, "mem_copy_from");
snd.archive & mem & offset & size;
snd.add(mem);
snd.add(y);
snd.add(w);
snd.add(h);
snd.add(elem);
snd.write();
RPCReceive rcv(socket);
rcv.read_buffer(host, size);
#endif
rcv.read_buffer((void*)mem.data_pointer, mem.memory_size());
}
void mem_zero(device_memory& mem)
{
#if 0
RPCSend snd(socket, "mem_zero");
snd.archive & mem & size;
snd.add(mem);
snd.write();
#endif
}
void mem_free(device_memory& mem)
{
#if 0
if(mem) {
if(mem.device_pointer) {
RPCSend snd(socket, "mem_free");
snd.archive & mem;
snd.add(mem);
snd.write();
mem.device_pointer = 0;
}
#endif
}
void const_copy_to(const char *name, void *host, size_t size)
@ -126,79 +125,107 @@ public:
string name_string(name);
snd.archive & name_string & size;
snd.add(name_string);
snd.add(size);
snd.write();
snd.write_buffer(host, size);
}
void tex_alloc(const char *name, device_memory& mem, bool interpolation, bool periodic)
{
#if 0
mem.device_pointer = ++mem_counter;
RPCSend snd(socket, "tex_alloc");
string name_string(name);
snd.archive & name_string & width & height & datatype & components & interpolation;
snd.add(name_string);
snd.add(mem);
snd.add(interpolation);
snd.add(periodic);
snd.write();
size_t size = width*height*components*datatype_size(datatype);
snd.write_buffer(host, size);
RPCReceive rcv(socket);
device_ptr mem;
*rcv.archive & mem;
return mem;
#endif
snd.write_buffer((void*)mem.data_pointer, mem.memory_size());
}
void tex_free(device_memory& mem)
{
#if 0
if(mem) {
if(mem.device_pointer) {
RPCSend snd(socket, "tex_free");
snd.archive & mem;
snd.add(mem);
snd.write();
mem.device_pointer = 0;
}
#endif
}
void path_trace(int x, int y, int w, int h, device_ptr buffer, device_ptr rng_state, int sample)
{
#if 0
RPCSend snd(socket, "path_trace");
snd.archive & x & y & w & h & buffer & rng_state & sample;
snd.write();
#endif
}
void tonemap(int x, int y, int w, int h, device_ptr rgba, device_ptr buffer, int sample, int resolution)
{
#if 0
RPCSend snd(socket, "tonemap");
snd.archive & x & y & w & h & rgba & buffer & sample & resolution;
snd.write();
#endif
}
void task_add(DeviceTask& task)
{
if(task.type == DeviceTask::TONEMAP)
tonemap(task.x, task.y, task.w, task.h, task.rgba, task.buffer, task.sample, task.resolution);
else if(task.type == DeviceTask::PATH_TRACE)
path_trace(task.x, task.y, task.w, task.h, task.buffer, task.rng_state, task.sample);
the_task = task;
RPCSend snd(socket, "task_add");
snd.add(task);
snd.write();
}
void task_wait()
{
RPCSend snd(socket, "task_wait");
snd.write();
list<RenderTile> the_tiles;
/* todo: run this threaded for connecting to multiple clients */
for(;;) {
RPCReceive rcv(socket);
RenderTile tile;
if(rcv.name == "acquire_tile") {
/* todo: watch out for recursive calls! */
if(the_task.acquire_tile(this, tile)) { /* write return as bool */
the_tiles.push_back(tile);
RPCSend snd(socket, "acquire_tile");
snd.add(tile);
snd.write();
}
else {
RPCSend snd(socket, "acquire_tile_none");
snd.write();
}
}
else if(rcv.name == "release_tile") {
rcv.read(tile);
for(list<RenderTile>::iterator it = the_tiles.begin(); it != the_tiles.end(); it++) {
if(tile.x == it->x && tile.y == it->y && tile.start_sample == it->start_sample) {
tile.buffers = it->buffers;
the_tiles.erase(it);
break;
}
}
assert(tile.buffers != NULL);
the_task.release_tile(tile);
RPCSend snd(socket, "release_tile");
snd.write();
}
else if(rcv.name == "task_wait_done")
break;
}
}
void task_cancel()
{
RPCSend snd(socket, "task_cancel");
snd.write();
}
bool support_advanced_shading()
{
return true; /* todo: get this info from device */
}
};
@ -219,16 +246,285 @@ void device_network_info(vector<DeviceInfo>& devices)
devices.push_back(info);
}
class DeviceServer {
public:
DeviceServer(Device *device_, tcp::socket& socket_)
: device(device_), socket(socket_)
{
}
void listen()
{
/* receive remote function calls */
for(;;) {
RPCReceive rcv(socket);
if(rcv.name == "stop")
break;
process(rcv);
}
}
protected:
void process(RPCReceive& rcv)
{
// fprintf(stderr, "receive process %s\n", rcv.name.c_str());
if(rcv.name == "mem_alloc") {
MemoryType type;
network_device_memory mem;
device_ptr remote_pointer;
rcv.read(mem);
rcv.read(type);
/* todo: CPU needs mem.data_pointer */
remote_pointer = mem.device_pointer;
mem_data[remote_pointer] = vector<uint8_t>();
mem_data[remote_pointer].resize(mem.memory_size());
if(mem.memory_size())
mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
else
mem.data_pointer = 0;
device->mem_alloc(mem, type);
ptr_map[remote_pointer] = mem.device_pointer;
ptr_imap[mem.device_pointer] = remote_pointer;
}
else if(rcv.name == "mem_copy_to") {
network_device_memory mem;
rcv.read(mem);
device_ptr remote_pointer = mem.device_pointer;
mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
rcv.read_buffer((uint8_t*)mem.data_pointer, mem.memory_size());
mem.device_pointer = ptr_map[remote_pointer];
device->mem_copy_to(mem);
}
else if(rcv.name == "mem_copy_from") {
network_device_memory mem;
int y, w, h, elem;
rcv.read(mem);
rcv.read(y);
rcv.read(w);
rcv.read(h);
rcv.read(elem);
device_ptr remote_pointer = mem.device_pointer;
mem.device_pointer = ptr_map[remote_pointer];
mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
device->mem_copy_from(mem, y, w, h, elem);
RPCSend snd(socket);
snd.write();
snd.write_buffer((uint8_t*)mem.data_pointer, mem.memory_size());
}
else if(rcv.name == "mem_zero") {
network_device_memory mem;
rcv.read(mem);
device_ptr remote_pointer = mem.device_pointer;
mem.device_pointer = ptr_map[mem.device_pointer];
mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
device->mem_zero(mem);
}
else if(rcv.name == "mem_free") {
network_device_memory mem;
device_ptr remote_pointer;
rcv.read(mem);
remote_pointer = mem.device_pointer;
mem.device_pointer = ptr_map[mem.device_pointer];
ptr_map.erase(remote_pointer);
ptr_imap.erase(mem.device_pointer);
mem_data.erase(remote_pointer);
device->mem_free(mem);
}
else if(rcv.name == "const_copy_to") {
string name_string;
size_t size;
rcv.read(name_string);
rcv.read(size);
vector<char> host_vector(size);
rcv.read_buffer(&host_vector[0], size);
device->const_copy_to(name_string.c_str(), &host_vector[0], size);
}
else if(rcv.name == "tex_alloc") {
network_device_memory mem;
string name;
bool interpolation;
bool periodic;
device_ptr remote_pointer;
rcv.read(name);
rcv.read(mem);
rcv.read(interpolation);
rcv.read(periodic);
remote_pointer = mem.device_pointer;
mem_data[remote_pointer] = vector<uint8_t>();
mem_data[remote_pointer].resize(mem.memory_size());
if(mem.memory_size())
mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
else
mem.data_pointer = 0;
rcv.read_buffer((uint8_t*)mem.data_pointer, mem.memory_size());
device->tex_alloc(name.c_str(), mem, interpolation, periodic);
ptr_map[remote_pointer] = mem.device_pointer;
ptr_imap[mem.device_pointer] = remote_pointer;
}
else if(rcv.name == "tex_free") {
network_device_memory mem;
device_ptr remote_pointer;
rcv.read(mem);
remote_pointer = mem.device_pointer;
mem.device_pointer = ptr_map[mem.device_pointer];
ptr_map.erase(remote_pointer);
ptr_map.erase(mem.device_pointer);
mem_data.erase(remote_pointer);
device->tex_free(mem);
}
else if(rcv.name == "task_add") {
DeviceTask task;
rcv.read(task);
if(task.buffer) task.buffer = ptr_map[task.buffer];
if(task.rgba) task.rgba = ptr_map[task.rgba];
if(task.shader_input) task.shader_input = ptr_map[task.shader_input];
if(task.shader_output) task.shader_output = ptr_map[task.shader_output];
task.acquire_tile = function_bind(&DeviceServer::task_acquire_tile, this, _1, _2);
task.release_tile = function_bind(&DeviceServer::task_release_tile, this, _1);
task.update_progress_sample = function_bind(&DeviceServer::task_update_progress_sample, this);
task.update_tile_sample = function_bind(&DeviceServer::task_update_tile_sample, this, _1);
task.get_cancel = function_bind(&DeviceServer::task_get_cancel, this);
device->task_add(task);
}
else if(rcv.name == "task_wait") {
device->task_wait();
RPCSend snd(socket, "task_wait_done");
snd.write();
}
else if(rcv.name == "task_cancel") {
device->task_cancel();
}
}
bool task_acquire_tile(Device *device, RenderTile& tile)
{
thread_scoped_lock acquire_lock(acquire_mutex);
bool result = false;
RPCSend snd(socket, "acquire_tile");
snd.write();
while(1) {
RPCReceive rcv(socket);
if(rcv.name == "acquire_tile") {
rcv.read(tile);
if(tile.buffer) tile.buffer = ptr_map[tile.buffer];
if(tile.rng_state) tile.rng_state = ptr_map[tile.rng_state];
if(tile.rgba) tile.rgba = ptr_map[tile.rgba];
result = true;
break;
}
else if(rcv.name == "acquire_tile_none")
break;
else
process(rcv);
}
return result;
}
void task_update_progress_sample()
{
; /* skip */
}
void task_update_tile_sample(RenderTile&)
{
; /* skip */
}
void task_release_tile(RenderTile& tile)
{
thread_scoped_lock acquire_lock(acquire_mutex);
if(tile.buffer) tile.buffer = ptr_imap[tile.buffer];
if(tile.rng_state) tile.rng_state = ptr_imap[tile.rng_state];
if(tile.rgba) tile.rgba = ptr_imap[tile.rgba];
RPCSend snd(socket, "release_tile");
snd.add(tile);
snd.write();
while(1) {
RPCReceive rcv(socket);
if(rcv.name == "release_tile")
break;
else
process(rcv);
}
}
bool task_get_cancel()
{
return false;
}
/* properties */
Device *device;
tcp::socket& socket;
/* mapping of remote to local pointer */
map<device_ptr, device_ptr> ptr_map;
map<device_ptr, device_ptr> ptr_imap;
map<device_ptr, vector<uint8_t> > mem_data;
thread_mutex acquire_mutex;
/* todo: free memory and device (osl) on network error */
};
void Device::server_run()
{
try
{
try {
/* starts thread that responds to discovery requests */
ServerDiscovery discovery;
for(;;)
{
for(;;) {
/* accept connection */
boost::asio::io_service io_service;
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), SERVER_PORT));
@ -236,145 +532,17 @@ void Device::server_run()
tcp::socket socket(io_service);
acceptor.accept(socket);
/* receive remote function calls */
for(;;) {
RPCReceive rcv(socket);
string remote_address = socket.remote_endpoint().address().to_string();
printf("Connected to remote client at: %s\n", remote_address.c_str());
if(rcv.name == "description") {
string desc = description();
DeviceServer server(this, socket);
server.listen();
RPCSend snd(socket);
snd.archive & desc;
snd.write();
}
else if(rcv.name == "mem_alloc") {
#if 0
MemoryType type;
size_t size;
device_ptr mem;
*rcv.archive & size & type;
mem = mem_alloc(size, type);
RPCSend snd(socket);
snd.archive & mem;
snd.write();
#endif
}
else if(rcv.name == "mem_copy_to") {
#if 0
device_ptr mem;
size_t size;
*rcv.archive & mem & size;
vector<char> host_vector(size);
rcv.read_buffer(&host_vector[0], size);
mem_copy_to(mem, &host_vector[0], size);
#endif
}
else if(rcv.name == "mem_copy_from") {
#if 0
device_ptr mem;
size_t offset, size;
*rcv.archive & mem & offset & size;
vector<char> host_vector(size);
mem_copy_from(&host_vector[0], mem, offset, size);
RPCSend snd(socket);
snd.write();
snd.write_buffer(&host_vector[0], size);
#endif
}
else if(rcv.name == "mem_zero") {
#if 0
device_ptr mem;
size_t size;
*rcv.archive & mem & size;
mem_zero(mem, size);
#endif
}
else if(rcv.name == "mem_free") {
#if 0
device_ptr mem;
*rcv.archive & mem;
mem_free(mem);
#endif
}
else if(rcv.name == "const_copy_to") {
string name_string;
size_t size;
*rcv.archive & name_string & size;
vector<char> host_vector(size);
rcv.read_buffer(&host_vector[0], size);
const_copy_to(name_string.c_str(), &host_vector[0], size);
}
else if(rcv.name == "tex_alloc") {
#if 0
string name_string;
DataType datatype;
device_ptr mem;
size_t width, height;
int components;
bool interpolation;
*rcv.archive & name_string & width & height & datatype & components & interpolation;
size_t size = width*height*components*datatype_size(datatype);
vector<char> host_vector(size);
rcv.read_buffer(&host_vector[0], size);
mem = tex_alloc(name_string.c_str(), &host_vector[0], width, height, datatype, components, interpolation);
RPCSend snd(socket);
snd.archive & mem;
snd.write();
#endif
}
else if(rcv.name == "tex_free") {
#if 0
device_ptr mem;
*rcv.archive & mem;
tex_free(mem);
#endif
}
else if(rcv.name == "path_trace") {
#if 0
device_ptr buffer, rng_state;
int x, y, w, h;
int sample;
*rcv.archive & x & y & w & h & buffer & rng_state & sample;
path_trace(x, y, w, h, buffer, rng_state, sample);
#endif
}
else if(rcv.name == "tonemap") {
#if 0
device_ptr rgba, buffer;
int x, y, w, h;
int sample, resolution;
*rcv.archive & x & y & w & h & rgba & buffer & sample & resolution;
tonemap(x, y, w, h, rgba, buffer, sample, resolution);
#endif
}
}
printf("Disconnected.\n");
}
}
catch(exception& e)
{
cerr << "Network server exception: " << e.what() << endl;
catch(exception& e) {
fprintf(stderr, "Network server exception: %s\n", e.what());
}
}

@ -31,15 +31,17 @@
#include <iostream>
#include "buffers.h"
#include "util_foreach.h"
#include "util_list.h"
#include "util_map.h"
#include "util_string.h"
CCL_NAMESPACE_BEGIN
using std::cout;
using std::cerr;
using std::endl;
using std::hex;
using std::setw;
using std::exception;
@ -51,13 +53,63 @@ static const int DISCOVER_PORT = 5121;
static const string DISCOVER_REQUEST_MSG = "REQUEST_RENDER_SERVER_IP";
static const string DISCOVER_REPLY_MSG = "REPLY_RENDER_SERVER_IP";
typedef struct RPCSend {
/* Serialization of device memory */
class network_device_memory : public device_memory
{
public:
network_device_memory() {}
~network_device_memory() { device_pointer = 0; };
vector<char> local_data;
};
/* Remote procedure call Send */
class RPCSend {
public:
RPCSend(tcp::socket& socket_, const string& name_ = "")
: name(name_), socket(socket_), archive(archive_stream)
: name(name_), socket(socket_), archive(archive_stream), sent(false)
{
archive & name_;
}
~RPCSend()
{
if(!sent)
fprintf(stderr, "Error: RPC %s not sent\n", name.c_str());
}
void add(const device_memory& mem)
{
archive & mem.data_type & mem.data_elements & mem.data_size;
archive & mem.data_width & mem.data_height & mem.device_pointer;
}
template<typename T> void add(const T& data)
{
archive & data;
}
void add(const DeviceTask& task)
{
int type = (int)task.type;
archive & type & task.x & task.y & task.w & task.h;
archive & task.rgba & task.buffer & task.sample & task.num_samples;
archive & task.resolution & task.offset & task.stride;
archive & task.shader_input & task.shader_output & task.shader_eval_type;
archive & task.shader_x & task.shader_w;
}
void add(const RenderTile& tile)
{
archive & tile.x & tile.y & tile.w & tile.h;
archive & tile.start_sample & tile.num_samples & tile.sample;
archive & tile.resolution & tile.offset & tile.stride;
archive & tile.buffer & tile.rng_state & tile.rgba;
}
void write()
{
boost::system::error_code error;
@ -84,6 +136,8 @@ typedef struct RPCSend {
if(error.value())
cout << "Network send error: " << error.message() << "\n";
sent = true;
}
void write_buffer(void *buffer, size_t size)
@ -98,13 +152,18 @@ typedef struct RPCSend {
cout << "Network send error: " << error.message() << "\n";
}
protected:
string name;
tcp::socket& socket;
ostringstream archive_stream;
boost::archive::text_oarchive archive;
} RPCSend;
bool sent;
};
typedef struct RPCReceive {
/* Remote procedure call Receive */
class RPCReceive {
public:
RPCReceive(tcp::socket& socket_)
: socket(socket_), archive_stream(NULL), archive(NULL)
{
@ -151,6 +210,19 @@ typedef struct RPCReceive {
delete archive_stream;
}
void read(network_device_memory& mem)
{
*archive & mem.data_type & mem.data_elements & mem.data_size;
*archive & mem.data_width & mem.data_height & mem.device_pointer;
mem.data_pointer = 0;
}
template<typename T> void read(T& data)
{
*archive & data;
}
void read_buffer(void *buffer, size_t size)
{
size_t len = boost::asio::read(socket, boost::asio::buffer(buffer, size));
@ -159,12 +231,39 @@ typedef struct RPCReceive {
cout << "Network receive error: buffer size doesn't match expected size\n";
}
void read(DeviceTask& task)
{
int type;
*archive & type & task.x & task.y & task.w & task.h;
*archive & task.rgba & task.buffer & task.sample & task.num_samples;
*archive & task.resolution & task.offset & task.stride;
*archive & task.shader_input & task.shader_output & task.shader_eval_type;
*archive & task.shader_x & task.shader_w;
task.type = (DeviceTask::Type)type;
}
void read(RenderTile& tile)
{
*archive & tile.x & tile.y & tile.w & tile.h;
*archive & tile.start_sample & tile.num_samples & tile.sample;
*archive & tile.resolution & tile.offset & tile.stride;
*archive & tile.buffer & tile.rng_state & tile.rgba;
tile.buffers = NULL;
}
string name;
protected:
tcp::socket& socket;
string archive_str;
istringstream *archive_stream;
boost::archive::text_iarchive *archive;
} RPCReceive;
};
/* Server auto discovery */
class ServerDiscovery {
public:

@ -55,6 +55,7 @@ set(SRC_CLOSURE_HEADERS
closure/bsdf_phong_ramp.h
closure/bsdf_reflection.h
closure/bsdf_refraction.h
closure/bsdf_toon.h
closure/bsdf_transparent.h
closure/bsdf_util.h
closure/bsdf_ward.h

@ -0,0 +1,206 @@
/*
* Adapted from Open Shading Language with this license:
*
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
* All Rights Reserved.
*
* Modifications Copyright 2011, Blender Foundation.
*
* 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 the names of its
* 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.
*/
#ifndef __BSDF_TOON_H__
#define __BSDF_TOON_H__
CCL_NAMESPACE_BEGIN
/* DIFFUSE TOON */
__device int bsdf_diffuse_toon_setup(ShaderClosure *sc)
{
sc->type = CLOSURE_BSDF_DIFFUSE_TOON_ID;
sc->data0 = clamp(sc->data0, 0.0f, 1.0f);
sc->data1 = clamp(sc->data1, 0.0f, 1.0f);
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
__device void bsdf_diffuse_toon_blur(ShaderClosure *sc, float roughness)
{
}
__device float3 bsdf_toon_get_intensity(float max_angle, float smooth, float angle)
{
float is;
if(angle < max_angle)
is = 1.0f;
else if(angle < (max_angle + smooth) && smooth != 0.0f)
is = (1.0f - (angle - max_angle)/smooth);
else
is = 0.0f;
return make_float3(is, is, is);
}
__device float bsdf_toon_get_sample_angle(float max_angle, float smooth)
{
return fminf(max_angle + smooth, M_PI_2_F);
}
__device float3 bsdf_diffuse_toon_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float max_angle = sc->data0*M_PI_2_F;
float smooth = sc->data1*M_PI_2_F;
float angle = safe_acosf(fmaxf(dot(sc->N, omega_in), 0.0f));
float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
if(eval.x > 0.0f) {
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
*pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
return *pdf * eval;
}
return make_float3(0.0f, 0.0f, 0.0f);
}
__device float3 bsdf_diffuse_toon_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
__device int bsdf_diffuse_toon_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{
float max_angle = sc->data0*M_PI_2_F;
float smooth = sc->data1*M_PI_2_F;
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
float angle = sample_angle*randu;
if(sample_angle > 0.0f) {
sample_uniform_cone(sc->N, sample_angle, randu, randv, omega_in, pdf);
if(dot(Ng, *omega_in) > 0.0f) {
*eval = *pdf * bsdf_toon_get_intensity(max_angle, smooth, angle);
#ifdef __RAY_DIFFERENTIALS__
// TODO: find a better approximation for the bounce
*domega_in_dx = (2.0f * dot(sc->N, dIdx)) * sc->N - dIdx;
*domega_in_dy = (2.0f * dot(sc->N, dIdy)) * sc->N - dIdy;
#endif
}
else
*pdf = 0.0f;
}
return LABEL_REFLECT | LABEL_DIFFUSE;
}
/* SPECULAR TOON */
__device int bsdf_specular_toon_setup(ShaderClosure *sc)
{
sc->type = CLOSURE_BSDF_SPECULAR_TOON_ID;
sc->data0 = clamp(sc->data0, 0.0f, 1.0f);
sc->data1 = clamp(sc->data1, 0.0f, 1.0f);
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
__device void bsdf_specular_toon_blur(ShaderClosure *sc, float roughness)
{
}
__device float3 bsdf_specular_toon_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float max_angle = sc->data0*M_PI_2_F;
float smooth = sc->data1*M_PI_2_F;
float cosNI = dot(sc->N, omega_in);
float cosNO = dot(sc->N, I);
if(cosNI > 0 && cosNO > 0) {
/* reflect the view vector */
float3 R = (2 * cosNO) * sc->N - I;
float cosRI = dot(R, omega_in);
float angle = safe_acosf(fmaxf(cosRI, 0.0f));
float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
*pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
return *pdf * eval;
}
return make_float3(0.0f, 0.0f, 0.0f);
}
__device float3 bsdf_specular_toon_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
__device int bsdf_specular_toon_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{
float max_angle = sc->data0*M_PI_2_F;
float smooth = sc->data1*M_PI_2_F;
float cosNO = dot(sc->N, I);
if(cosNO > 0) {
/* reflect the view vector */
float3 R = (2 * cosNO) * sc->N - I;
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
float angle = sample_angle*randu;
sample_uniform_cone(R, sample_angle, randu, randv, omega_in, pdf);
if(dot(Ng, *omega_in) > 0.0f) {
float cosNI = dot(sc->N, *omega_in);
/* make sure the direction we chose is still in the right hemisphere */
if(cosNI > 0) {
*eval = *pdf * bsdf_toon_get_intensity(max_angle, smooth, angle);
#ifdef __RAY_DIFFERENTIALS__
*domega_in_dx = (2 * dot(sc->N, dIdx)) * sc->N - dIdx;
*domega_in_dy = (2 * dot(sc->N, dIdy)) * sc->N - dIdy;
#endif
}
else
*pdf = 0.0f;
}
else
*pdf = 0.0f;
}
return LABEL_GLOSSY | LABEL_REFLECT;
}
CCL_NAMESPACE_END
#endif /* __BSDF_TOON_H__ */

@ -37,6 +37,7 @@
#define __global
#define __shared __shared__
#define __constant
#define __may_alias
/* No assert supported for CUDA */

@ -40,6 +40,7 @@
#define __device
#define __device_inline __device
#define __device_noinline __device __noinline
#define __may_alias
/* no assert in opencl */
#define kernel_assert(cond)

@ -105,6 +105,22 @@ __device_inline void sample_uniform_hemisphere(const float3 N,
*pdf = 0.5f * M_1_PI_F;
}
__device_inline void sample_uniform_cone(const float3 N, float angle,
float randu, float randv,
float3 *omega_in, float *pdf)
{
float z = cosf(angle*randu);
float r = sqrtf(max(0.0f, 1.0f - z*z));
float phi = 2.0f * M_PI_F * randv;
float x = r * cosf(phi);
float y = r * sinf(phi);
float3 T, B;
make_orthonormals (N, &T, &B);
*omega_in = x * T + y * B + z * N;
*pdf = 0.5f * M_1_PI_F / (1.0f - cosf(angle));
}
__device float3 sample_uniform_sphere(float u1, float u2)
{
float z = 1.0f - 2.0f*u1;

@ -20,11 +20,16 @@ CCL_NAMESPACE_BEGIN
enum ObjectTransform {
OBJECT_TRANSFORM = 0,
OBJECT_INVERSE_TRANSFORM = 3,
OBJECT_PROPERTIES = 6,
OBJECT_TRANSFORM_MOTION_PRE = 8,
OBJECT_TRANSFORM_MOTION_POST = 12,
OBJECT_DUPLI = 16
OBJECT_TRANSFORM_MOTION_PRE = 0,
OBJECT_INVERSE_TRANSFORM = 4,
OBJECT_TRANSFORM_MOTION_POST = 4,
OBJECT_PROPERTIES = 8,
OBJECT_DUPLI = 9
};
enum ObjectVectorTransform {
OBJECT_VECTOR_MOTION_PRE = 0,
OBJECT_VECTOR_MOTION_POST = 3
};
__device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, enum ObjectTransform type)
@ -40,6 +45,19 @@ __device_inline Transform object_fetch_transform(KernelGlobals *kg, int object,
return tfm;
}
__device_inline Transform object_fetch_vector_transform(KernelGlobals *kg, int object, enum ObjectVectorTransform type)
{
int offset = object*OBJECT_VECTOR_SIZE + (int)type;
Transform tfm;
tfm.x = kernel_tex_fetch(__objects_vector, offset + 0);
tfm.y = kernel_tex_fetch(__objects_vector, offset + 1);
tfm.z = kernel_tex_fetch(__objects_vector, offset + 2);
tfm.w = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
return tfm;
}
#ifdef __OBJECT_MOTION__
__device_inline Transform object_fetch_transform_motion(KernelGlobals *kg, int object, float time)
{

@ -34,6 +34,7 @@ KERNEL_TEX(uint, texture_uint, __object_node)
/* objects */
KERNEL_TEX(float4, texture_float4, __objects)
KERNEL_TEX(float4, texture_float4, __objects_vector)
/* triangles */
KERNEL_TEX(float4, texture_float4, __tri_normal)

@ -209,10 +209,10 @@ __device float4 triangle_motion_vector(KernelGlobals *kg, ShaderData *sd)
* transformation was set match the world/object space of motion_pre/post */
Transform tfm;
tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM_MOTION_PRE);
tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_PRE);
motion_pre = transform_point(&tfm, motion_pre);
tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM_MOTION_POST);
tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_POST);
motion_post = transform_point(&tfm, motion_post);
float3 P;

@ -29,7 +29,8 @@
CCL_NAMESPACE_BEGIN
/* constants */
#define OBJECT_SIZE 18
#define OBJECT_SIZE 11
#define OBJECT_VECTOR_SIZE 6
#define LIGHT_SIZE 4
#define FILTER_TABLE_SIZE 256
#define RAMP_TABLE_SIZE 256

@ -16,6 +16,7 @@ set(SRC
background.cpp
bsdf_diffuse_ramp.cpp
bsdf_phong_ramp.cpp
bsdf_toon.cpp
emissive.cpp
osl_closures.cpp
osl_services.cpp

@ -0,0 +1,179 @@
/*
* Adapted from Open Shading Language with this license:
*
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
* All Rights Reserved.
*
* Modifications Copyright 2011, Blender Foundation.
*
* 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 the names of its
* 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.
*/
#include <OpenImageIO/fmath.h>
#include <OSL/genclosure.h>
#include "osl_closures.h"
#include "kernel_types.h"
#include "kernel_montecarlo.h"
#include "closure/bsdf_toon.h"
CCL_NAMESPACE_BEGIN
using namespace OSL;
/* DIFFUSE TOON */
class DiffuseToonClosure : public CBSDFClosure {
public:
DiffuseToonClosure() : CBSDFClosure(LABEL_DIFFUSE) {}
size_t memsize() const { return sizeof(*this); }
const char *name() const { return "diffuse_toon"; }
void setup()
{
sc.prim = this;
m_shaderdata_flag = bsdf_diffuse_toon_setup(&sc);
}
bool mergeable(const ClosurePrimitive *other) const
{
return false;
}
void blur(float roughness)
{
bsdf_diffuse_toon_blur(&sc, roughness);
}
void print_on(std::ostream &out) const
{
out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))";
}
float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const
{
return bsdf_diffuse_toon_eval_reflect(&sc, omega_out, omega_in, &pdf);
}
float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const
{
return bsdf_diffuse_toon_eval_transmit(&sc, omega_out, omega_in, &pdf);
}
int sample(const float3 &Ng,
const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy,
float randu, float randv,
float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy,
float &pdf, float3 &eval) const
{
return bsdf_diffuse_toon_sample(&sc, Ng, omega_out, domega_out_dx, domega_out_dy,
randu, randv, &eval, &omega_in, &domega_in_dx, &domega_in_dy, &pdf);
}
};
ClosureParam *closure_bsdf_diffuse_toon_params()
{
static ClosureParam params[] = {
CLOSURE_FLOAT3_PARAM(DiffuseToonClosure, sc.N),
CLOSURE_FLOAT_PARAM(DiffuseToonClosure, sc.data0),
CLOSURE_FLOAT_PARAM(DiffuseToonClosure, sc.data1),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(DiffuseToonClosure)
};
return params;
}
CLOSURE_PREPARE(closure_bsdf_diffuse_toon_prepare, DiffuseToonClosure)
/* SPECULAR TOON */
class SpecularToonClosure : public CBSDFClosure {
public:
SpecularToonClosure() : CBSDFClosure(LABEL_GLOSSY) {}
size_t memsize() const { return sizeof(*this); }
const char *name() const { return "specular_toon"; }
void setup()
{
sc.prim = this;
m_shaderdata_flag = bsdf_specular_toon_setup(&sc);
}
bool mergeable(const ClosurePrimitive *other) const
{
return false;
}
void blur(float roughness)
{
bsdf_specular_toon_blur(&sc, roughness);
}
void print_on(std::ostream &out) const
{
out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))";
}
float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const
{
return bsdf_specular_toon_eval_reflect(&sc, omega_out, omega_in, &pdf);
}
float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const
{
return bsdf_specular_toon_eval_transmit(&sc, omega_out, omega_in, &pdf);
}
int sample(const float3 &Ng,
const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy,
float randu, float randv,
float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy,
float &pdf, float3 &eval) const
{
return bsdf_specular_toon_sample(&sc, Ng, omega_out, domega_out_dx, domega_out_dy,
randu, randv, &eval, &omega_in, &domega_in_dx, &domega_in_dy, &pdf);
}
};
ClosureParam *closure_bsdf_specular_toon_params()
{
static ClosureParam params[] = {
CLOSURE_FLOAT3_PARAM(SpecularToonClosure, sc.N),
CLOSURE_FLOAT_PARAM(SpecularToonClosure, sc.data0),
CLOSURE_FLOAT_PARAM(SpecularToonClosure, sc.data1),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(SpecularToonClosure)
};
return params;
}
CLOSURE_PREPARE(closure_bsdf_specular_toon_prepare, SpecularToonClosure)
CCL_NAMESPACE_END

@ -48,7 +48,6 @@
#include "closure/bsdf_diffuse.h"
#include "closure/bsdf_microfacet.h"
#include "closure/bsdf_oren_nayar.h"
#include "closure/bsdf_phong_ramp.h"
#include "closure/bsdf_reflection.h"
#include "closure/bsdf_refraction.h"
#include "closure/bsdf_transparent.h"
@ -194,10 +193,14 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
closure_holdout_params(), closure_holdout_prepare);
register_closure(ss, "ambient_occlusion", id++,
closure_ambient_occlusion_params(), closure_ambient_occlusion_prepare);
register_closure(ss, "phong_ramp", id++,
closure_bsdf_phong_ramp_params(), closure_bsdf_phong_ramp_prepare);
register_closure(ss, "diffuse_ramp", id++,
closure_bsdf_diffuse_ramp_params(), closure_bsdf_diffuse_ramp_prepare);
register_closure(ss, "phong_ramp", id++,
closure_bsdf_phong_ramp_params(), closure_bsdf_phong_ramp_prepare);
register_closure(ss, "diffuse_toon", id++,
closure_bsdf_diffuse_toon_params(), closure_bsdf_diffuse_toon_prepare);
register_closure(ss, "specular_toon", id++,
closure_bsdf_specular_toon_params(), closure_bsdf_specular_toon_prepare);
}
CCL_NAMESPACE_END

@ -47,15 +47,19 @@ OSL::ClosureParam *closure_emission_params();
OSL::ClosureParam *closure_background_params();
OSL::ClosureParam *closure_holdout_params();
OSL::ClosureParam *closure_ambient_occlusion_params();
OSL::ClosureParam *closure_bsdf_phong_ramp_params();
OSL::ClosureParam *closure_bsdf_diffuse_ramp_params();
OSL::ClosureParam *closure_bsdf_phong_ramp_params();
OSL::ClosureParam *closure_bsdf_diffuse_toon_params();
OSL::ClosureParam *closure_bsdf_specular_toon_params();
void closure_emission_prepare(OSL::RendererServices *, int id, void *data);
void closure_background_prepare(OSL::RendererServices *, int id, void *data);
void closure_holdout_prepare(OSL::RendererServices *, int id, void *data);
void closure_ambient_occlusion_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_diffuse_ramp_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_diffuse_toon_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_specular_toon_prepare(OSL::RendererServices *, int id, void *data);
enum {
AmbientOcclusion = 100

@ -634,11 +634,10 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
{
KernelGlobals *kg = kernel_globals;
ShaderData *sd = (ShaderData *)renderstate;
int object = sd->object;
int tri = sd->prim;
int object, tri;
/* lookup of attribute on another object */
if (object_name != u_empty) {
if (object_name != u_empty || sd == NULL) {
OSLGlobals::ObjectNameMap::iterator it = kg->osl->object_name_map.find(object_name);
if (it == kg->osl->object_name_map.end())
@ -647,8 +646,12 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
object = it->second;
tri = ~0;
}
else if (object == ~0) {
return get_background_attribute(kg, sd, name, type, derivatives, val);
else {
object = sd->object;
tri = sd->prim;
if (object == ~0)
return get_background_attribute(kg, sd, name, type, derivatives, val);
}
/* find attribute on object */

@ -161,7 +161,6 @@ vector cross (vector a, vector b) BUILTIN;
float dot (vector a, vector b) BUILTIN;
float length (vector v) BUILTIN;
float distance (point a, point b) BUILTIN;
float distance (point a, point b, point q) BUILTIN;
normal normalize (normal v) BUILTIN;
vector normalize (vector v) BUILTIN;
vector faceforward (vector N, vector I, vector Nref) BUILTIN;
@ -433,8 +432,10 @@ string concat (string a, string b, string c, string d, string e, string f) {
closure color diffuse(normal N) BUILTIN;
closure color oren_nayar(normal N, float sigma) BUILTIN;
closure color phong_ramp(normal N, float exponent, color colors[8]) BUILTIN;
closure color diffuse_ramp(normal N, color colors[8]) BUILTIN;
closure color phong_ramp(normal N, float exponent, color colors[8]) BUILTIN;
closure color diffuse_toon(normal N, float size, float smooth) BUILTIN;
closure color specular_toon(normal N, float size, float smooth) BUILTIN;
closure color translucent(normal N) BUILTIN;
closure color reflection(normal N) BUILTIN;
closure color refraction(normal N, float eta) BUILTIN;

@ -18,73 +18,6 @@
CCL_NAMESPACE_BEGIN
__device float safe_asinf(float a)
{
if(a <= -1.0f)
return -M_PI_2_F;
else if(a >= 1.0f)
return M_PI_2_F;
return asinf(a);
}
__device float safe_acosf(float a)
{
if(a <= -1.0f)
return M_PI_F;
else if(a >= 1.0f)
return 0.0f;
return acosf(a);
}
__device float compatible_powf(float x, float y)
{
/* GPU pow doesn't accept negative x, do manual checks here */
if(x < 0.0f) {
if(fmod(-y, 2.0f) == 0.0f)
return powf(-x, y);
else
return -powf(-x, y);
}
else if(x == 0.0f)
return 0.0f;
return powf(x, y);
}
__device float safe_powf(float a, float b)
{
if(b == 0.0f)
return 1.0f;
if(a == 0.0f)
return 0.0f;
if(a < 0.0f && b != (int)b)
return 0.0f;
return compatible_powf(a, b);
}
__device float safe_logf(float a, float b)
{
if(a < 0.0f || b < 0.0f)
return 0.0f;
return logf(a)/logf(b);
}
__device float safe_divide(float a, float b)
{
float result;
if(b == 0.0f)
result = 0.0f;
else
result = a/b;
return result;
}
__device float svm_math(NodeMath type, float Fac1, float Fac2)
{
float Fac;

@ -314,6 +314,7 @@ typedef enum ClosureType {
CLOSURE_BSDF_DIFFUSE_ID,
CLOSURE_BSDF_OREN_NAYAR_ID,
CLOSURE_BSDF_DIFFUSE_RAMP_ID,
CLOSURE_BSDF_DIFFUSE_TOON_ID,
CLOSURE_BSDF_GLOSSY_ID,
CLOSURE_BSDF_REFLECTION_ID,
@ -323,6 +324,7 @@ typedef enum ClosureType {
CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
CLOSURE_BSDF_WESTIN_SHEEN_ID,
CLOSURE_BSDF_PHONG_RAMP_ID,
CLOSURE_BSDF_SPECULAR_TOON_ID,
CLOSURE_BSDF_TRANSMISSION_ID,
CLOSURE_BSDF_TRANSLUCENT_ID,

@ -150,12 +150,17 @@ ObjectManager::~ObjectManager()
void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, uint *object_flag, Progress& progress)
{
float4 *objects = dscene->objects.resize(OBJECT_SIZE*scene->objects.size());
float4 *objects;
float4 *objects_vector = NULL;
int i = 0;
map<Mesh*, float> surface_area_map;
Scene::MotionType need_motion = scene->need_motion(device->info.advanced_shading);
bool have_motion = false;
objects = dscene->objects.resize(OBJECT_SIZE*scene->objects.size());
if(need_motion == Scene::MOTION_PASS)
objects_vector = dscene->objects_vector.resize(OBJECT_VECTOR_SIZE*scene->objects.size());
foreach(Object *ob, scene->objects) {
Mesh *mesh = ob->mesh;
uint flag = 0;
@ -205,8 +210,8 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
int offset = i*OBJECT_SIZE;
memcpy(&objects[offset], &tfm, sizeof(float4)*3);
memcpy(&objects[offset+3], &itfm, sizeof(float4)*3);
objects[offset+6] = make_float4(surface_area, pass_id, random_number, __int_as_float(ob->particle_id));
memcpy(&objects[offset+4], &itfm, sizeof(float4)*3);
objects[offset+8] = make_float4(surface_area, pass_id, random_number, __int_as_float(ob->particle_id));
if(need_motion == Scene::MOTION_PASS) {
/* motion transformations, is world/object space depending if mesh
@ -220,8 +225,8 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
if(!mesh->attributes.find(ATTR_STD_MOTION_POST))
mtfm_post = mtfm_post * itfm;
memcpy(&objects[offset+8], &mtfm_pre, sizeof(float4)*4);
memcpy(&objects[offset+12], &mtfm_post, sizeof(float4)*4);
memcpy(&objects_vector[i*OBJECT_VECTOR_SIZE+0], &mtfm_pre, sizeof(float4)*3);
memcpy(&objects_vector[i*OBJECT_VECTOR_SIZE+3], &mtfm_post, sizeof(float4)*3);
}
#ifdef __OBJECT_MOTION__
else if(need_motion == Scene::MOTION_BLUR) {
@ -230,20 +235,16 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
DecompMotionTransform decomp;
transform_motion_decompose(&decomp, &ob->motion, &ob->tfm);
memcpy(&objects[offset+8], &decomp, sizeof(float4)*8);
memcpy(&objects[offset], &decomp, sizeof(float4)*8);
flag |= SD_OBJECT_MOTION;
have_motion = true;
}
else {
float4 no_motion = make_float4(FLT_MAX);
memcpy(&objects[offset+8], &no_motion, sizeof(float4)*8);
}
}
#endif
/* dupli object coords */
objects[offset+16] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f);
objects[offset+17] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f);
objects[offset+9] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f);
objects[offset+10] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f);
/* object flag */
if(ob->use_holdout)
@ -256,6 +257,8 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
}
device->tex_alloc("__objects", dscene->objects);
if(need_motion == Scene::MOTION_PASS)
device->tex_alloc("__objects_vector", dscene->objects_vector);
dscene->data.bvh.have_motion = have_motion;
}
@ -297,6 +300,9 @@ void ObjectManager::device_free(Device *device, DeviceScene *dscene)
device->tex_free(dscene->objects);
dscene->objects.clear();
device->tex_free(dscene->objects_vector);
dscene->objects_vector.clear();
device->tex_free(dscene->object_flag);
dscene->object_flag.clear();
}

@ -74,6 +74,7 @@ public:
/* objects */
device_vector<float4> objects;
device_vector<float4> objects_vector;
/* attributes */
device_vector<uint4> attributes_map;

@ -394,10 +394,10 @@ bool cuLibraryInit()
string cuCompilerPath()
{
#ifdef _WIN32
const char *defaultpath = "C:/CUDA/bin";
const char *defaultpaths[] = {"C:/CUDA/bin", NULL};
const char *executable = "nvcc.exe";
#else
const char *defaultpath = "/usr/local/cuda/bin";
const char *defaultpaths[] = {"/Developer/NVIDIA/CUDA-4.2/bin", "/usr/local/cuda-4.2/bin", "/usr/local/cuda/bin", NULL};
const char *executable = "nvcc";
#endif
@ -405,13 +405,17 @@ string cuCompilerPath()
string nvcc;
if(binpath)
if(binpath) {
nvcc = path_join(binpath, executable);
else
nvcc = path_join(defaultpath, executable);
if(path_exists(nvcc))
return nvcc;
}
if(path_exists(nvcc))
return nvcc;
for(int i = 0; defaultpaths[i]; i++) {
nvcc = path_join(defaultpaths[i], executable);
if(path_exists(nvcc))
return nvcc;
}
#ifndef _WIN32
{

@ -38,7 +38,7 @@ CCL_NAMESPACE_END
#define CUDA_VERSION 3020
#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64)
#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) || defined(__LP64__)
typedef unsigned long long CUdeviceptr;
#else
typedef unsigned int CUdeviceptr;

@ -1092,6 +1092,75 @@ __device_inline float3 rotate_around_axis(float3 p, float3 axis, float angle)
return r;
}
/* NaN-safe math ops */
__device float safe_asinf(float a)
{
if(a <= -1.0f)
return -M_PI_2_F;
else if(a >= 1.0f)
return M_PI_2_F;
return asinf(a);
}
__device float safe_acosf(float a)
{
if(a <= -1.0f)
return M_PI_F;
else if(a >= 1.0f)
return 0.0f;
return acosf(a);
}
__device float compatible_powf(float x, float y)
{
/* GPU pow doesn't accept negative x, do manual checks here */
if(x < 0.0f) {
if(fmod(-y, 2.0f) == 0.0f)
return powf(-x, y);
else
return -powf(-x, y);
}
else if(x == 0.0f)
return 0.0f;
return powf(x, y);
}
__device float safe_powf(float a, float b)
{
if(b == 0.0f)
return 1.0f;
if(a == 0.0f)
return 0.0f;
if(a < 0.0f && b != (int)b)
return 0.0f;
return compatible_powf(a, b);
}
__device float safe_logf(float a, float b)
{
if(a < 0.0f || b < 0.0f)
return 0.0f;
return logf(a)/logf(b);
}
__device float safe_divide(float a, float b)
{
float result;
if(b == 0.0f)
result = 0.0f;
else
result = a/b;
return result;
}
CCL_NAMESPACE_END
#endif /* __UTIL_MATH_H__ */

@ -45,7 +45,7 @@ typedef struct Transform {
*
* For the DecompMotionTransform we drop scale from pre/post. */
typedef struct MotionTransform {
typedef struct __may_alias MotionTransform {
Transform pre;
Transform mid;
Transform post;

@ -39,12 +39,14 @@
#if defined(_WIN32) && !defined(FREE_WINDOWS)
#define __device_inline static __forceinline
#define __align(...) __declspec(align(__VA_ARGS__))
#define __may_alias
#else
#define __device_inline static inline __attribute__((always_inline))
#ifndef FREE_WINDOWS64
#define __forceinline inline __attribute__((always_inline))
#endif
#define __align(...) __attribute__((aligned(__VA_ARGS__)))
#define __may_alias __attribute__((__may_alias__))
#endif
#endif

@ -296,8 +296,6 @@ protected:
/** Multitouch trackpad availability */
bool m_hasMultiTouchTrackpad;
/** Multitouch gesture in progress, useful to distinguish trackpad from mouse scroll events */
bool m_isGestureInProgress;
};
#endif // __GHOST_SYSTEMCOCOA_H__

@ -551,7 +551,6 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
char *rstring = NULL;
m_modifierMask =0;
m_isGestureInProgress = false;
m_cursorDelta_x=0;
m_cursorDelta_y=0;
m_outsideLoopEventProcessed = false;
@ -1580,8 +1579,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
case NSScrollWheel:
{
/* Send trackpad event if inside a trackpad gesture, send wheel event otherwise */
if (!m_hasMultiTouchTrackpad || !m_isGestureInProgress) {
if (!m_hasMultiTouchTrackpad) {
GHOST_TInt32 delta;
double deltaF = [event deltaY];
@ -1641,12 +1639,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000, window, GHOST_kTrackpadEventRotate, x, y,
-[event rotation] * 5.0, 0));
}
case NSEventTypeBeginGesture:
m_isGestureInProgress = true;
break;
case NSEventTypeEndGesture:
m_isGestureInProgress = false;
break;
default:
return GHOST_kFailure;
break;

@ -67,13 +67,13 @@ extern "C" {
}
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa;
- (void)windowWillClose:(NSNotification *)notification;
- (void)windowDidBecomeKey:(NSNotification *)notification;
- (void)windowDidResignKey:(NSNotification *)notification;
- (void)windowDidExpose:(NSNotification *)notification;
- (void)windowDidResize:(NSNotification *)notification;
- (void)windowDidMove:(NSNotification *)notification;
- (void)windowWillMove:(NSNotification *)notification;
- (BOOL)windowShouldClose:(id)sender;
@end
@implementation CocoaWindowDelegate : NSObject
@ -83,11 +83,6 @@ extern "C" {
associatedWindow = winCocoa;
}
- (void)windowWillClose:(NSNotification *)notification
{
systemCocoa->handleWindowEvent(GHOST_kEventWindowClose, associatedWindow);
}
- (void)windowDidBecomeKey:(NSNotification *)notification
{
systemCocoa->handleWindowEvent(GHOST_kEventWindowActivate, associatedWindow);
@ -132,6 +127,14 @@ extern "C" {
wm_draw_update(ghostC);
}*/
}
- (BOOL)windowShouldClose:(id)sender;
{
//Let Blender close the window rather than closing immediately
systemCocoa->handleWindowEvent(GHOST_kEventWindowClose, associatedWindow);
return false;
}
@end
#pragma mark NSWindow subclass
@ -571,8 +574,6 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
[m_window setContentView:m_openGLView];
[m_window setInitialFirstResponder:m_openGLView];
[m_window setReleasedWhenClosed:NO]; //To avoid bad pointer exception in case of user closing the window
[m_window makeKeyAndOrderFront:nil];
setDrawingContextType(type);
@ -616,11 +617,6 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa()
[m_openGLView release];
if (m_window) {
// previously we called [m_window release], but on 10.8 this does not
// remove the window from [NSApp orderedWindows] and perhaps other
// places, leading to crashes. so instead we set setReleasedWhenClosed
// back to YES right before closing
[m_window setReleasedWhenClosed:YES];
[m_window close];
}
@ -955,7 +951,6 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
//Copy current window parameters
[tmpWindow setTitle:[m_window title]];
[tmpWindow setRepresentedFilename:[m_window representedFilename]];
[tmpWindow setReleasedWhenClosed:NO];
[tmpWindow setAcceptsMouseMovedEvents:YES];
[tmpWindow setDelegate:[m_window delegate]];
[tmpWindow setSystemAndWindowCocoa:[m_window systemCocoa] windowCocoa:this];
@ -1013,7 +1008,6 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
//Copy current window parameters
[tmpWindow setTitle:[m_window title]];
[tmpWindow setRepresentedFilename:[m_window representedFilename]];
[tmpWindow setReleasedWhenClosed:NO];
[tmpWindow setAcceptsMouseMovedEvents:YES];
[tmpWindow setDelegate:[m_window delegate]];
[tmpWindow setSystemAndWindowCocoa:[m_window systemCocoa] windowCocoa:this];

@ -1,4 +1,5 @@
#!/bin/sh
# This script updates icons from the SVG file
inkscape blender_icons.svg --without-gui --export-png=blender_icons.png
inkscape blender_icons.svg --export-dpi=90 --without-gui --export-png=blender_icons16.png
inkscape blender_icons.svg --export-dpi=180 --without-gui --export-png=blender_icons32.png

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 4.5 MiB

After

Width:  |  Height:  |  Size: 3.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 216 KiB

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 539 KiB

After

Width:  |  Height:  |  Size: 562 KiB

@ -29,7 +29,7 @@ __all__ = (
)
import bpy as _bpy
_user_preferences = _bpy.context.user_preferences
error_duplicates = False
error_encoding = False
@ -201,7 +201,7 @@ def check(module_name):
:rtype: tuple of booleans
"""
import sys
loaded_default = module_name in _bpy.context.user_preferences.addons
loaded_default = module_name in _user_preferences.addons
mod = sys.modules.get(module_name)
loaded_state = mod and getattr(mod, "__addon_enabled__", Ellipsis)
@ -232,6 +232,7 @@ def enable(module_name, default_set=True, persistent=False):
import os
import sys
from bpy_restrict_state import RestrictBlend
def handle_error():
import traceback
@ -259,34 +260,38 @@ def enable(module_name, default_set=True, persistent=False):
# Split registering up into 3 steps so we can undo
# if it fails par way through.
# 1) try import
try:
mod = __import__(module_name)
mod.__time__ = os.path.getmtime(mod.__file__)
mod.__addon_enabled__ = False
except:
handle_error()
return None
# disable the context, using the context at all is
# really bad while loading an addon, don't do it!
with RestrictBlend():
# 2) try register collected modules
# removed, addons need to handle own registration now.
# 1) try import
try:
mod = __import__(module_name)
mod.__time__ = os.path.getmtime(mod.__file__)
mod.__addon_enabled__ = False
except:
handle_error()
return None
# 3) try run the modules register function
try:
mod.register()
except:
print("Exception in module register(): %r" %
getattr(mod, "__file__", module_name))
handle_error()
del sys.modules[module_name]
return None
# 2) try register collected modules
# removed, addons need to handle own registration now.
# 3) try run the modules register function
try:
mod.register()
except:
print("Exception in module register(): %r" %
getattr(mod, "__file__", module_name))
handle_error()
del sys.modules[module_name]
return None
# * OK loaded successfully! *
if default_set:
# just in case its enabled already
ext = _bpy.context.user_preferences.addons.get(module_name)
ext = _user_preferences.addons.get(module_name)
if not ext:
ext = _bpy.context.user_preferences.addons.new()
ext = _user_preferences.addons.new()
ext.module = module_name
mod.__addon_enabled__ = True
@ -327,7 +332,7 @@ def disable(module_name, default_set=True):
(module_name, "disabled" if mod is None else "loaded"))
# could be in more then once, unlikely but better do this just in case.
addons = _bpy.context.user_preferences.addons
addons = _user_preferences.addons
if default_set:
while module_name in addons:

@ -57,6 +57,7 @@ import sys as _sys
import addon_utils as _addon_utils
_user_preferences = _bpy.context.user_preferences
_script_module_dirs = "startup", "modules"
@ -132,8 +133,6 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
"""
use_time = _bpy.app.debug_python
prefs = _bpy.context.user_preferences
if use_time:
import time
t_main = time.time()
@ -150,7 +149,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
# to reload. note that they will only actually reload of the
# modification time changes. This `won't` work for packages so...
# its not perfect.
for module_name in [ext.module for ext in prefs.addons]:
for module_name in [ext.module for ext in _user_preferences.addons]:
_addon_utils.disable(module_name, default_set=False)
def register_module_call(mod):
@ -218,24 +217,27 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
del _global_loaded_modules[:]
for base_path in script_paths():
for path_subdir in _script_module_dirs:
path = _os.path.join(base_path, path_subdir)
if _os.path.isdir(path):
_sys_path_ensure(path)
from bpy_restrict_state import RestrictBlend
# only add this to sys.modules, don't run
if path_subdir == "modules":
continue
with RestrictBlend():
for base_path in script_paths():
for path_subdir in _script_module_dirs:
path = _os.path.join(base_path, path_subdir)
if _os.path.isdir(path):
_sys_path_ensure(path)
for mod in modules_from_path(path, loaded_modules):
test_register(mod)
# only add this to sys.modules, don't run
if path_subdir == "modules":
continue
for mod in modules_from_path(path, loaded_modules):
test_register(mod)
# deal with addons separately
_addon_utils.reset_all(reload_scripts)
# run the active integration preset
filepath = preset_find(prefs.inputs.active_keyconfig, "keyconfig")
filepath = preset_find(_user_preferences.inputs.active_keyconfig, "keyconfig")
if filepath:
keyconfig_set(filepath)
@ -264,7 +266,7 @@ def script_path_user():
def script_path_pref():
"""returns the user preference or None"""
path = _bpy.context.user_preferences.filepaths.script_directory
path = _user_preferences.filepaths.script_directory
return _os.path.normpath(path) if path else None

@ -0,0 +1,57 @@
# ##### 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.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8-80 compliant>
"""
This module contains RestrictBlend context manager.
"""
__all__ = (
"RestrictBlend",
)
import bpy as _bpy
class _RestrictContext():
__slots__ = ()
_real_data = _bpy.data
@property
def window_manager(self):
return self._real_data.window_managers[0]
class _RestrictData():
__slots__ = ()
_context_restrict = _RestrictContext()
_data_restrict = _RestrictData()
class RestrictBlend():
__slots__ = ("context", "data")
def __enter__(self):
self.data = _bpy.data
self.context = _bpy.context
_bpy.data = _data_restrict
_bpy.context = _context_restrict
def __exit__(self, type, value, traceback):
_bpy.data = self.data
_bpy.context = self.context

@ -484,6 +484,15 @@ class Text(bpy_types.ID):
if cont.type == 'PYTHON']
)
class NodeSocket(StructRNA): # , metaclass=RNAMeta
__slots__ = ()
@property
def links(self):
"""List of node links from or to this socket"""
return tuple(link for link in self.id_data.links if link.from_socket == self or link.to_socket == self)
# values are module: [(cls, path, line), ...]
TypeMap = {}

@ -170,6 +170,8 @@ class BONE_PT_relations(BoneButtonsPanel, Panel):
if ob and pchan:
col.label(text="Bone Group:")
col.prop_search(pchan, "bone_group", ob.pose, "bone_groups", text="")
col.label(text="Object Children:")
col.prop(bone, "use_relative_parent")
col = split.column()
col.label(text="Parent:")
@ -181,11 +183,11 @@ class BONE_PT_relations(BoneButtonsPanel, Panel):
sub = col.column()
sub.active = (bone.parent is not None)
sub.prop(bone, "use_connect")
sub.prop(bone, "use_inherit_rotation", text="Inherit Rotation")
sub.prop(bone, "use_inherit_scale", text="Inherit Scale")
sub.prop(bone, "use_inherit_rotation")
sub.prop(bone, "use_inherit_scale")
sub = col.column()
sub.active = (not bone.parent or not bone.use_connect)
sub.prop(bone, "use_local_location", text="Local Location")
sub.prop(bone, "use_local_location")
class BONE_PT_display(BoneButtonsPanel, Panel):

@ -1,4 +1,5 @@
# ##### 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
@ -544,7 +545,7 @@ class RENDER_PT_bake(RenderButtonsPanel, Panel):
if rd.bake_type == 'AO':
col = split.column()
col.prop(rd, "bake_bias")
col.prop(rd, "bake_rays_number")
col.prop(rd, "bake_samples")
if __name__ == "__main__": # only for live edit.

@ -66,6 +66,7 @@ class TEXT_HT_header(Header):
row.operator("text.run_script")
row = layout.row()
row.active = text.name.endswith(".py")
row.prop(text, "use_module")
row = layout.row()

@ -686,6 +686,28 @@ class USERPREF_PT_theme(Panel):
col.separator()
ui = theme.user_interface
col.label("Menu Shadow:")
row = col.row()
subsplit = row.split(percentage=0.95)
padding = subsplit.split(percentage=0.15)
colsub = padding.column()
colsub = padding.column()
colsub.row().prop(ui, "menu_shadow_fac")
subsplit = row.split(percentage=0.85)
padding = subsplit.split(percentage=0.15)
colsub = padding.column()
colsub = padding.column()
colsub.row().prop(ui, "menu_shadow_width")
col.separator()
col.separator()
col.label("Icons:")
row = col.row()

@ -971,6 +971,7 @@ class VIEW3D_PT_tools_weightpaint(View3DPanel, Panel):
col.operator("object.vertex_group_transfer_weight", text="Transfer Weights")
col.operator("object.vertex_group_limit_total", text="Limit Total")
col.operator("object.vertex_group_fix", text="Fix Deforms")
col.operator("paint.weight_gradient")
class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):

@ -2,7 +2,7 @@ bl_info = {
"name": "New Object",
"author": "Your Name Here",
"version": (1, 0),
"blender": (2, 5, 5),
"blender": (2, 65, 0),
"location": "View3D > Add > Mesh > New Object",
"description": "Adds a new Mesh Object",
"warning": "",

@ -42,20 +42,22 @@ class ModalDrawOperator(bpy.types.Operator):
self.mouse_path.append((event.mouse_region_x, event.mouse_region_y))
elif event.type == 'LEFTMOUSE':
context.region.callback_remove(self._handle)
bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
return {'FINISHED'}
elif event.type in {'RIGHTMOUSE', 'ESC'}:
context.region.callback_remove(self._handle)
bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
return {'CANCELLED'}
return {'RUNNING_MODAL'}
def invoke(self, context, event):
if context.area.type == 'VIEW_3D':
# the arguments we pass the the callback
args = (self, context)
# Add the region OpenGL drawing callback
# draw in view space with 'POST_VIEW' and 'PRE_VIEW'
self._handle = context.region.callback_add(draw_callback_px, (self, context), 'POST_PIXEL')
self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, args, 'WINDOW', 'POST_PIXEL')
self.mouse_path = []

@ -49,7 +49,7 @@
#ifdef __BIG_ENDIAN__
/* copied from BLI_endian_switch_inline.h */
static void invert(int *num)
static void invert(int *val)
{
int tval = *val;
*val = ((tval >> 24)) |

@ -50,7 +50,7 @@ extern "C" {
/* used by packaging tools */
/* can be left blank, otherwise a,b,c... etc with no quotes */
#define BLENDER_VERSION_CHAR
#define BLENDER_VERSION_CHAR a
/* alpha/beta/rc/release, docs use this */
#define BLENDER_VERSION_CYCLE alpha

@ -185,6 +185,7 @@ enum {
PointerRNA CTX_data_pointer_get(const bContext *C, const char *member);
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type);
ListBase CTX_data_collection_get(const bContext *C, const char *member);
ListBase CTX_data_dir_get_ex(const bContext *C, const short use_store, const short use_rna, const short use_all);
ListBase CTX_data_dir_get(const bContext *C);
int CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb, short *r_type);

@ -114,7 +114,7 @@ typedef struct Global {
#define G_BACKBUFSEL (1 << 4)
#define G_PICKSEL (1 << 5)
/* #define G_FACESELECT (1 << 8) use (mesh->editflag & ME_EDIT_PAINT_MASK) */
/* #define G_FACESELECT (1 << 8) use (mesh->editflag & ME_EDIT_PAINT_FACE_SEL) */
#define G_SCRIPT_AUTOEXEC (1 << 13)
#define G_SCRIPT_OVERRIDE_PREF (1 << 14) /* when this flag is set ignore the userprefs */

@ -123,6 +123,17 @@ void BKE_mesh_flush_hidden_from_verts(const struct MVert *mvert,
struct MEdge *medge, int totedge,
struct MPoly *mpoly, int totpoly);
void BKE_mesh_flush_select_from_polys_ex(struct MVert *mvert, const int totvert,
struct MLoop *mloop,
struct MEdge *medge, const int totedge,
const struct MPoly *mpoly, const int totpoly);
void BKE_mesh_flush_select_from_polys(struct Mesh *me);
void BKE_mesh_flush_select_from_verts_ex(const struct MVert *mvert, const int totvert,
struct MLoop *mloop,
struct MEdge *medge, const int totedge,
struct MPoly *mpoly, const int totpoly);
void BKE_mesh_flush_select_from_verts(struct Mesh *me);
void BKE_mesh_unlink(struct Mesh *me);
void BKE_mesh_free(struct Mesh *me, int unlink);
struct Mesh *BKE_mesh_add(const char *name);
@ -132,7 +143,7 @@ void mesh_update_customdata_pointers(struct Mesh *me, const short do_ensure_tess
void BKE_mesh_make_local(struct Mesh *me);
void BKE_mesh_boundbox_calc(struct Mesh *me, float r_loc[3], float r_size[3]);
void BKE_mesh_texspace_calc(struct Mesh *me);
float *BKE_mesh_orco_verts_get(struct Object *ob);
float (*BKE_mesh_orco_verts_get(struct Object *ob))[3];
void BKE_mesh_orco_verts_transform(struct Mesh *me, float (*orco)[3], int totvert, int invert);
int test_index_face(struct MFace *mface, struct CustomData *mfdata, int mfindex, int nr);
struct Mesh *BKE_mesh_from_object(struct Object *ob);
@ -152,7 +163,7 @@ void BKE_mesh_from_nurbs_displist(struct Object *ob, struct ListBase *dispbase,
int **orco_index_ptr);
void BKE_mesh_from_curve(struct Scene *scene, struct Object *ob);
void free_dverts(struct MDeformVert *dvert, int totvert);
void copy_dverts(struct MDeformVert *dst, struct MDeformVert *src, int totvert); /* __NLA */
void copy_dverts(struct MDeformVert *dst, const struct MDeformVert *src, int totvert);
void BKE_mesh_delete_material_index(struct Mesh *me, short index);
void BKE_mesh_smooth_flag_set(struct Object *meshOb, int enableSmooth);
void BKE_mesh_convert_mfaces_to_mpolys(struct Mesh *mesh);

@ -857,30 +857,27 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob,
return dm;
}
static float *get_editbmesh_orco_verts(BMEditMesh *em)
static float (*get_editbmesh_orco_verts(BMEditMesh *em))[3]
{
BMIter iter;
BMVert *eve;
float *orco;
int a, totvert;
float (*orco)[3];
int i;
/* these may not really be the orco's, but it's only for preview.
* could be solver better once, but isn't simple */
totvert = em->bm->totvert;
orco = MEM_mallocN(sizeof(float) * 3 * totvert, "BMEditMesh Orco");
orco = MEM_mallocN(sizeof(float) * 3 * em->bm->totvert, "BMEditMesh Orco");
eve = BM_iter_new(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
for (a = 0; eve; eve = BM_iter_step(&iter), a += 3) {
copy_v3_v3(orco + a, eve->co);
BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
copy_v3_v3(orco[i], eve->co);
}
return orco;
}
/* orco custom data layer */
static void *get_orco_coords_dm(Object *ob, BMEditMesh *em, int layer, int *free)
static float (*get_orco_coords_dm(Object *ob, BMEditMesh *em, int layer, int *free))[3]
{
*free = 0;
@ -889,9 +886,9 @@ static void *get_orco_coords_dm(Object *ob, BMEditMesh *em, int layer, int *free
*free = 1;
if (em)
return (float(*)[3])get_editbmesh_orco_verts(em);
return get_editbmesh_orco_verts(em);
else
return (float(*)[3])BKE_mesh_orco_verts_get(ob);
return BKE_mesh_orco_verts_get(ob);
}
else if (layer == CD_CLOTH_ORCO) {
/* apply shape key for cloth, this should really be solved
@ -1815,17 +1812,18 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
BLI_linklist_free((LinkNode *)datamasks, NULL);
}
float (*editbmesh_get_vertex_cos(BMEditMesh * em, int *numVerts_r))[3]
float (*editbmesh_get_vertex_cos(BMEditMesh *em, int *numVerts_r))[3]
{
int i, numVerts = *numVerts_r = em->bm->totvert;
float (*cos)[3];
BMIter iter;
BMVert *eve;
float (*cos)[3];
int i;
cos = MEM_mallocN(sizeof(float) * 3 * numVerts, "vertexcos");
*numVerts_r = em->bm->totvert;
eve = BM_iter_new(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
for (i = 0; eve; eve = BM_iter_step(&iter), i++) {
cos = MEM_mallocN(sizeof(float) * 3 * em->bm->totvert, "vertexcos");
BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
copy_v3_v3(cos[i], eve->co);
}

@ -25,7 +25,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/blenlib/intern/bpath.c
/** \file blender/blenkernel/intern/bpath.c
* \ingroup bli
*/

@ -1875,7 +1875,7 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, int use_mdisps,
bm->totface);
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
BMIter iter, liter;
BMIter iter;
BMVert *eve;
BMEdge *eed;
BMFace *efa;
@ -1913,7 +1913,7 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, int use_mdisps,
CD_CALLOC, dm->numLoopData);
CustomData_merge(&bm->pdata, &dm->polyData, mask,
CD_CALLOC, dm->numPolyData);
/* add tessellation mface layers */
if (use_tessface) {
CustomData_from_bmeshpoly(&dm->faceData, &dm->polyData, &dm->loopData, em_tottri);
@ -2002,7 +2002,8 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, int use_mdisps,
j = 0;
efa = BM_iter_new(&iter, bm, BM_FACES_OF_MESH, NULL);
for (i = 0; efa; i++, efa = BM_iter_step(&iter), index++) {
BMLoop *l;
BMLoop *l_iter;
BMLoop *l_first;
MPoly *mp = &mpoly[i];
BM_elem_index_set(efa, i); /* set_inline */
@ -2011,15 +2012,16 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, int use_mdisps,
mp->flag = BM_face_flag_to_mflag(efa);
mp->loopstart = j;
mp->mat_nr = efa->mat_nr;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
mloop->v = BM_elem_index_get(l->v);
mloop->e = BM_elem_index_get(l->e);
CustomData_from_bmesh_block(&bm->ldata, &dm->loopData, l->head.data, j);
l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
do {
mloop->v = BM_elem_index_get(l_iter->v);
mloop->e = BM_elem_index_get(l_iter->e);
CustomData_from_bmesh_block(&bm->ldata, &dm->loopData, l_iter->head.data, j);
j++;
mloop++;
}
} while ((l_iter = l_iter->next) != l_first);
CustomData_from_bmesh_block(&bm->pdata, &dm->polyData, efa->head.data, i);

@ -427,11 +427,11 @@ int CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListB
return ret;
}
static void data_dir_add(ListBase *lb, const char *member)
static void data_dir_add(ListBase *lb, const char *member, const short use_all)
{
LinkData *link;
if (strcmp(member, "scene") == 0) /* exception */
if ((use_all == FALSE) && strcmp(member, "scene") == 0) /* exception */
return;
if (BLI_findstring(lb, member, offsetof(LinkData, data)))
@ -442,7 +442,13 @@ static void data_dir_add(ListBase *lb, const char *member)
BLI_addtail(lb, link);
}
ListBase CTX_data_dir_get(const bContext *C)
/**
* \param C Context
* \param use_store Use 'C->wm.store'
* \param use_rna Use Include the properties from 'RNA_Context'
* \param use_all Don't skip values (currently only "scene")
*/
ListBase CTX_data_dir_get_ex(const bContext *C, const short use_store, const short use_rna, const short use_all)
{
bContextDataResult result;
ListBase lb;
@ -453,11 +459,33 @@ ListBase CTX_data_dir_get(const bContext *C)
memset(&lb, 0, sizeof(lb));
if (C->wm.store) {
if (use_rna) {
char name[256], *nameptr;
int namelen;
PropertyRNA *iterprop;
PointerRNA ctx_ptr;
RNA_pointer_create(NULL, &RNA_Context, (void *)C, &ctx_ptr);
iterprop = RNA_struct_iterator_property(ctx_ptr.type);
RNA_PROP_BEGIN (&ctx_ptr, itemptr, iterprop)
{
nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen);
data_dir_add(&lb, name, use_all);
if (nameptr) {
if (name != nameptr) {
MEM_freeN(nameptr);
}
}
}
RNA_PROP_END;
}
if (use_store && C->wm.store) {
bContextStoreEntry *entry;
for (entry = C->wm.store->entries.first; entry; entry = entry->next)
data_dir_add(&lb, entry->name);
data_dir_add(&lb, entry->name, use_all);
}
if ((ar = CTX_wm_region(C)) && ar->type && ar->type->context) {
memset(&result, 0, sizeof(result));
@ -465,7 +493,7 @@ ListBase CTX_data_dir_get(const bContext *C)
if (result.dir)
for (a = 0; result.dir[a]; a++)
data_dir_add(&lb, result.dir[a]);
data_dir_add(&lb, result.dir[a], use_all);
}
if ((sa = CTX_wm_area(C)) && sa->type && sa->type->context) {
memset(&result, 0, sizeof(result));
@ -473,7 +501,7 @@ ListBase CTX_data_dir_get(const bContext *C)
if (result.dir)
for (a = 0; result.dir[a]; a++)
data_dir_add(&lb, result.dir[a]);
data_dir_add(&lb, result.dir[a], use_all);
}
if ((sc = CTX_wm_screen(C)) && sc->context) {
bContextDataCallback cb = sc->context;
@ -482,12 +510,17 @@ ListBase CTX_data_dir_get(const bContext *C)
if (result.dir)
for (a = 0; result.dir[a]; a++)
data_dir_add(&lb, result.dir[a]);
data_dir_add(&lb, result.dir[a], use_all);
}
return lb;
}
ListBase CTX_data_dir_get(const bContext *C)
{
return CTX_data_dir_get_ex(C, TRUE, FALSE, FALSE);
}
int CTX_data_equals(const char *member, const char *str)
{
return (strcmp(member, str) == 0);

@ -687,7 +687,7 @@ static void boundInsert(Bounds3D *b, float point[3])
static float getSurfaceDimension(PaintSurfaceData *sData)
{
Bounds3D *mb = &sData->bData->mesh_bounds;
return MAX3((mb->max[0] - mb->min[0]), (mb->max[1] - mb->min[1]), (mb->max[2] - mb->min[2]));
return max_fff((mb->max[0] - mb->min[0]), (mb->max[1] - mb->min[1]), (mb->max[2] - mb->min[2]));
}
static void freeGrid(PaintSurfaceData *data)
@ -754,14 +754,14 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
/* get dimensions */
sub_v3_v3v3(dim, grid->grid_bounds.max, grid->grid_bounds.min);
copy_v3_v3(td, dim);
min_dim = MAX3(td[0], td[1], td[2]) / 1000.f;
min_dim = max_fff(td[0], td[1], td[2]) / 1000.f;
/* deactivate zero axises */
for (i = 0; i < 3; i++) {
if (td[i] < min_dim) { td[i] = 1.0f; axis -= 1; }
}
if (axis == 0 || MAX3(td[0], td[1], td[2]) < 0.0001f) {
if (axis == 0 || max_fff(td[0], td[1], td[2]) < 0.0001f) {
MEM_freeN(grid_bounds);
MEM_freeN(bData->grid);
bData->grid = NULL;
@ -4260,7 +4260,7 @@ static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *s
if (surface->effect & MOD_DPAINT_EFFECT_DO_SHRINK)
shrink_speed = surface->shrink_speed;
fastest_effect = MAX3(spread_speed, shrink_speed, average_force);
fastest_effect = max_fff(spread_speed, shrink_speed, average_force);
avg_dist = bData->average_dist * CANVAS_REL_SIZE / getSurfaceDimension(sData);
steps = (int)ceil(1.5f * EFF_MOVEMENT_PER_FRAME * fastest_effect / avg_dist * timescale);
@ -4444,8 +4444,7 @@ static void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescal
float dt, min_dist, damp_factor;
float wave_speed = surface->wave_speed;
double average_dist = 0.0f;
Bounds3D *mb = &sData->bData->mesh_bounds;
float canvas_size = MAX3((mb->max[0] - mb->min[0]), (mb->max[1] - mb->min[1]), (mb->max[2] - mb->min[2]));
const float canvas_size = getSurfaceDimension(sData);
float wave_scale = CANVAS_REL_SIZE / canvas_size;
/* allocate memory */

@ -115,10 +115,10 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em)
BMesh *bm = em->bm;
BMLoop *(*looptris)[3] = NULL;
BLI_array_declare(looptris);
BMIter iter, liter;
BMIter iter;
BMFace *efa;
BMLoop *l;
int i = 0, j;
int i = 0;
ScanFillContext sf_ctx;
@ -161,16 +161,29 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em)
/* no need to ensure the loop order, we know its ok */
else if (efa->len == 3) {
#if 0
int j;
BLI_array_grow_one(looptris);
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) {
looptris[i][j] = l;
}
i += 1;
#else
/* more cryptic but faster */
BLI_array_grow_one(looptris);
{
BMLoop **l_ptr = looptris[i++];
l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa);
l_ptr[1] = l = l->next;
l_ptr[2] = l->next;
}
#endif
}
else if (efa->len == 4) {
#if 0
BMLoop *ltmp[4];
int j;
BLI_array_grow_items(looptris, 2);
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) {
ltmp[j] = l;
}
@ -184,11 +197,27 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em)
looptris[i][1] = ltmp[2];
looptris[i][2] = ltmp[3];
i += 1;
#else
/* more cryptic but faster */
BLI_array_grow_items(looptris, 2);
{
BMLoop **l_ptr_a = looptris[i++];
BMLoop **l_ptr_b = looptris[i++];
(l_ptr_a[0] = l_ptr_b[0] = l = BM_FACE_FIRST_LOOP(efa));
(l_ptr_a[1] = l = l->next);
(l_ptr_a[2] = l_ptr_b[1] = l = l->next);
( l_ptr_b[2] = l->next);
}
#endif
}
#endif /* USE_TESSFACE_SPEEDUP */
else {
int j;
BMLoop *l_iter;
BMLoop *l_first;
ScanFillVert *sf_vert, *sf_vert_last = NULL, *sf_vert_first = NULL;
/* ScanFillEdge *e; */ /* UNUSED */
ScanFillFace *sf_tri;
@ -197,20 +226,25 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *em)
BLI_scanfill_begin(&sf_ctx);
/* scanfill time */
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) {
/*mark order */
BM_elem_index_set(l, j); /* set_loop */
sf_vert = BLI_scanfill_vert_add(&sf_ctx, l->v->co);
sf_vert->tmp.p = l;
j = 0;
l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
do {
sf_vert = BLI_scanfill_vert_add(&sf_ctx, l_iter->v->co);
sf_vert->tmp.p = l_iter;
if (sf_vert_last) {
/* e = */ BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
}
sf_vert_last = sf_vert;
if (sf_vert_first == NULL) sf_vert_first = sf_vert;
}
if (sf_vert_first == NULL) {
sf_vert_first = sf_vert;
}
/*mark order */
BM_elem_index_set(l_iter, j++); /* set_loop */
} while ((l_iter = l_iter->next) != l_first);
/* complete the loop */
BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);

@ -500,8 +500,8 @@ short calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, flo
BLI_assert(bezt_last != NULL);
if (include_handles) {
xminv = MIN3(xminv, bezt_first->vec[0][0], bezt_first->vec[1][0]);
xmaxv = MAX3(xmaxv, bezt_last->vec[1][0], bezt_last->vec[2][0]);
xminv = min_fff(xminv, bezt_first->vec[0][0], bezt_first->vec[1][0]);
xmaxv = max_fff(xmaxv, bezt_last->vec[1][0], bezt_last->vec[2][0]);
}
else {
xminv = min_ff(xminv, bezt_first->vec[1][0]);
@ -517,8 +517,8 @@ short calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, flo
for (bezt = fcu->bezt, i = 0; i < fcu->totvert; bezt++, i++) {
if ((do_sel_only == FALSE) || BEZSELECTED(bezt)) {
if (include_handles) {
yminv = MIN4(yminv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]);
ymaxv = MAX4(ymaxv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]);
yminv = min_ffff(yminv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]);
ymaxv = max_ffff(ymaxv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]);
}
else {
yminv = min_ff(yminv, bezt->vec[1][1]);

@ -188,7 +188,7 @@ bGPDlayer *gpencil_layer_addnew(bGPdata *gpd, const char *name, int setactive)
/* make this one the active one */
if (setactive)
gpencil_layer_setactive(gpd, gpl);
gpencil_layer_setactive(gpd, gpl);
/* return layer */
return gpl;

@ -937,7 +937,7 @@ int BKE_imtype_to_ftype(const char imtype)
return RADHDR;
#endif
else if (imtype == R_IMF_IMTYPE_PNG)
return PNG;
return PNG | 90;
#ifdef WITH_DDS
else if (imtype == R_IMF_IMTYPE_DDS)
return DDS;

@ -158,8 +158,10 @@ void id_lib_extern(ID *id)
/* ensure we have a real user */
void id_us_ensure_real(ID *id)
{
if (ID_REAL_USERS(id) <= 0) {
id->us = MAX2(id->us, 0) + 1;
if (id) {
if (ID_REAL_USERS(id) <= 0) {
id->us = MAX2(id->us, 0) + 1;
}
}
}

@ -1514,7 +1514,7 @@ static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a)
float in_v /*, out_v*/;
float workp[3];
float dvec[3];
float tmp_v, workp_v, max_len, len, nx, ny, nz, MAXN;
float tmp_v, workp_v, max_len, nx, ny, nz, max_dim;
calc_mballco(ml, in);
in_v = mbproc->function(in[0], in[1], in[2]);
@ -1573,17 +1573,17 @@ static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a)
ny = abs((out[1] - in[1]) / mbproc->size);
nz = abs((out[2] - in[2]) / mbproc->size);
MAXN = MAX3(nx, ny, nz);
if (MAXN != 0.0f) {
dvec[0] = (out[0] - in[0]) / MAXN;
dvec[1] = (out[1] - in[1]) / MAXN;
dvec[2] = (out[2] - in[2]) / MAXN;
max_dim = max_fff(nx, ny, nz);
if (max_dim != 0.0f) {
float len = 0.0f;
dvec[0] = (out[0] - in[0]) / max_dim;
dvec[1] = (out[1] - in[1]) / max_dim;
dvec[2] = (out[2] - in[2]) / max_dim;
len = 0.0;
while (len <= max_len) {
workp[0] += dvec[0];
workp[1] += dvec[1];
workp[2] += dvec[2];
add_v3_v3(workp, dvec);
/* compute value of implicite function */
tmp_v = mbproc->function(workp[0], workp[1], workp[2]);
/* add cube to the stack, when value of implicite function crosses zero value */

@ -430,7 +430,7 @@ void BKE_mesh_free(Mesh *me, int unlink)
if (me->edit_btmesh) MEM_freeN(me->edit_btmesh);
}
void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount)
void copy_dverts(MDeformVert *dst, const MDeformVert *src, int copycount)
{
/* Assumes dst is already set up */
int i;
@ -442,7 +442,7 @@ void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount)
for (i = 0; i < copycount; i++) {
if (src[i].dw) {
dst[i].dw = MEM_callocN(sizeof(MDeformWeight) * src[i].totweight, "copy_deformWeight");
dst[i].dw = MEM_mallocN(sizeof(MDeformWeight) * src[i].totweight, "copy_deformWeight");
memcpy(dst[i].dw, src[i].dw, sizeof(MDeformWeight) * src[i].totweight);
}
}
@ -731,7 +731,7 @@ void BKE_mesh_texspace_get(Mesh *me, float r_loc[3], float r_rot[3], float r_siz
if (r_size) copy_v3_v3(r_size, me->size);
}
float *BKE_mesh_orco_verts_get(Object *ob)
float (*BKE_mesh_orco_verts_get(Object *ob))[3]
{
Mesh *me = ob->data;
MVert *mvert = NULL;
@ -748,7 +748,7 @@ float *BKE_mesh_orco_verts_get(Object *ob)
copy_v3_v3(vcos[a], mvert->co);
}
return (float *)vcos;
return vcos;
}
void BKE_mesh_orco_verts_transform(Mesh *me, float (*orco)[3], int totvert, int invert)
@ -3107,6 +3107,107 @@ void BKE_mesh_flush_hidden_from_verts(const MVert *mvert,
}
}
/**
* simple poly -> vert/edge selection.
*/
void BKE_mesh_flush_select_from_polys_ex(MVert *mvert, const int totvert,
MLoop *mloop,
MEdge *medge, const int totedge,
const MPoly *mpoly, const int totpoly)
{
MVert *mv;
MEdge *med;
const MPoly *mp;
int i;
i = totvert;
for (mv = mvert; i--; mv++) {
mv->flag &= ~SELECT;
}
i = totedge;
for (med = medge; i--; med++) {
med->flag &= ~SELECT;
}
i = totpoly;
for (mp = mpoly; i--; mp++) {
/* assume if its selected its not hidden and none of its verts/edges are hidden
* (a common assumption)*/
if (mp->flag & ME_FACE_SEL) {
MLoop *ml;
int j;
j = mp->totloop;
for (ml = &mloop[mp->loopstart]; j--; ml++) {
mvert[ml->v].flag |= SELECT;
medge[ml->e].flag |= SELECT;
}
}
}
}
void BKE_mesh_flush_select_from_polys(Mesh *me)
{
BKE_mesh_flush_select_from_polys_ex(me->mvert, me->totvert,
me->mloop,
me->medge, me->totedge,
me->mpoly, me->totpoly);
}
void BKE_mesh_flush_select_from_verts_ex(const MVert *mvert, const int UNUSED(totvert),
MLoop *mloop,
MEdge *medge, const int totedge,
MPoly *mpoly, const int totpoly)
{
MEdge *med;
MPoly *mp;
int i;
/* edges */
i = totedge;
for (med = medge; i--; med++) {
if ((med->flag & ME_HIDE) == 0) {
if ((mvert[med->v1].flag & SELECT) && (mvert[med->v2].flag & SELECT)) {
med->flag |= SELECT;
}
else {
med->flag &= ~SELECT;
}
}
}
/* polys */
i = totpoly;
for (mp = mpoly; i--; mp++) {
if ((mp->flag & ME_HIDE) == 0) {
int ok = TRUE;
MLoop *ml;
int j;
j = mp->totloop;
for (ml = &mloop[mp->loopstart]; j--; ml++) {
if ((mvert[ml->v].flag & SELECT) == 0) {
ok = FALSE;
break;
}
}
if (ok) {
mp->flag |= ME_FACE_SEL;
}
else {
mp->flag &= ~ME_FACE_SEL;
}
}
}
}
void BKE_mesh_flush_select_from_verts(Mesh *me)
{
BKE_mesh_flush_select_from_verts_ex(me->mvert, me->totvert,
me->mloop,
me->medge, me->totedge,
me->mpoly, me->totpoly);
}
/* basic vertex data functions */
int BKE_mesh_minmax(Mesh *me, float r_min[3], float r_max[3])
{

@ -2162,6 +2162,24 @@ void nodeRegisterType(bNodeTreeType *ttype, bNodeType *ntype)
if (found == NULL)
BLI_addtail(typelist, ntype);
/* Associate the RNA struct type with the bNodeType.
* Dynamically registered nodes will create an RNA type at runtime
* and call RNA_struct_blender_type_set, so this only needs to be done for old RNA types
* created in makesrna, which can not be associated to a bNodeType immediately,
* since bNodeTypes are registered afterward ...
*/
#define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
if (ID == ntype->type) { \
StructRNA *srna = RNA_struct_find(STRINGIFY_ARG(Category##StructName)); \
BLI_assert(srna != NULL); \
RNA_struct_blender_type_set(srna, ntype); \
}
/* XXX hack, this file will be moved to the nodes folder in customnodes branch,
* then this stupid include path is not needed any more.
*/
#include "intern/rna_nodetree_types.h"
}
static void registerCompositNodes(bNodeTreeType *ttype)

@ -1853,12 +1853,19 @@ static void ob_parbone(Object *ob, Object *par, float mat[4][4])
}
/* get bone transform */
copy_m4_m4(mat, pchan->pose_mat);
if (pchan->bone->flag & BONE_RELATIVE_PARENTING) {
/* the new option uses the root - expected bahaviour, but differs from old... */
/* XXX check on version patching? */
copy_m4_m4(mat, pchan->chan_mat);
}
else {
copy_m4_m4(mat, pchan->pose_mat);
/* but for backwards compatibility, the child has to move to the tail */
copy_v3_v3(vec, mat[1]);
mul_v3_fl(vec, pchan->bone->length);
add_v3_v3(mat[3], vec);
/* but for backwards compatibility, the child has to move to the tail */
copy_v3_v3(vec, mat[1]);
mul_v3_fl(vec, pchan->bone->length);
add_v3_v3(mat[3], vec);
}
}
static void give_parvert(Object *par, int nr, float vec[3])
@ -1936,7 +1943,7 @@ static void give_parvert(Object *par, int nr, float vec[3])
}
else if (ELEM(par->type, OB_CURVE, OB_SURF)) {
Curve *cu = par->data;
ListBase *nurb = BKE_curve_nurbs_get(cu);;
ListBase *nurb = BKE_curve_nurbs_get(cu);
BKE_nurbList_index_get_co(nurb, nr, vec);
}

@ -154,7 +154,7 @@ int paint_facesel_test(Object *ob)
return ( (ob != NULL) &&
(ob->type == OB_MESH) &&
(ob->data != NULL) &&
(((Mesh *)ob->data)->editflag & ME_EDIT_PAINT_MASK) &&
(((Mesh *)ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) &&
(ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))
);
}
@ -165,7 +165,7 @@ int paint_vertsel_test(Object *ob)
return ( (ob != NULL) &&
(ob->type == OB_MESH) &&
(ob->data != NULL) &&
(((Mesh *)ob->data)->editflag & ME_EDIT_VERT_SEL) &&
(((Mesh *)ob->data)->editflag & ME_EDIT_PAINT_VERT_SEL) &&
(ob->mode & OB_MODE_WEIGHT_PAINT)
);
}

@ -18,7 +18,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/blenlib/intern/pbvh.c
/** \file blender/blenkernel/intern/pbvh.c
* \ingroup bli
*/

@ -446,7 +446,8 @@ static Scene *scene_add(Main *bmain, const char *name)
sce->r.bake_osa = 5;
sce->r.bake_flag = R_BAKE_CLEAR;
sce->r.bake_normal_space = R_BAKE_SPACE_TANGENT;
sce->r.bake_rays_number = 256;
sce->r.bake_samples = 256;
sce->r.bake_biasdist = 0.001;
sce->r.scemode = R_DOCOMP | R_DOSEQ | R_EXTENSION;
sce->r.stamp = R_STAMP_TIME | R_STAMP_FRAME | R_STAMP_DATE | R_STAMP_CAMERA | R_STAMP_SCENE | R_STAMP_FILENAME | R_STAMP_RENDERTIME;
sce->r.stamp_font_id = 12;

@ -593,8 +593,8 @@ void BKE_sequence_calc(Scene *scene, Sequence *seq)
/* XXX These resets should not be necessary, but users used to be able to
* edit effect's length, leading to strange results. See [#29190] */
seq->startofs = seq->endofs = seq->startstill = seq->endstill = 0;
seq->start = seq->startdisp = MAX3(seq->seq1->startdisp, seq->seq2->startdisp, seq->seq3->startdisp);
seq->enddisp = MIN3(seq->seq1->enddisp, seq->seq2->enddisp, seq->seq3->enddisp);
seq->start = seq->startdisp = max_iii(seq->seq1->startdisp, seq->seq2->startdisp, seq->seq3->startdisp);
seq->enddisp = min_iii(seq->seq1->enddisp, seq->seq2->enddisp, seq->seq3->enddisp);
/* we cant help if strips don't overlap, it wont give useful results.
* but at least ensure 'len' is never negative which causes bad bugs elsewhere. */
if (seq->enddisp < seq->startdisp) {

@ -170,7 +170,7 @@ void smoke_reallocate_fluid(SmokeDomainSettings *sds, float dx, int res[3], int
if (free_old && sds->fluid)
smoke_free(sds->fluid);
if (!MIN3(res[0], res[1], res[2])) {
if (!min_iii(res[0], res[1], res[2])) {
sds->fluid = NULL;
return;
}
@ -191,7 +191,7 @@ void smoke_reallocate_highres_fluid(SmokeDomainSettings *sds, float dx, int res[
if (free_old && sds->wt)
smoke_turbulence_free(sds->wt);
if (!MIN3(res[0], res[1], res[2])) {
if (!min_iii(res[0], res[1], res[2])) {
sds->wt = NULL;
return;
}

@ -1097,12 +1097,12 @@ static int sb_detect_face_pointCached(float face_v1[3], float face_v2[3], float
float facedist, outerfacethickness, tune = 10.f;
int a, deflected=0;
aabbmin[0] = MIN3(face_v1[0], face_v2[0], face_v3[0]);
aabbmin[1] = MIN3(face_v1[1], face_v2[1], face_v3[1]);
aabbmin[2] = MIN3(face_v1[2], face_v2[2], face_v3[2]);
aabbmax[0] = MAX3(face_v1[0], face_v2[0], face_v3[0]);
aabbmax[1] = MAX3(face_v1[1], face_v2[1], face_v3[1]);
aabbmax[2] = MAX3(face_v1[2], face_v2[2], face_v3[2]);
aabbmin[0] = min_fff(face_v1[0], face_v2[0], face_v3[0]);
aabbmin[1] = min_fff(face_v1[1], face_v2[1], face_v3[1]);
aabbmin[2] = min_fff(face_v1[2], face_v2[2], face_v3[2]);
aabbmax[0] = max_fff(face_v1[0], face_v2[0], face_v3[0]);
aabbmax[1] = max_fff(face_v1[1], face_v2[1], face_v3[1]);
aabbmax[2] = max_fff(face_v1[2], face_v2[2], face_v3[2]);
/* calculate face normal once again SIGH */
sub_v3_v3v3(edge1, face_v1, face_v2);
@ -1196,12 +1196,12 @@ static int sb_detect_face_collisionCached(float face_v1[3], float face_v2[3], fl
float t, tune = 10.0f;
int a, deflected=0;
aabbmin[0] = MIN3(face_v1[0], face_v2[0], face_v3[0]);
aabbmin[1] = MIN3(face_v1[1], face_v2[1], face_v3[1]);
aabbmin[2] = MIN3(face_v1[2], face_v2[2], face_v3[2]);
aabbmax[0] = MAX3(face_v1[0], face_v2[0], face_v3[0]);
aabbmax[1] = MAX3(face_v1[1], face_v2[1], face_v3[1]);
aabbmax[2] = MAX3(face_v1[2], face_v2[2], face_v3[2]);
aabbmin[0] = min_fff(face_v1[0], face_v2[0], face_v3[0]);
aabbmin[1] = min_fff(face_v1[1], face_v2[1], face_v3[1]);
aabbmin[2] = min_fff(face_v1[2], face_v2[2], face_v3[2]);
aabbmax[0] = max_fff(face_v1[0], face_v2[0], face_v3[0]);
aabbmax[1] = max_fff(face_v1[1], face_v2[1], face_v3[1]);
aabbmax[2] = max_fff(face_v1[2], face_v2[2], face_v3[2]);
hash = vertexowner->soft->scratch->colliderhash;
ihash = BLI_ghashIterator_new(hash);
@ -1957,7 +1957,7 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3],
}
closest_to_line_segment_v3(ve, opco, nv2, nv3);
sub_v3_v3v3(ve, opco, ve);
sub_v3_v3v3(ve, opco, ve);
dist = normalize_v3(ve);
if ((dist < outerfacethickness)&&(dist < mindistedge )) {
copy_v3_v3(coledge, ve);
@ -1966,7 +1966,7 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3],
}
closest_to_line_segment_v3(ve, opco, nv3, nv1);
sub_v3_v3v3(ve, opco, ve);
sub_v3_v3v3(ve, opco, ve);
dist = normalize_v3(ve);
if ((dist < outerfacethickness)&&(dist < mindistedge )) {
copy_v3_v3(coledge, ve);

@ -106,8 +106,8 @@
((arr = (void *)_##arr##_static), (_##arr##_count += (num))) \
: \
/* use existing static array or allocate */ \
((BLI_array_totalsize(arr) >= _##arr##_count + num) ? \
(_##arr##_count += num) : \
(LIKELY(BLI_array_totalsize(arr) >= _##arr##_count + num) ? \
(_##arr##_count += num) : /* UNLIKELY --> realloc */ \
( \
(void) (_##arr##_tmp = MEM_callocN( \
sizeof(*arr) * (num < _##arr##_count ? \

@ -175,6 +175,42 @@ MINLINE int max_ii(int a, int b)
return (b < a) ? a : b;
}
MINLINE float min_fff(float a, float b, float c)
{
return min_ff(min_ff(a, b), c);
}
MINLINE float max_fff(float a, float b, float c)
{
return max_ff(max_ff(a, b), c);
}
MINLINE int min_iii(int a, int b, int c)
{
return min_ii(min_ii(a, b), c);
}
MINLINE int max_iii(int a, int b, int c)
{
return max_ii(max_ii(a, b), c);
}
MINLINE float min_ffff(float a, float b, float c, float d)
{
return min_ff(min_fff(a, b, c), d);
}
MINLINE float max_ffff(float a, float b, float c, float d)
{
return max_ff(max_fff(a, b, c), d);
}
MINLINE int min_iiii(int a, int b, int c, int d)
{
return min_ii(min_iii(a, b, c), d);
}
MINLINE int max_iiii(int a, int b, int c, int d)
{
return max_ii(max_iii(a, b, c), d);
}
MINLINE float signf(float f)
{
return (f < 0.f) ? -1.f : 1.f;

@ -266,8 +266,8 @@ void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
void rgb_to_hsl(float r, float g, float b, float *lh, float *ls, float *ll)
{
float cmax = MAX3(r, g, b);
float cmin = MIN3(r, g, b);
const float cmax = max_fff(r, g, b);
const float cmin = min_fff(r, g, b);
float h, s, l = (cmax + cmin) / 2.0f;
if (cmax == cmin) {

@ -140,7 +140,7 @@ float area_poly_v3(int nr, float verts[][3], const float normal[3])
x = fabsf(normal[0]);
y = fabsf(normal[1]);
z = fabsf(normal[2]);
max = MAX3(x, y, z);
max = max_fff(x, y, z);
if (max == y) py = 2;
else if (max == x) {
px = 1;
@ -1198,10 +1198,10 @@ int isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3]
return isect_line_tri_v3(p1,p2,v0,v1,v2,lambda);
/* first a simple bounding box test */
if (MIN3(v0[a1],v1[a1],v2[a1]) > p1[a1]) return 0;
if (MIN3(v0[a2],v1[a2],v2[a2]) > p1[a2]) return 0;
if (MAX3(v0[a1],v1[a1],v2[a1]) < p1[a1]) return 0;
if (MAX3(v0[a2],v1[a2],v2[a2]) < p1[a2]) return 0;
if (min_fff(v0[a1], v1[a1], v2[a1]) > p1[a1]) return 0;
if (min_fff(v0[a2], v1[a2], v2[a2]) > p1[a2]) return 0;
if (max_fff(v0[a1], v1[a1], v2[a1]) < p1[a1]) return 0;
if (max_fff(v0[a2], v1[a2], v2[a2]) < p1[a2]) return 0;
/* then a full intersection test */
#endif

@ -1,41 +0,0 @@
/*
* ***** 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) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef __BLO_SOUNDFILE_H__
#define __BLO_SOUNDFILE_H__
/** \file BLO_soundfile.h
* \ingroup blenloader
*/
#include "DNA_sound_types.h"
#include "DNA_packedFile_types.h"
struct bSound;
struct PackedFile;
#endif

@ -52,7 +52,6 @@ set(SRC
BLO_blend_defs.h
BLO_readfile.h
BLO_runtime.h
BLO_soundfile.h
BLO_sys_types.h
BLO_undofile.h
BLO_writefile.h

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