1
1

Compare commits

..

451 Commits

Author SHA1 Message Date
4a801f6c6f Merge branch 'master' into object_nodes 2016-08-09 16:37:15 +02:00
49c63d46db Merge branch 'master' into object_nodes 2016-07-25 09:35:03 +02:00
be12e7a42e Added a number of addition matrix manipulation nodes. 2016-07-24 13:09:35 +02:00
dcb4ca500f Merge branch 'master' into object_nodes 2016-07-19 11:43:07 +02:00
41cc366010 Merge branch 'master' into object_nodes 2016-07-19 10:53:34 +02:00
794cbb2790 Minor whitespace fix. 2016-06-26 12:45:51 +02:00
0dbafd1fe5 Added object nodes for looking up an object and transform from global data. 2016-06-24 16:19:23 +02:00
c97a25b206 LLVM TypeBuilder and copy function for node_counted_ptr.
Using a DerivedMesh directly for mesh data isn't so great because
the lifetime of a DM is not necessarily known at compile time, depending
on branching. node_counted_ptr is basically a simplified shared_ptr variant.
2016-06-24 14:45:53 +02:00
af27ce2497 Use a hash table to register external functions with the LLVM engine.
This will allow using BLI/BKE code for complex data types, such as DerivedMesh.
2016-06-24 10:23:30 +02:00
0f868ea6b6 Include mesh opcode functions in modules.
Modifier functions with variable expression inputs are disabled,
until DerivedMesh handling through LLVM is implemented.
2016-06-24 10:23:03 +02:00
0f9c5bdb5c Fix graph return values: Not all value types are returned as duals. 2016-06-23 19:16:40 +02:00
11bbcce929 Fix for graph function signature: use pointers also for aggregate and struct types. 2016-06-23 18:36:10 +02:00
0be2c2a89a Use the LLVM backend for modifier nodes.
This currently fails, because the actual mesh nodes are not yet implemented
in the LLVM backend.
2016-06-23 13:43:25 +02:00
cf27fdb659 Reduce repetitive code in the C API by defining static node graph signatures.
Node graph inputs/outputs are now defined statically and graph instances
can be constructed by passing these as ArrayRefs. The code for compiling
various node graph types can then be unified.
2016-06-23 12:36:05 +02:00
48038ee8a5 More codegen implementations for basic functions.
* float/int conversion
* float3/float4 getters and setters
2016-06-22 18:25:37 +02:00
d86efe5830 Removed unused source file. 2016-06-22 12:35:57 +02:00
d2e2ec766f Use load/store for float3 and float4 to generate a bit nicer code.
It's unclear if the same can be done for larger aggregate types like matrix44.
2016-06-21 17:42:27 +02:00
13a84fcb33 Define names for most values in generated LLVM code.
These are purely for debugging the code, they help a lot in reading
LLVM dumps.
2016-06-21 16:50:04 +02:00
e4dea76bdd New CodeGenerator implementation for replacing the old BVM compiler. 2016-06-20 17:38:37 +02:00
075f60c6f5 Moved old bvm codegen and function files into bvm module.
The intern and compile modules are now truly independent from backends (llvm and bvm).
2016-06-19 14:50:05 +02:00
ff3c066324 Refactor of the node graph compiler class, to have a backend-agnostic base.
The main compiler class is now itself independent of LLVM and can be used for
future backends. The implementation of specific behavior (values, statements, etc.)
happens through a CodeGenerator implementation. This also uses aggregation rather
than inheritance on the compiler class part (which is not a virtual class itself).
2016-06-18 12:41:06 +02:00
e197ce618b Merge branch 'master' into object_nodes 2016-06-16 09:18:40 +02:00
926819d82f Use a Scope concept for avoiding codegen for existing nodes.
Rather than a single socket value map, use a "scope" to keep track of which
nodes are already generated. This reintroduces the "block" idea from earlier
versions, but at the later codegen stage rather than the node graph.

Describing scope on the level of nodes becomes quite clumsy and ambiguous,
and moves nodes further away from the UI representation. The compiler can
handle this more elegantly without requiring persistent data.

Scopes can be nested. This is not used yet, but will allow scoped variables
later on, where the variables being used for a node path depend on its scope.
2016-06-16 09:10:35 +02:00
5963c56967 Removed/Disabled some deprecated code. 2016-06-12 14:50:54 +02:00
989810f312 Disabled compiling and eval of broken BVM functions, to simplify debugging until they can be reimplemented. 2016-06-10 11:07:55 +02:00
6666b84182 Use persistent pass managers for optimization, rather than creating them every time. 2016-06-09 16:11:18 +02:00
c590f30623 Set a target triple and data layout for modules.
According to the site below, this is necessary for proper optimization.

http://llvm.org/docs/Frontend/PerformanceTips.html
2016-06-09 15:44:39 +02:00
6d4dd66d1f Generalized code generation for nodes to support more complex control flow in the future.
The basic idea is that a node represents a function F, without assuming anything about
how the input expressions are evaluated:

F = F()

In most common case this function can be decomposed and defined in terms of concrete values,
which are given by the input expressions:

F = F'(G1(), G2(), ...), where Gn are the respective inputs of the node

This is a first *very* naive implementation. It would rely heavily on common-subexpression-
elimination (CSE) to avoid generating the same code paths over and over again. There should
probably be some initial optimization on the BVM node level instead of relying just on LLVM passes.

The purpose of this generalization is to allow more complicated control flow inside node functions.
Nodes would then also be able to take additional variable arguments (e.g. an index), which can
be modified before being used as internal arguments for input expressions.
2016-06-09 12:29:27 +02:00
a6fdd7d876 Merge branch 'master' into object_nodes 2016-06-08 09:41:04 +02:00
95a603c607 Basic Gabor noise implementation for BLI_noise and blenvm.
This is just the very basic version of the sparse convolution noise
with a Gabor kernel. It does not yet have derivatives or anisotropic
filtering. The only frequency spectrum implemented atm is isotropic
band-limited noise.
2016-06-08 09:14:07 +02:00
ee58ba226e Removed cmake macro entry for deleted bf_blenvm_llvm_modules. 2016-06-03 10:24:14 +02:00
570bbf680a Support for image sampling in the LLVM backend.
This reintroduces the "globals" concept for mapping ID datablocks with
a consistent permanent identifier key.
2016-06-02 17:30:33 +02:00
8fda725b18 Fix invalid function signature when passing derivatives for types that don't support them. 2016-06-02 14:58:19 +02:00
de09b75175 Unify code generation through the llvm API.
Also standard functions for copying and zeroing values are now
implemented per type rather than relying on a simple load/store.
This will become more important with larger aggregate types such as matrix44.
2016-06-01 16:36:17 +02:00
318201968f Removed the unused "simple" (without derivatives) compiler implementation.
As long as the compiler class is WIP the two implementations go out of sync too
easily. Better to make a copy of the dual version and then reduce it when the
compiler class is reasonably stable.
2016-05-31 10:33:30 +02:00
926bdb8a05 Removed the WITH_IRMODULES option, used previously for loading IR code from text files.
This approach suffers from difficulty of generating machine-independent IR code
and is better generated using the C++ API directly. The llc tool can be used to suggest
implementations with C++ API usage, see for example
http://fdiv.net/2012/11/16/llvm-generates-code-that-generates-code
2016-05-31 10:09:35 +02:00
37db749fa6 Merge branch 'master' into object_nodes 2016-05-30 16:36:07 +02:00
d8e0006237 Generate names for formal function parameters to make LLVM output more readable.
Note that these names are not identifiers and don't have to be unique, their only
purpose is to aid in understanding the generated LLVM code.
2016-05-29 13:34:02 +02:00
bdd9bff0b3 Replace function signature for dual values with a flattened sequence of basic types.
This avoids the allocation of aggregate struct space for duals and allows better
optimizations.
2016-05-29 11:29:02 +02:00
ded2b507a1 Move the node-output-to-value map into compiler subclasses.
This is in preparation for specializing the value types of compiler implementations,
so that we can replace dual struct types with independent llvm values.
2016-05-28 11:29:01 +02:00
ac7d221734 Rename NodeValue to NodeConstant, to make it more consistent with LLVM naming. 2016-05-28 08:22:11 +02:00
b7bb0a0c4d Cleanup: use argument pointers for aggregate base types. 2016-05-27 17:20:52 +02:00
d8aaed17eb Merge branch 'master' into object_nodes 2016-05-27 16:01:49 +02:00
e6777be1d1 Derivatives for all the basic math node functions. 2016-05-27 12:26:05 +02:00
61b728a199 Small fixes for compiler errors in VS2013. 2016-05-27 11:01:37 +02:00
f40b79378c Use a more consistent naming scheme for value and derivative functions with prefixes. 2016-05-27 09:37:24 +02:00
d5408d7b13 Another depsgraph fix, internal texture relations need to be built explicitly.
Like node trees, textures are only optionally constructed in the depsgraph when something
uses them. When a modifier (or other potential future user of the "handle" system)
declares a texture dependency, the internal relations of that texture are not necessarily built -
this only happens when the texture is part of a material texture stack. So we need to also
construct the internal texture relations (lazy init) in addition to the external modifier->texture
dependency.
2016-05-27 09:06:39 +02:00
2b9d5205e6 Fix for node group updates: need to force-update the group node because of crappy node update system. 2016-05-26 15:17:40 +02:00
ce8c882509 Fix node tree group relations.
Recent commits removed an important depsgraph relation between a node group and its tree.
2016-05-26 14:52:26 +02:00
ae8bde9f09 Fix for pynode group registration.
Because pynode groups now use the bl_idname of tree types rather than
expecting a python class attribute, these tree types need to be registered
*before* generating node group classes. Messy stuff, needs some rewriting.
2016-05-26 09:01:49 +02:00
3960e5671d Fix for depsgraph building of modifiers, missing nodes for ID blocks (textures).
The updateDepsgraph callback for modifiers needs to be used in both passes of
depsgraph building, once for creating nodes and then for relations. Without the
initial node building pass some datablocks like textures can be missing, if they
are not incidentally built by other means such as a render texture.
2016-05-26 08:45:50 +02:00
8478d4127e Use (1,0,0) and (0,1,0) as derivatives of texvec when no explicit derivatives are given.
This is a bit stupid, but allows testing the system without major changes
to old textures or the displacement modifier.
2016-05-25 17:34:46 +02:00
0e30440080 New node "Get Derivative" for using a derivative as the value.
This is mostly a debugging feature for getting visual feedback about
the derivatives. The function doesn't work in the regular scheme of
decomposing a function into the value and derivative parts, so it is
only implemented in the internal IR (making it directly inlineable).
2016-05-25 17:20:50 +02:00
cabcfb0062 Use the common BVM_DEFINE_ALL_OPCODES macro to simplify node->opcode mapping. 2016-05-25 12:10:58 +02:00
09385dcda0 Fix for uninitialized variable and removed some unused code. 2016-05-25 11:58:09 +02:00
f8ef1f0d09 Straightforward texture eval function in BKE for getting texture results with derivatives. 2016-05-25 10:35:37 +02:00
2030217042 Use derivative functions for calculating dual values using the forward accumulation method.
Only a few functions have derivatives defined yet.
2016-05-24 18:14:11 +02:00
3dae50bc4c Cleanup: Remove the unnecessary compiler subclasses for final instantiation. 2016-05-24 12:07:31 +02:00
f19a6f39c5 Cleanup: renamed "codegen" files to "compiler" and split the implementation. 2016-05-24 11:36:16 +02:00
0e8cd49e3b Move IR function implementations using the LLVM api into modules.h. 2016-05-24 10:58:31 +02:00
ee9797808c Generate wrapper functions in LLVM for converting dual types to primitives.
Currently Dual2 arguments are structs with the main value and 2 derivatives
in x and y. Node functions will generally be implemented using the base types,
so the value and derivatives have to be extracted and later combined using
the chain rule.
2016-05-23 15:07:44 +02:00
fd6a3c863f Generate dual values for input constants to match the declared function signatures.
Note that actual functions currently don't use Dual2<> values, but because they
only read/write the 'value' field it works anyway ...
2016-05-20 08:00:38 +02:00
cdda6bd19a Fix module linking: initialize the node graph module right away to avoid repeating code. 2016-05-19 18:34:08 +02:00
d98433c467 Leave the decision about passing arguments by pointer to the compiler class too.
This removes the last "global" type function, so all the details of types are now
decided in the compiler implementation subclass.
2016-05-19 18:22:53 +02:00
8a790c2b86 Removed unused codegen_begin/end functions. 2016-05-19 18:06:56 +02:00
bf007badbf Define a separate node function module for every compiler type.
This means we can have differing implementations for every potential use
of nodes, such as plain value functions vs. dual values with derivatives.

Node functions for each compiler type are stored in a static map and are
lazy-initialized on the first node graph compilation.
2016-05-19 18:04:21 +02:00
d54b4d2532 Pass texture arguments and return values as dual values.
Currently only the value part is actually accessed. Using dual values
allows the node graph to handle input/output arguments are single a
single llvm::Value instance.
2016-05-19 11:52:48 +02:00
030a327f40 Preparatory changes for differing node compiler implementations.
Uses some virtual functions of the node compiler to allow different
implementation of values. This will be used for calculating values
and partial derivatives in texture nodes.
2016-05-18 17:40:55 +02:00
ce022f4506 Use a TypeSpec pointer for structure fields rather than direct storage. 2016-05-18 11:28:50 +02:00
2ade7d5815 Type system refactor: Use a global type definition map instead of defining each type locally. 2016-05-18 08:03:47 +02:00
076564e5bd Merge branch 'master' into object_nodes 2016-05-16 12:45:24 +02:00
82fc0e02ab Cleanup: removed some unused code. 2016-05-16 12:44:25 +02:00
a601d5d18f Enable the new depsgraph by default.
The blenvm system depends on the new depsgraph, so it doesn't make sense
to have to enable it every time.

The legacy depsgraph can still be switched back on by the --enable-legacy-depsgraph option.
2016-05-16 12:37:14 +02:00
97681db89f Internal definition of commonly used node functions, so that LLVM can optimize better.
This currently includes just a few 'value' nodes, but should be extended as much as feasible.
In particular many vector functions can be split component-wise.
2016-05-14 19:49:57 +02:00
be79a6886b Implemented common procedural texture patterns for LLVM. 2016-05-14 12:44:35 +02:00
df2a739a86 Include all module functions in a single header for convenience. 2016-05-14 10:25:56 +02:00
b9ad0b94c0 Simple coordinate input node for texture nodes. 2016-05-14 09:55:20 +02:00
939810add5 Handle all node type kinds appropriately.
The LLVM backend also supports PASS nodes, even though these are usually
removed from the node graph in a preprocessing step for clarity.

ARG nodes have their output values mapped in advance, so no extra code
needs to be generated for them.
2016-05-14 09:53:33 +02:00
2d9bad03b7 Fix incorrect argument order for vector/color constructor functions. 2016-05-14 09:52:38 +02:00
d435274887 Replaced mix of bool type flags for node types with a single enum for special kinds of nodes. 2016-05-14 09:09:05 +02:00
83b1b3417b Implemented math functions for the LLVM backend. 2016-05-13 18:08:02 +02:00
da70902731 Fix for missing notifier application on texture node trees.
The pynodes tree does not have the static NTREE_TEXTURE type set.
2016-05-13 15:48:24 +02:00
9616b72e57 Fix node socket update callbacks exiting early because of missing output connection.
Outputs are currently identified in the nodes via the DO_OUTPUT flag. This is not
nicely accessible for pynodes and needs to be reimplemented in a proper way.
Until then this optimization for node recalculation should just be ignored for texnodes,
so nodes now have a callback for checking usage, and will always be considered used by default.
2016-05-13 15:46:15 +02:00
ca85cb436d Remove redundant dependency declaration from pynodes, which creates a circular dependency.
Previously the "parameters" depsnode was the POST operation for node trees, but has now
been supplanted by the cache invalidation node. Making an explicit dependency on the component
thus creates a cycle.
2016-05-13 11:22:00 +02:00
464505174b Switch texture nodes to a pynodes implementation.
This also removes the static bNodeTree type definition C, because
BVM requires some functions that are best defined in python (and it
would have been switched eventually anyway).
2016-05-13 11:15:54 +02:00
545413d8e8 Removed texture nodes.
The node tree type is left alone for now, only the node types are removed.
2016-05-13 07:53:03 +02:00
0e974d6e91 Define the base opcode functions for LLVM and use util_ files for types. 2016-05-12 19:26:03 +02:00
0e7c9a93ae Split opcode macro into thematic sections to make it easier to handle them in parts. 2016-05-12 18:17:32 +02:00
2d3f526403 More meaningful dependencies between node tree parameters and cache-invalidation operations, and textures that use them. 2016-05-12 17:56:54 +02:00
894511d568 Fix for regenerating functions with MCJIT.
LLVM was reusing old machine code, apparently regenerating it explicitly
with EE->generateCodeForModule() fixes this.
2016-05-12 17:51:54 +02:00
436e84a12c Fix for node function invalidation through the depsgraph.
We have two separate caches for bvm and llvm backend, both of them
might contain a function for the node tree.
2016-05-12 16:50:43 +02:00
50a244951b Merge branch 'master' into object_nodes 2016-05-12 09:56:05 +02:00
f49b698e87 Merge branch 'master' into object_nodes 2016-05-11 11:47:42 +02:00
e23c508f1c Fix the module.cc file. 2016-05-11 10:15:50 +02:00
38c5bf5f63 Small fix for llvm file includes. 2016-05-11 10:14:41 +02:00
c3888a6eaf Silence a few (false positive) compiler warnings about uninitialized variables. 2016-05-11 08:48:54 +02:00
948e0cfea8 Cleanup: removed unused code for struct return values and pointer arguments. 2016-05-10 11:24:33 +02:00
2556262f6c Implemented external C function linking and change of function signature convention.
The general signature layout for node functions is

void foobar(out1_t *out1, out2_t *out2, ..., in1_t in1, in2_t in2, ...);

All outputs are passed as pointers or references (using references in C code for clarity).
Inputs can be passed by-value or as const pointers/references (for structs and arrays).

In the future we may also support single value return types for convenience.
2016-05-10 11:14:50 +02:00
b220c9e5c6 Moved type definition functions for LLVM types into own file. 2016-05-09 09:12:37 +02:00
24b78398cf Disable IR module loading for blenvm by default (with a compile option).
Base modules for nodes will instead be declared as external functions with regular
linkage through C code. This means some potential for low-level optimization might be lost,
but this shouldn't be a big problem as long as node functions don't get too complex
(which means they should be split up in the first place).

IR module loading is not the real issue, but generating the IR code from C/C++ code
in a generic way is not so easy. In the future we may actually generate most code for
basic operators and types directly inside blenvm and only use precompiled modules
for more complex functions.
2016-05-09 08:17:30 +02:00
c5fd1aeff2 Merge branch 'master' into object_nodes 2016-05-08 11:15:48 +02:00
318ffd8e3c Remove the unordered_map cmake monstrosity from subdirectory build files.
Doing this in the top-level cmake file for blenvm is enough.
2016-04-12 10:27:01 +02:00
d42a384296 Extended debug printing modes to the LLVM code.
The LLVM IR code can be dumped either in raw form or optimized.
It is stored as a raw text file.
2016-04-12 10:12:19 +02:00
9edebfb9ab Minor fixes for compiling without LLVM. 2016-04-11 17:21:20 +02:00
103ecf7aca Fix expression result use as function arguments and add RGBA color mix node. 2016-04-11 16:51:45 +02:00
2c16ec47ed Inlining of base node functions in LLVM IR code.
This requires a somewhat hackish stub function to force linking of inlined
functions in the modules, so that clang doesn't just omit them when
producing IR code. Not very nice, but also not directly related to the
actual Blender code.
2016-04-11 09:16:05 +02:00
4828cf2313 Optimization passes for the generated LLVM code. 2016-04-09 15:47:29 +02:00
50410d1ce5 Completed basic expression tree code generation.
The code uses a pointer-based signature convention for node functions,
which helps to avoid issues with type coercion through clang.
In the future we could either find a more reliable way to produce llvm IR
for the nodes, or use node functions as external functions without inlining.
2016-04-08 17:28:42 +02:00
2205d2870d Use annotation attributes on module functions to avoid name mangling issues.
Names in C++ code tend to get mangled by the clang compiler according to the
respective target ABI. This is unfortunate because it makes it difficult to
map functions to nodes by name. For now we use a function attribute in the module
C++ code to pass on the "true" name of the function and map them internally.
2016-04-07 17:54:53 +02:00
3c30c96850 Make LLVM module compilation depend on header files to force recompile when headers change. 2016-04-07 17:53:14 +02:00
d02c7eeacb Generate function calls for every node, using code defined in precompiled modules.
Note that this is currently not quite working: The clang compiler call used
tentatively for generating the LLVM IR code for modules uses a lowering pass to
coerce struct data types (such as float3) according to the target ABI. This should
be avoided and is unnecessary for our purposes, since we stitch together and optimize
these code fragments ourselves. In principle we could avoid using a C compiler altogether
and write this stuff by hand, but the point of using the compiler is to avoid this tedious
work. More info:
http://stackoverflow.com/questions/22776391/why-does-clang-coerce-struct-parameters-to-ints
2016-04-06 17:52:34 +02:00
37477ffa1c Ported over code from previous llvm branch for loading IR modules and linking runtime code. 2016-04-05 17:57:29 +02:00
3346568b01 Initial code for mapping node sockets to llvm values. 2016-04-05 16:58:21 +02:00
fa1f852381 Cleanup: Fixed deprecated docstrings for file location. 2016-04-05 16:32:16 +02:00
1fc5680442 Cleanup: Renamed Value class to NodeValue, to distinguish from llvm::Value easier. 2016-04-05 16:26:38 +02:00
1ddfdfa31d With the proper formal function parameters for node functions they can now actually be called. 2016-04-05 11:37:43 +02:00
6392e8885a Use getFunctionAddress instead of deprecated getFunctionPointer. 2016-04-05 11:30:30 +02:00
baf585cdc5 Retain functions both for storage in the cache as well as keeping the pointer during eval.
Otherwise the function is freed immediately after each use, making the cache pointless.
2016-04-05 11:04:44 +02:00
1761091ce6 Only insert functions into the function cache when use_cache argument is true. 2016-04-05 10:26:59 +02:00
ff6673d8b8 Type generation for LLVM based on node socket types.
Currently every socket stores a complete and unique type definition.
This should be changed to module-level type declarations and referencing by name.
2016-04-05 10:16:57 +02:00
7658c6cf0d Implement bvm internal function caching and spin lock (missing from previous commit). 2016-04-05 09:17:14 +02:00
7a57a4f871 Use function caching in the same way for BVM as for LLVM.
The previous way of acquiring functions from the cache was actually not threadsafe.
To do this efficiently the cache locking, lookup and potential update is now done
inside the API functions to prevent race conditions on the cache.
2016-04-04 19:28:04 +02:00
72fd685f2f Experimental (and very messy) code for JIT compiling and running a simple stub function for texnodes on the LLVM backend. 2016-04-04 17:34:08 +02:00
84407d57c0 Use a _bvm postfix to distinguish the "gen_XXX_function" and "eval" API methods by backend. 2016-04-01 10:22:12 +02:00
9032c2ae96 Generalization of the function cache feature to support both bvm and llvm backends.
This code is not very elegant atm, but it does the job. Have to see how internal code
management of LLVM (modules) plays into this, the function cache then could become
redundant.
2016-04-01 09:23:35 +02:00
a9cdbda687 Partial revert: Use only BVMFunction stub type as a handle for all backends.
API functions are still distinguished by backend.
2016-03-31 16:39:21 +02:00
15684cda57 Use the BVM postfix to distinguish 'Function' in bvm backend from future LLVM functions. 2016-03-31 16:35:36 +02:00
c25ca841fb Fix incorrect stub type name for texnodes. 2016-03-31 16:14:09 +02:00
05cdeb6745 Added llvm_engine files for managing global LLVM initialization and ExecutionEngine. 2016-03-31 13:00:53 +02:00
038e45de62 Rename BVMFunction to BVMFunctionBVM in the C API.
The awkward double shorthand "BVM" has two meanings here:
 * BVM*** is short prefix for "BlenVM" (to be changed later?).
 * ***FunctionBVM means a function in the bvm backend implementation (see FunctionLLVM etc.)

This should be cleaned up later, by chosing a more sensible name for the overall code module.
2016-03-30 17:08:46 +02:00
d8b97405d1 Cleanup: replace namespace bvm with namespace blenvm in comments. 2016-03-30 16:41:36 +02:00
5415e884f6 Own file for function cache API. 2016-03-30 16:22:34 +02:00
09a8d6794b Moved the modules directory to the blenvm base level, so modules can be shared code.
The idea is to use modules code for all the various backends to avoid lots of duplicate code.
This is similar to how the same code is used in Cycles for CPU and CUDA backends.
2016-03-30 15:07:10 +02:00
cf7c185dc1 Added blenvm_llvm submodule for implementing the LLVM backend to the blenvm node system. 2016-03-30 13:48:50 +02:00
07d3c2c317 Support LLVM header includes.
These were not needed by Blender yet, because LLVM is only used indirectly
through dependencies, which use their own build settings for LLVM include paths.
2016-03-30 12:10:39 +02:00
b5a454f6cf Renamed bvm_typedesc to typedesc: It's not actually specific to the bvm backend. 2016-03-30 09:54:45 +02:00
f56be79da6 Restructuring: Remove the 'bvm' prefix from files that are not directly concerned with the bvm backend.
The naming here is a bit confusing: BlenVM is the name used for the overall code module. BVM can be a shorthand
for BlenVM, but is also the name of the backend for SVM-like code interpreter. General purpose code (such as
node graph and util files) should avoid the bvm prefix. BlenVM as the overall name for the code module is kept
for now, but may be replaced at a later point.

Note that currently one bad-level-include from non-bvm to bvm code remains, for the Value class used in nodes.
Values should ultimately be a backend-agnostic class for storing literal values (node inputs).
2016-03-29 18:48:41 +02:00
245d7a08d0 Merge branch 'master' into object_nodes 2016-03-29 16:45:12 +02:00
39af860e6d Cleanup: Moved value class into own file, away from pure type declarations. 2016-03-09 17:25:58 +01:00
94b4a06c53 Merge branch 'master' into object_nodes 2016-03-06 15:48:32 +01:00
a168e65f1b Merge branch 'master' into object_nodes 2016-02-28 16:12:25 +01:00
f232d7a599 Merge branch 'master' into object_nodes 2016-02-08 10:21:41 +01:00
843e0d1f3a Fix for use of TypeDesc.base_type as a plain value rather than a function call. 2016-02-01 12:38:27 +01:00
c98b02495b New buffer type 'Image' for 2-dimensional arrays. 2016-01-30 13:34:15 +01:00
1c5340de2d Removed the 'Iteration' node, the main index is now an implicit variable. 2016-01-30 11:22:32 +01:00
239c864318 Updated codegen for handling variables and expressions.
Note that kernel nodes now don't have explicit 'function' inputs
any more. Any expression input can be a separate block. Eventually
this should be handled by creating true loops, branches, etc. in the
generated code, rather than reading a jump address from the instructions
and passing it to a blackbox method as a "function pointer".

For the time being the kernel nodes simply prepend a jump address before
*every* input, using BVM_JMP_INVALID in case the input node is not in a
separate block.
2016-01-29 14:31:59 +01:00
067dfb3e52 Adapted the node blockify procedure to the new concept of expressions and variables.
The internal bvm nodes now can contain (implicit) cyclic connections, owing to the
connection of variable inputs to local variable outputs of kernel nodes. These link
cycles are never created explicitly by the node parser (pynodes), but are a result
of the semi-functional programming nature of the nodes: each node constitutes a
function of the local variables defined inside a kernel block. When the nodes are first
constructed from the user-level nodes these inputs are left unbound, and are then
resolved backwards as the individual node functions are inlined.
2016-01-29 11:56:15 +01:00
a4108eba7f Redefinition of the meaning of "value type" for sockets (intermediate commit).
The use of "expressions" for node inputs must be generalized to support array-like
data and a level of functional programming. Inputs are now expressions *by default*.

A node can also have "variables" as inputs, which are implicitly defined in the base node
graph and should not be bounded in the first compiler step (i.e. are not defined by
pynodes). Variables instead are defined as outputs of other nodes (currently still called
"kernel" nodes), which would mostly constitute loops over such variables.

The concepts being worked on here are loosely based on those found in the Halide language
http://halide-lang.org/index.html
2016-01-26 11:51:40 +01:00
9cbdfdbdfa Merge branch 'master' into object_nodes 2016-01-24 14:43:59 +01:00
cb96f9d568 Mockup Nodes: Dummy pynodes for smoke and rigidbody simulations.
These have no implementation yet, they are just meant to test concepts.
2016-01-22 10:56:54 +01:00
dd6a0dc910 Basic image sampling node for reading interpolated color values from an Image datablock. 2016-01-19 23:29:51 +01:00
0b2b29ba56 Cleanup: Simplify depsgraph API by using the same depsnode type for each ID.
This means the user might use an invalid component key for generating dependencies,
but the only consequence is that no relation is created.
2016-01-19 16:41:16 +01:00
a31609a6be Two-level use-count system for bvm pointer variables.
The rationale for this change is that copying variables on the bvm stack
will become necessary for compound variables (structs). In order to
efficiently keep pointers on the stack without making deep copies every
time such a variable is copied, the pointer must be a kind of shared_ptr
concept. In addition to this the stack variable itself must also be counted,
so that we have a way of detecting when it "goes out of scope", i.e. all
nodes using it have finished.

The node_counted_ptr is not a full C++ shared_ptr, because the user counting
is handled explicitly by the compiled bvm instructions. Using a std::shared_ptr
would be difficult due to the mixed levels of evaluation (compile-time constants,
storing shared_ptr on the opaque stack), and because of difficult interfacing
with C code (returning persistent plain pointers).
2016-01-18 13:05:36 +01:00
0549e0eeaf Cleanup: use size_t (i.e. size in bytes) for data types, rather than explicit stack size.
The stack size is calculated during codegen by an int-ceil division,
currently padding to int size (probably later to be changed to int4 for
better SSE support).
2016-01-16 17:44:33 +01:00
e44d648779 Cleanup: Use an real type 'EvalStack' for passing the value stack around.
This should avoid possible confusion of values (floats) with the more
abstract value stack.
2016-01-16 17:25:07 +01:00
40150c9e6e Extended TypeDesc to support compound type definitions (structures). 2016-01-15 11:10:03 +01:00
9b22c3854d New util file for structure type implementations in C/C++. 2016-01-15 10:08:09 +01:00
475c13a7d2 Rename: POINTER base type to "RNAPOINTER".
This is so the POINTER type can be used for general struct pointers and arrays.

RNA pointers should eventually be replaced with more specific types for
data that can be accessed in the bvm system.
2016-01-14 15:38:30 +01:00
0df953fb92 Fix for incorrect pointer type in smoke effector updates. 2016-01-14 09:42:31 +01:00
d9d9c97106 Moved util_typedesc file into the compile module. 2016-01-13 19:32:24 +01:00
66070ec814 Split off from the bvm::Function class the basic instruction list functionality.
The point of this is to keep type definitions out of the core bvm eval code.
TypeDesc is only used for the outermost layer of bvm::Function in order to
copy arguments to and results from the eval stack. OpCodes themselves are
agnostic to higher type definitions and just work with raw data.
2016-01-13 19:26:17 +01:00
04f9286c07 TypeDesc registration in NodeGraph for reusable type definitions.
Eventually this could allow actual user typedefs (through the API),
but primarily this is to make complex type definitions possible without
having to do a full definition every time, and simply use the type name.
2016-01-13 14:54:46 +01:00
431b90c969 Merge branch 'master' into object_nodes 2016-01-13 12:19:32 +01:00
326255d080 Fix a memleak of the return value user counter from mesh_ptr.
The returned mesh_ptr result needs to be cleared to ensure the user
counter is also freed. To avoid deleting the mesh data as well a new
function 'reset' was added, which frees the user counter but only resets
the data pointer without freeing it.
2016-01-13 11:02:00 +01:00
0937f5baa3 Another geometry node for loading another objects 'final derived' mesh.
Modifiers should be able to work on meshes directly as much as possible,
without direct reference to an object. The space transform should
ultimately be passed along with the DM (TODO, currently requires explicit
inputs).
2016-01-12 14:48:10 +01:00
29daf7dedb Prepend a value node on all (non-constant) node inputs without a link.
In principle the input value could be used directly in codegen, but this
approach means one less condition to check and has the same effect.
2016-01-12 14:46:33 +01:00
71747fa395 Fix for incorrect output type displace element.index. 2016-01-12 14:39:15 +01:00
af0215918e Added a simple operator and panel for one-click debug display of bvm node visualizations.
This was formerly part of an addon, but is useful enough to include directly in the branch
for debugging purposes. It uses the existing graphviz dump functions to write into a
temp dot file, then runs graphviz on it and opens the resulting image in the standard
system image viewer.

This is tailored for linux systems, but that shouldn't be a big issue since most developers
(who are the target audience) use this platform anyway.
2016-01-12 12:22:15 +01:00
9fccaadb84 Use the new node block structure in code generation, to determine dependencies of symbols. 2016-01-12 11:40:35 +01:00
97642e0c96 More elegant construction of implicit node blocks, by copying argument node first. 2016-01-11 15:24:36 +01:00
f918012866 Represent nested node blocks in the graphviz debug dump. 2016-01-09 17:40:19 +01:00
65b4da0cc3 Cleanup: class for debug dumping functions for node graphs. 2016-01-09 15:01:30 +01:00
d5707b9a05 Moved the block definition from codegen to the node graph optimization.
This now involves making actual copies of nodes, so that each block has
a unique instance of each node and ambiguity is avoided.
2016-01-09 14:07:58 +01:00
c882d15626 Generalized algorithm for constructing node blocks based on local arguments.
Nodes can have expression inputs and override argument nodes with local
variables. This means that a local block must be created for each expression
input. The boundaries of such blocks are defined implicitly by upstream nodes
which define their own local arguments (or ultimately by the graph arguments).

The current version is still not quite generic enough to allow arbitrary
nesting of blocks, but it should ensure that expressions don't include all
the parent nodes which don't depend on local arguments and therefore should
be calculated in the parent block (a form of constant folding).
2016-01-08 17:31:46 +01:00
3598ef2536 Use a global node index assignment to enable sorted sets for nodes.
This simplifies code generation because we can use a set with efficient
lookup which also keeps a valid ordering of nodes as dictated by links.
Since any generated code uses only subsets of nodes, the ordering still
is valid for any BasicBlock.
2016-01-07 12:11:15 +01:00
5eaabb9aac Moved BasicBlock out of the Compiler struct. 2016-01-07 11:11:22 +01:00
8796a997d6 Fix for missing stack indices in expression blocks.
When creating an expression block, the parent block stack indices must
initialize the local index map, so that external variables can be accessed.
2016-01-07 10:41:35 +01:00
a16ff1f568 New node for finding the closest point on a mesh.
This will be useful for shrinkwrap-type modifier behavior.
2016-01-06 13:46:37 +01:00
9121c804a7 Cleanup: Moved some classes out of the typedesc utility file. 2016-01-06 11:29:16 +01:00
6858b1fd81 Fix incorrect header naming. 2016-01-06 11:25:08 +01:00
72878c26a2 Cleanup: Use node/socket pair keys more consistently instead of pointers. 2016-01-04 15:21:14 +01:00
01f7d71fa7 Strict separation of input and output socket keys for clarity.
This avoids confusion regarding what socket keys are stored in maps etc.
2016-01-04 13:47:03 +01:00
0313128207 Merge branch 'master' into object_nodes 2016-01-04 10:48:52 +01:00
289493c74f Added basic semantics to the debug compiler by accessing node types. 2016-01-04 00:39:55 +01:00
1313440c59 Debug representation of generated bvm code.
A specialized compiler variant is added that turns generated code
into a graphviz diagram of the instruction lists.
2016-01-03 23:59:29 +01:00
8b5cae92c5 Abstract virtual base for the BVMCompiler class.
This will allow different implementations of the compiler depending
on the intended target. This could be other bytecode formats (LLVM, SPIR),
but most imminently would be used for debugging.
2016-01-03 12:55:14 +01:00
a7da96ad1b Merge branch 'master' into object_nodes 2016-01-03 10:57:26 +01:00
97e00d6091 Fix for broken pynodes: BVM functions in NodeTree must be optional. 2016-01-03 10:55:30 +01:00
37875dc003 Renamed map of basic blocks used for expressions. 2016-01-01 17:41:41 +01:00
4ca0309f13 Renamed the FUNCTION input value type to EXPRESSION for clarity.
'Function' is a more general term, the input is specifically an
'expression' because it returns a single value.
2016-01-01 17:41:41 +01:00
4c6b05322c Renamed FunctionInfo to BasicBlock, because that's what it is generally called in compilers. 2016-01-01 17:41:41 +01:00
acd4b54f91 Implement more texture types.
This adds support for marble, magic, stucci, distorted noise, musgrave
and wood textures.
2016-01-01 17:27:00 +01:00
8331fceec6 New vector math mode for vector length, patch by Philipp Oeser (lichtwerk). 2016-01-01 13:42:13 +01:00
7335106206 Output values in node graphs are unused, removed.
In fact there is no per-output data in node instances at all, so the
OutputInstance data was removed entirely. All the connectivity and
value information is in the inputs.
2015-12-31 15:05:25 +01:00
08530c7eea Fix memleaks in refcounted data pointers on the bvm stack. 2015-12-31 14:56:54 +01:00
8c5041be5c Fix for memleaks caused by un-freed Value instances, kudos to Kevin Dietrich!
These values are heap-allocated virtual classes, because general node code is
largely agnostic to data types. After adding values to a node (either as
default input values or per instance), care must be taken to free them when
the node type or instance is destroyed.
2015-12-31 13:11:19 +01:00
bb0e1375b1 Merge branch 'master' into object_nodes 2015-12-31 12:04:51 +01:00
8e0489442f Reusable functions for copying a set of nodes and calculating node bounds. 2015-12-29 09:12:40 +01:00
77ae38677c Added an optional update callback for the configurable object node ID property. 2015-12-28 11:27:34 +01:00
e26d7a72fd 'Make Group' operator (ctrl+g) to easily create a node group from selected nodes. 2015-12-27 18:39:48 +01:00
397e1aeccb Use a unified list for simplifying socket identifiers and matching RNA struct types. 2015-12-27 17:17:43 +01:00
48e0785dc5 Fix compiler warning from illegal zero-initialization in C++0x. 2015-12-27 14:42:37 +01:00
f036fa079c ID.flag has been split to put runtime tags in a separate field (rB3fcf535d). 2015-12-27 14:35:06 +01:00
ad072beb68 Merge branch 'master' into object_nodes
Conflicts:
	source/blender/depsgraph/intern/depsgraph_build_nodes.cc
	source/blender/depsgraph/intern/depsgraph_build_relations.cc
2015-12-27 14:21:03 +01:00
898d2ac36c List existing node groups in 'Group' categories for easy instancing.
This includes polling by type and recursion level to ensure groups
are only added in appropriate tree types, and don't create cyclic
dependencies.
2015-12-27 10:29:30 +01:00
36c6cbb902 Poll node groups based on node tree datablocks rather than node instances.
There is a redundancy in the nodetree/node relationship, since each nodes
is part of exactly one node tree. This means we can test for either trees
or nodes to detect cycles, and because we usually poll for node trees
rather than nodes that would be the natural choice.
2015-12-27 07:28:10 +01:00
d3b626711f Automatically create a new node tree when making an object component node. 2015-12-25 18:19:29 +01:00
6a82c17c10 Create a default minimal node setup when creating new trees or groups. 2015-12-25 17:06:21 +01:00
842a138071 Duplicate enum values lead to creating mesh instead of dupli sockets in node groups. 2015-12-23 18:46:04 +01:00
c92dc52f34 Fix for empty dupli list defaults, these must be neither NULL nor static. 2015-12-23 18:34:13 +01:00
e339326621 Use dedicated functions for producing graphviz debug output.
This allows creating unoptimized node graph output dumps without
causing crashes, because the codegen step is not performed when
just producing debug output.
2015-12-23 18:10:22 +01:00
894c9f3f85 Added RNA function for debugging dupli bvm nodes. 2015-12-23 17:35:54 +01:00
a51fc1b993 Fix for node groups: operator for creating a new tree was hard-wired to geometry nodes. 2015-12-23 17:12:09 +01:00
3e2fa696bf Added missing bf_blenvm linking for blenderplayer. 2015-12-23 15:21:35 +01:00
f0860367f1 Use dynamic socket lists for mesh and dupli output nodes for convenience. 2015-12-23 14:45:33 +01:00
a2f5fc297f Generalization of the dynamic socket list feature, currently used by mesh-combine. 2015-12-23 14:38:59 +01:00
70e84dc17a Use default node input value for constants. 2015-12-23 14:37:27 +01:00
92f55bcf87 BVM node for combining dupli lists. 2015-12-23 13:18:45 +01:00
d0949254da Extended notifiers from node value editing to include instancing trees.
The use of notifiers from node trees is very unsatisfactory atm.
Notifiers should be integrated into the depsgraph, so that changes
to data automatically trigger appropriate UI redrawing.
2015-12-23 13:00:29 +01:00
562bcb4d36 Implementation of the "make dupli" node to generate a single dupli object. 2015-12-23 12:46:36 +01:00
aacff41363 Use a std::vector for storing Dupli instances in bvm for efficiency. 2015-12-23 12:24:00 +01:00
1a37890ac0 Return duplis from a bvm node evaluation, just like DerivedMesh. 2015-12-22 14:30:09 +01:00
9af1dfb91d Fix for default values of array types.
Now an array can be passed directly to the add_input functions to
construct an ArrayValue.
2015-12-22 13:55:26 +01:00
9f1165c8aa New opaque type 'DUPLIS' for storing a dupli list.
This works just like the MESH type, but wraps a ListBase instead of
a DerivedMesh. Using this type the duplis can be generated internally
and returned as a result.

All such data types should be handled in a generalized way eventually.
2015-12-22 13:30:17 +01:00
5c9ccf04a4 Correct types for array 'pass' nodes. 2015-12-22 12:40:19 +01:00
13329d9a63 Reordered data types a bit, so mesh and other complex types are at the end. 2015-12-22 12:02:19 +01:00
674bb4b6a4 PASS nodes for array types. 2015-12-22 11:07:41 +01:00
66a41f2e9f Array types for node sockets.
These are an extension of the type description to support contiguous
arrays of base values. They effectively form a second set of types,
mirroring the 'single' base types. Socket connections will have to
strictly match between these types as well, i.e. any dereferencing and
array access will have to be explicit.
2015-12-22 11:07:41 +01:00
ab25e2f6c6 Sqrt math node mode, patch by lichtwerk. 2015-12-21 12:09:28 +01:00
bb96d3d29b Removed unused function declaration. 2015-12-20 11:42:39 +01:00
031c14e123 New dupli mode for use of BVM node trees to generate duplis.
Not yet functional, as it doesn't have opcodes yet.
2015-12-20 10:07:48 +01:00
83ca36a6e9 Object pointer should not be needed for constructing modifier node functions. 2015-12-18 16:27:52 +01:00
9f766ea134 Merge branch 'master' into object_nodes 2015-12-18 13:31:25 +01:00
fe3657a575 Use the bvm function cache for modifier nodes, to avoid recompiling all the time. 2015-12-16 13:43:36 +01:00
5353ae384d Separation of dependencies of node trees and their users for compiling vs. evaluation.
So far any change in a node tree would cause both a recompile of bvm functions
as well as a re-evaluation of any users of that function. This is quite inefficient
and should be separated to allow caching of the bvm functions independent from
their users.

To this end the nodes now have 2 callbacks: one for getting compile deps, the other
for getting eval deps.
* Compile dependencies are typically other node trees (node groups). In the future
  this could also be Text datablocks, similar to how OSL script nodes work.
* Eval dependencies are all the blend_data blocks that a function might access.
  For modifier nodes these could typically be meshes, curves; for shaders could
  be images, textures; and so forth.

Separating these dependencies means the bvm functions will have to be recompiled
only when the actual bNodes change (add/remove, linking, socket values).
Conversely when some modifier input data changes (editing, cfra) the modifier
function will be re-evaluated.
2015-12-16 13:25:46 +01:00
d736d8073b Use C callbacks for implementation of DepsNodeHandle.
This makes it possible to create generic dependency functions to
handle dependencies in various ways, using the same reporting callback.
Currently used for depsgraph building in 2 passes (nodes & relations).
2015-12-16 09:01:20 +01:00
69687b7c5c Removed default case for the opcode switch, all opcodes should be handled explicitly. 2015-12-15 07:58:38 +01:00
3cb01d1409 Merge branch 'master' into object_nodes 2015-12-14 13:58:32 +01:00
caec65686f Explicit depsgraph tagging for object nodetree is not necessary any more. 2015-12-14 13:56:51 +01:00
929324995f Extension of depsgraph API to handle the relations between node trees.
This allows node groups and similar nodes with a node tree ID pointer
to register in the depsgraph.

In addition to defining relations, the builder must also make sure
that the node tree depsnodes are created first, because, unlike objects,
node trees depsnodes have no direct scene connection and are not generated
in advance. Since the build process has two distinct steps for creating
nodes and relations, the same API is used for both to simplify the code.
2015-12-14 12:19:14 +01:00
6b97c36df3 Generalization of function caching to avoid unnecessary recompilation.
The function cache allows callers to store functions in a cache (hash table).
The functions also have a reference count, so replacing the function
in the cache (when the node tree changes) does not immediately delete
the current instance. This allows background threads to keep using the
old function until they can cleanly return (tasks should be restarted
when the nodes become outdated, but this is up to the caller system).
2015-12-14 08:16:35 +01:00
e6bf664d78 New data type for constant (!) strings.
The const-ness is very important: strings are only stored as const char*
on the stack, which point to memory inside the instructions list.
The instructions contain the actual char array, with a null terminator.

This does not allow allocating new strings during eval, but it makes
it possible to use static strings as identifiers and keys for global data.
Eventually we could allow string operations through an allocation system
similar to DerivedMesh handling, with init/release nodes to manage
alloc/free.
2015-12-12 12:40:30 +01:00
465327ff9f Merge branch 'master' into object_nodes 2015-12-12 11:56:39 +01:00
434123a6ea Use the relative transform of target objects and the modified object to adjust modifiers.
This affects modifiers which use an external target object (currently
boolean and curve path). The modified object is a graph input argument,
which the target object is looked up via its key. The relative transform
means the values calculated from external geometry are always in the
modified object's local space.

Note that transform and its inverse are provided explicitly to nodes.
This will allow optimization for constants later on.
2015-12-11 18:30:25 +01:00
9f01d87ddf Merge branch 'master' into object_nodes 2015-12-11 16:24:16 +01:00
6bb58ce842 Boolean modifier node, based on the new bmesh boolean operations. 2015-12-11 16:11:17 +01:00
5dd13527b9 Merge branch 'master' into object_nodes 2015-12-11 10:55:12 +01:00
6f11cf2400 Clamp the curve parameter in the curve path eval, because where_on_path is touchy about it. 2015-12-11 09:46:36 +01:00
e94400084c Reenabled the depsgraph relations for nested node trees, for the time being.
This should also work through the API! However, it requires building the nodetree
depsnodes before making relations which is not well supported yet.
The forced relations are currently needed to make updates inside the component
node trees trigger object recalc.
2015-12-11 09:44:41 +01:00
9f584095d7 Minimal RNA API of the depsgraph for registering object node dependencies.
This simply reflects the existing C API for the depsgraph, as already used
by modifiers. The object nodes gain two callbacks, one for depsgraph
relations and one for registering globals. Since both of these should
require the same objects and other ID blocks to be registered, they share
a common `relations_update` function on the pynode level for convenience.
2015-12-11 09:16:34 +01:00
99e998483b New node "Curve Path" for reading interpolated curve data.
This introduces an improved way of handling ID relations inside the
node tree. Instead of storing simple indices to an object array,
the nodes now generate a 'key' (currently just ID name + lib name).
At eval time this key is then looked up from a hash table in globals,
to produce the actual pointer to the object.

Currently the node will not work, because the curve is not yet registered
in the globals map. This should happen in conjunction with depsgraph
updates.
2015-12-10 20:26:56 +01:00
9d3dc3d57b Merge branch 'master' into object_nodes 2015-12-10 15:21:58 +01:00
b08c193d14 EvalData is now deprecated and unused, removed it. 2015-12-10 15:20:25 +01:00
bed76fe570 Removed global data from the compile process, this should only be needed for eval.
Global data is used primarily for blend_data pointers (objects primarily).
These should not be stored directly inside the function instructions,
but should be stored by a key (hash value) and resolved at eval time.
2015-12-10 15:17:54 +01:00
87cf7d85f5 A number of actual value nodes for simple input constants in the UI. 2015-12-10 14:23:26 +01:00
d5d35d5b15 Moved debugging code output node graph into a utility file. 2015-12-10 12:51:47 +01:00
2e3f780118 Represent local output behavior in the graphviz debug by showing additional links. 2015-12-10 12:37:33 +01:00
e839d2f39a Fix for graph debug: input arguments refer to outputs, can just use the ARG nodes themselves. 2015-12-10 12:01:49 +01:00
2bf4d8f1ae Partial revert: need to allow pointer/mesh value nodes and constants.
These are generated automatically as terminators in pass node chains.
No pointer/mesh values will be stored in instructions though, the
sockets are just dummies to ensure a consistent value node signature.
2015-12-10 11:51:29 +01:00
a30a863a54 Removed 'Value' node types for pointer and mesh data, and disallow hardcoding them as constants.
Pointers in the instruction lists are bound to be invalid most of the time. They should only be
supplied externally via graph input arguments.

Note that opcodes still exist for POINTER/MESH, but these always store a NULL/empty DM
default value, rather than reading from instructions. They are only used by the code generator
as fallbacks if such sockets are not connected.
2015-12-10 11:23:31 +01:00
8432aac5f6 'Value' nodes are actually regular function nodes, not pass-type nodes. 2015-12-10 11:21:51 +01:00
61e5f39eb8 Removed unused code. 2015-12-10 11:13:29 +01:00
5fc8222bab Basic randomization node, producing PRNG values based on either int or float input. 2015-12-10 09:40:50 +01:00
d551b56680 Use a different variable name to prevent shadowing. 2015-12-09 16:29:09 +01:00
61d847f101 Displacement modifier is always expected to affect mesh normals. 2015-12-09 16:27:41 +01:00
8e6177520c Have to ensure correct normals after running modifier nodes. 2015-12-09 16:27:19 +01:00
a50dfeade6 Added procedural Clouds and Voronoi texture nodes to python for general use. 2015-12-09 16:23:00 +01:00
fd2b0e1365 Added vector multiply/divide modes to the vector math node.
In combination with implicit float->vector conversion these can also
be used for simple scalar multiplication. This is not quite ideal
because of the conversion, but math nodes have to be redesigned at
some point anyway.
2015-12-09 15:50:33 +01:00
7b83720817 Some simplifying python functions for copying existing enum properties. 2015-12-09 15:44:14 +01:00
10387fa3ae Added missing draw functions for euler angle nodes. 2015-12-09 15:24:21 +01:00
aa6d62132d New modifier node for generic vertex displacement. 2015-12-09 14:52:31 +01:00
c2722fbc5e Use 'local' output values to override input argument nodes.
This reenables the iteration input used by the array modifier node.
2015-12-09 13:02:30 +01:00
9b1456ba37 Unified handling of both the main function and expression functions. 2015-12-09 11:02:57 +01:00
c7f44335fa Splitting the codegen function into a 'symbol resolve' part and a 'codegen' part.
This basically introduces a linker step which will allow the proper use of function calls.
2015-12-09 10:45:12 +01:00
31e7eb9a13 'Local' value type for outputs to indicate their use as local function arguments. 2015-12-08 21:31:02 +01:00
32becc1813 Use two distinctive structs for node type inputs and outputs.
This helps clarity, and also we need to start using different
value types for inputs and outputs.
2015-12-08 17:26:23 +01:00
be82139b91 Renamed ValueType to InputValueType, because we will need to also have an OutputValueType. 2015-12-08 16:58:28 +01:00
de0933f0aa Replaced EvalData for node evaluation with graph inputs.
Warning: this disabled the iteration input for mesh arrays. To make it
work again the mesh array kernel needs to overwrite the input argument.
2015-12-08 14:50:55 +01:00
306235fa70 Use formal node graph inputs to create formal function arguments and initialize the stack. 2015-12-08 14:21:07 +01:00
079ecfde22 Graph inputs/outputs need an explicit type, since they may not have a node after optimizing. 2015-12-08 12:45:09 +01:00
e493f2039e Keep a list of input arguments of a function in addition to return values. 2015-12-08 12:36:16 +01:00
0b80bb6bb8 Get rid of the extra list of "outputs" for subgraph codegen.
Instead we now pass a socket index map directly to subgraph codegen,
and then read out the final output indices externally.
2015-12-08 12:09:02 +01:00
bc91cba012 Pass input arguments as const void* when calling bvm functions.
This is not used yet, but will replace the EvalData pointer.
2015-12-08 11:11:39 +01:00
00d9beda03 New set of node types for 'arguments' which will act as stack entry placeholders.
These are like value nodes in that an output socket stack entry is reserved for them.
However, like 'pass' nodes they don't actually perform an operation. Their purpose is
to provide a place on the stack for input arguments that other nodes can then read from.
2015-12-08 10:24:16 +01:00
d17a937e89 Expose the get_input function of the node graph just like get_output. 2015-12-08 10:15:20 +01:00
7ec91558f8 Bump the BVM stack size to 4095.
Currently there is no optimization for stack usage, which would ultimately
reduce the required stack size dramatically. 255 is still very low though.
2015-12-07 17:12:58 +01:00
7ef782f1a7 Use individual node types for constructing transform matrices.
Transforms can be created as translations, rotations (euler and axis/angle)
and scale.

The UI nodes include and automatic multiplication node for convenience.
2015-12-07 17:08:36 +01:00
d103f7daab Use an explicit transform input in the array modifier node.
Transforms can only be created from translations atm.
2015-12-07 13:50:03 +01:00
794e16591b Fix for mismatching socket type identifiers.
Have to be careful about distinguishing socket type identifiers
and bvm type identifiers.
2015-12-07 13:49:02 +01:00
3f770bcfeb Fix for ugly socket color because of swapped G and B ... 2015-12-07 13:19:01 +01:00
026ad8d2f9 Merge branch 'master' into object_nodes 2015-12-07 12:37:16 +01:00
17d6b2f158 Some basic math operations for 4x4 matrices. 2015-12-07 12:24:11 +01:00
b985176b57 Moved math eval functions to a dedicated file. 2015-12-07 11:43:38 +01:00
6f99c84123 Introduced a UI node socket type for affine transforms.
This matches the matrix44 internal bvm type. It is useful particulary
for describing rotations.
2015-12-07 09:31:48 +01:00
0665d467ad Fixed and improved the socket conversion function. 2015-12-07 08:47:15 +01:00
02c3eccc31 Cleanup: Renamed socket type utility functions for clarity. 2015-12-06 17:59:41 +01:00
063b5351df Moved the socket converter function into the socket_type module. 2015-12-06 17:25:56 +01:00
d67aab6467 Fix for re-entrant update problems, using a base class with a context manager. 2015-12-06 15:23:52 +01:00
37ac434577 Make node groups work by linking proxy nodes to the external sockets of the parent node graph. 2015-12-06 13:43:32 +01:00
b3bfc8915e Leave the creation of proxies for bNode inputs/outputs to the node compiler. 2015-12-06 13:01:32 +01:00
c6e593d269 New utility module for socket types. 2015-12-06 12:55:10 +01:00
37b980565a Node compiler function for adding proxy nodes. 2015-12-06 12:49:16 +01:00
36e09d2a4e Generalize the node compiler functions a bit to prepare for node groups. 2015-12-06 12:10:37 +01:00
084265454e Moved type conversion utility functions to the common_node module. 2015-12-06 11:37:43 +01:00
19d44991f8 Use update callbacks to sync sockets of group input/output nodes to the interface items. 2015-12-06 11:26:07 +01:00
7c421555bf Use a general update function to update all the nodes that are affected by a group interface.
This is not particularly nice, because it relies on every interface variable to call the
update explicitly. Eventually such things should work via the depsgraph, but this is
currently not easy to do.
2015-12-05 17:14:13 +01:00
57b63e66b5 Register node trees only after creating associated group types.
That way the node group definition can update the node tree type before.
2015-12-05 16:44:02 +01:00
a4ab2d71d6 Added lists of inputs and outputs to node trees for defining the group interface. 2015-12-05 16:09:23 +01:00
6b55e29baf Rudimentary node group classes for an instance node and inputs/outputs.
The node group instance prevents recursive groups by disallowing nested
node trees, both when selecting a different group tree for an existing
node instance, and when adding an existing node to a tree (copy/paste).
2015-12-05 11:32:34 +01:00
0b6ddb5112 Fix for keymap quirk not resetting default property values.
Keymap entries have to use explicit values for properties if they
are modified in any of the variants. Otherwise the value is not
reset to the default in subsequent calls once it gets changed.
2015-12-05 11:29:41 +01:00
10157551be Object node id property poll function should be a regular function rather that a classmethod. 2015-12-05 11:27:59 +01:00
051706bf95 Restrict the ObjectNodeEdit operator to only work on the object nodes.
We want to keep this separate from shader/compo/tex nodes which have
their own node group operators.
2015-12-05 08:36:30 +01:00
f57cfa892f Reorganize python scripts for object nodes into their own script directory. 2015-12-04 18:08:11 +01:00
31d0960734 Merge branch 'master' into object_nodes
Conflicts:
	source/blender/makesrna/intern/rna_nodetree.c
2015-12-04 17:17:52 +01:00
2bac0260a6 Removed useless pass statement. 2015-12-04 13:42:32 +01:00
15689a42fb Better implementation of socket updates for list-style node.
The previous implementation was based on recreating links and did not work
very well when reordering connections, because the insert_link callback does
not allow changing the link target.
2015-12-04 13:35:20 +01:00
3d9fc9016e List behavior for the mesh-combine node.
This is primarily a python implementation for UI convenience.
It makes the list of input sockets behave dynamically for typical list operations:
* adding an element at the end
* inserting an element
* removing an element

Each of these keeps the list compact and shifts remaining sockets, so users don't
have to move each individual connection every time.

Internally it still uses the simple binary combine operation, adding as many
nodes as necessary.
2015-12-04 11:39:36 +01:00
22b2698243 Merge branch 'master' into object_nodes 2015-12-04 10:26:16 +01:00
b475180a57 Merge branch 'master' into object_nodes 2015-12-04 09:20:30 +01:00
8b5af7f3ca Disable explicit update calls _while_ the modal node link operator is running.
These update calls can have bad consequences such as removing node sockets,
which should not happen until after the operator is finished. This was already
questionable in the past. At some point all update handling for nodes should go
through the depsgraph rather than the current fragile update flag/callback system.
2015-12-03 15:33:30 +01:00
fb1ddcc7c1 Merge branch 'master' into object_nodes 2015-12-03 13:04:54 +01:00
48ee73d500 Simple node for concatenating 2 meshes into one. 2015-12-02 17:41:12 +01:00
3675a0fedf Ignore nodes that don't have the 'compile' method, to allow frames. 2015-12-02 17:40:24 +01:00
5ab6b6bbac Added back automatic type conversion.
Now automatic type conversion for sockets happens in the python code.
2015-12-02 13:05:25 +01:00
343c1e3006 Fix for refcounting in the mesh value node.
This node was overwriting the entire stack pointer (incl. the refcount)
but should only store the DM itself.
2015-12-02 12:04:29 +01:00
fe2c73db61 Make sure invalid node connections are rejected at the basic level.
The internal bvm nodes require strict type matching. Any implicit
automatic type conversions should be added on the level of DNA->bvm
conversion. This keeps the bvm nodes simple, and also allows for
semantics on the DNA node level that could not be properly implemented
in bvm.
2015-12-02 11:48:39 +01:00
120ea1179e Improved python API for constructing the internal node graph.
Socket connections can now be handled consistently through single py objects,
so the compilation code becomes more concise and readable.
2015-12-02 11:29:44 +01:00
3f71a178e1 Fix for dangling root sockets when skipping 'pass' nodes.
This can happen when proxies are created, and should always create
a 'value' node to act as a clean root terminator.
2015-12-02 11:28:35 +01:00
d53946ad7e Improved RNA API for bvm node graphs.
Now there are actual collections of inputs/outputs to perform proper checks
on valid names/indices and types.
2015-12-01 18:16:35 +01:00
723c51313c Sanity check for array count <= 0, otherwise CDDM keeps spewing warnings about empty mesh. 2015-12-01 11:04:24 +01:00
e431c5bde6 Added an "Iteration" node as a general-purpose input for expressions.
This is used by the Array modifier node to give a meaningful per-instance
input to calculate a transform from.
2015-12-01 09:52:07 +01:00
91a0b2a8ea Use the jump address in the array modifier to evaluate a transform function per copy. 2015-12-01 08:52:45 +01:00
d125723719 Codegen: for function inputs store the entry point in the instructions. 2015-11-30 16:16:45 +01:00
962478523e Generate instructions for a subgraph in a separate codegen function.
This will be useful for separately generating kernel functions, which
are to be stored as own code blocks so kernels can call them repeatedly
as needed.
2015-11-28 17:07:11 +01:00
dbd3d6d55c Fix for API changes in pynodes. 2015-11-26 14:12:50 +01:00
276b533ffe Fix for stack index assignment to graph outputs. 2015-11-26 14:12:30 +01:00
6db9c275f3 Use a simple value node for graph outputs that are only connected to pass nodes. 2015-11-26 12:47:12 +01:00
11c34a0934 Changing graph output mechanism to use proxy nodes. 2015-11-26 11:13:11 +01:00
1254009072 Distinguish 'function' and 'kernel' node types.
Only kernel nodes will be allowed to have function inputs. This is
necessary because any kernel node will define the boundaries of
node subtrees used for function inputs.
2015-11-25 13:55:20 +01:00
803f7f208c Node inputs now have a 'value type' to specify how input connections are treated.
VALUE_CONSTANT inputs can not have connections, their values are known at compile time.
bvm stores these values directly in the instruction list.

VALUE_VARIABLE inputs store values at evaluation time. bvm stores a stack index for them
which is used to load and store from/to the evaluation stack.

VALUE_FUNCTION inputs are passed to kernels to be called internally when needed.
bvm stores an instruction index and allows a jump to this instruction (TODO).
2015-11-25 12:29:39 +01:00
60779ad90e Added an 'entry point' instruction number to functions.
This is currently always 0, but will be used in the future to allow
storing per-element functions along with the main code. These can then
be called within kernels.
2015-11-25 11:27:37 +01:00
9d0ffa84ce Enabled generic math nodes for modifier node trees. 2015-11-25 11:12:05 +01:00
458ba77ff7 Fix for static empty mesh variable, used as default value of meshes on the stack.
This creates a (minor) mem leak when statically creating the mesh. Instead it
should be constructed in a init/free pair of functions.

Because this variable is used in all different compile units, each of them has
to create their own global 'empty_mesh' variable.
2015-11-25 10:51:28 +01:00
ca6f1efe5d Fixed missing delete call for unused nodes. 2015-11-25 10:01:36 +01:00
527f7d5088 Free the modifier bvm function after use.
Note that eventually these should be cached to avoid unnecessary
recompilation, but for now they get compiled on every modifier eval.
2015-11-25 09:58:10 +01:00
d54eca15d6 Use the guardedalloc new/delete overloads for relevant classes. 2015-11-25 09:53:01 +01:00
044cb7eaf0 Fixed overzealous assert for input stack assignments in codegen.
For constant inputs no stack index is needed. Previous to node pruning
this did not trigger the assert because there were still pass nodes
allocating the stack indices.
2015-11-25 09:29:39 +01:00
170f158b80 Node tree pruning function for removing unused nodes.
This also removes the placeholder 'pass' nodes, which were already
being skipped and made unused.
2015-11-25 09:28:48 +01:00
df9f633da2 Changed node instance storage in the node graph to pointers.
This makes it much easier to optimize the graph by removing and reconnecting nodes.
2015-11-25 09:09:30 +01:00
124bc03035 Merge branch 'master' into object_nodes
Conflicts:
	source/blender/blenkernel/intern/softbody.c
2015-11-24 09:40:33 +01:00
8c17d8e462 Use the base mesh as a fallback result in case no geometry nodes exist. 2015-11-23 12:50:18 +01:00
d4e67dfe37 Fix for store/load of mesh_ptr on the stack.
Most actual mesh operations should only store the data pointer itself
but not modify the refcount.
2015-11-23 12:29:18 +01:00
591e485054 Fix for wrong index in codegen.
Was using the socket instance map sizes rather than the overall number
of sockets of the node type.
2015-11-23 11:42:11 +01:00
71402ca5d9 Added a matrix compose/decompose node for loc/rot/scale. 2015-11-23 11:07:07 +01:00
b1c8112980 Horrible fix for depsgraph/notifier updates through property changes in geometry nodes.
This is really awful, but we don't have a good generic way of defining node tree relations
in the dependency graph yet. More importantly, the notifier system is not up to the task -
putting the responsibility for notifying into operators requires anticipating their effects,
which is not good at all for node operators which affect geometry through complex processing.
The depsgraph really should be handling this.
2015-11-23 10:14:53 +01:00
59080a1d81 Implementation of a simple 'Array' modifier node. 2015-11-22 15:24:07 +01:00
66bb6de449 Fix for invalid comparison operator of SocketPair. 2015-11-22 11:18:35 +01:00
f375f6e6dc Notifier from node changes to redraw the viewport when geometry nodes are updated.
This is a hack! The nodes are defined in python and the notifier is currently
triggered far to broadly, but currently there is no nicer way of doing it.
2015-11-22 10:05:25 +01:00
148ac78b4a Extension of the new dependency graph relations to support object nodes.
This generally triggers a mesh data recalc when *anything* inside the
object node tree is changed. Eventually it should be more specific to
changes in a geometry node tree, but the current design of deps nodes
does not reflect such internal node semantics nicely (although new
depsgraph will allow us to do it properly in the future).
2015-11-22 10:03:01 +01:00
5956bed117 Revert "Fix for unfreed memory of the default empty mesh."
This reverts commit 0ab9e4848d.
2015-11-21 17:20:23 +01:00
0ab9e4848d Fix for unfreed memory of the default empty mesh.
When using a static variable for this it needs to be destroyed explicitly.
2015-11-21 17:00:27 +01:00
6fb22ddfed Reference counting for mesh_ptr variables on the stack.
Any extensive data stored as a pointer on the stack should be ref-counted,
so that it stays alive only as long as used by some node.

The way this works is by enclosing instructions that access the stack
entry with 'init'/'release' opcodes. These are added automatically based
on output socket types (nodes don't have to be created explicitly for them).
2015-11-21 11:56:01 +01:00
9188ac0896 Merge branch 'master' into object_nodes 2015-11-21 11:35:30 +01:00
cc31a5696d Extended graphviz debug printing to also show the graph input/output connections. 2015-11-20 17:37:02 +01:00
1074abc470 Node graph optimization: skip over 'pass' nodes.
These nodes don't have opcodes any more, they are merely placeholders
to simplify node graph construction. Ultimately they will be removed
in the 'finalize' function, along with any other unreachable nodes.
2015-11-20 17:01:43 +01:00
6ee2d69201 Removed unused function declaration get_node_type_from_opcode 2015-11-20 16:03:58 +01:00
5d99ad37ea Use a single geometry subtree also for the graphviz debug function. 2015-11-20 10:22:41 +01:00
4aaa1bed74 Use the geometry subtree in object nodes rather than the toplevel node tree.
This is currently a hack, since only a single geotree is used. Eventually
all geometry subtree result should just be combined.
2015-11-20 10:12:35 +01:00
73bbfe5711 Removed unused code. 2015-11-20 09:58:33 +01:00
da90b8ef79 Added a 'PASS_MESH' node. 2015-11-19 17:19:43 +01:00
07a30be179 Make an extra copy of the resulting node DM after eval.
This is necessary unfortunately because of the unreliable nature of dm->needsFree.
Without it the BKE_object_free_derived_caches function can destroy our static
empty DM at any point.
2015-11-19 17:18:11 +01:00
79dcd08a8a Added an assertion to make sure we don't add invalid node instances with unknown types. 2015-11-19 17:01:46 +01:00
a30be36030 Added a graphviz debug dump function for the object modifier node tree. 2015-11-19 16:42:03 +01:00
8a4fbdcbb4 Use the default output value for graph returns in case they remain unlinked.
In case of meshes this will always be an empty mesh, but it at least gives a valid return value.
2015-11-19 16:12:36 +01:00
ceb9eba6bd Foundations for a mesh data type in bvm 2015-11-19 15:50:36 +01:00
950e2644e8 Mesh type for storing DerivedMesh as a temporary storage on the node eval stack. 2015-11-19 09:59:30 +01:00
a7bfdb0cdf Use a full TypeDesc in node sockets.
For the time being this is synonymous with the base type, but in future
it could allow (fixed-size) arrays and vector semantics.
2015-11-18 10:21:16 +01:00
0c2cfb44f0 Set of basic node classes for representing modifiers in pynodes. 2015-11-18 10:20:49 +01:00
5de05567f9 Simple integration of object nodes into the modifier stack evaluation. 2015-11-18 10:20:19 +01:00
88dcc8566c Merge branch 'master' into object_nodes 2015-11-18 09:27:08 +01:00
6d9406453a Removed an unconventional typename use that causes problems with MSVC. 2015-11-10 10:59:59 +01:00
1e84d69d72 Refactor: renamed 'Expression' to 'Function'. 2015-11-09 16:16:42 +01:00
fbdaaa72e9 Removed unused deprecated code parts. 2015-11-09 13:22:01 +01:00
dec5472349 Disabled some unused function args. 2015-11-08 12:20:26 +01:00
f37d7ed83b Merge branch 'master' into object_nodes 2015-11-08 09:35:20 +01:00
238e2389c0 Add support for texture node trees in new dependency graph. 2015-11-07 17:15:28 +01:00
b03095919a Added clouds noise pattern node. 2015-11-06 17:04:41 +01:00
1d67149c59 Use the material blending function for the RGB mix node for the time being. 2015-11-06 11:47:45 +01:00
d3bc6dcb67 Added the RGB mix node (unfinished). 2015-11-05 17:56:55 +01:00
151ed70fc0 Fix for debug output to avoid backward links when inputs/outputs share a name. 2015-11-05 11:09:41 +01:00
7e50fc041d Added some more opcodes for scalar multiplication and division. 2015-11-04 17:39:20 +01:00
2330dae3ef Added optional automatic datatype conversion for nodes.
This only applies to a handful of common types that can be unambiguously converted.
In any other case the link is considered invalid (proper error handling still needed).
2015-11-04 14:08:59 +01:00
06c957fc70 Made node name arguments optional.
Node names are only used for identifying them in debugging, but
can just be autogenerated as well.
2015-11-04 13:43:39 +01:00
c64c3e41e3 Make the compose/decompose and scalar math nodes work for textures. 2015-11-04 11:39:59 +01:00
84ab551f35 Missing C header for the vfprintf function. 2015-11-04 11:22:33 +01:00
255edd977f Merge branch 'master' into object_nodes 2015-11-04 11:05:49 +01:00
fd1a206f92 Added explicit vector input socket to the procedural texture nodes. 2015-11-04 11:03:02 +01:00
498ca41b8a Added graphviz debug output for parsed bvm node graphs. 2015-11-03 13:51:32 +01:00
6bb619039b Cleanup for the texture node compiler API functions. 2015-11-03 11:02:51 +01:00
965cae5a7b Removed unused code. 2015-11-02 14:27:22 +01:00
3561b4ca36 Use an object pointer from the evaluation data, rather than storing just indices. 2015-11-02 14:23:44 +01:00
09f875e164 Pointer type for passing opaque DNA references and the like through the VM. 2015-11-02 12:44:12 +01:00
e98a35220d Moved the conversion of bNodeTree (DNA/pynodes) to python code for simplicity.
This has several advantages over doing the same in C/C++ code:

- The two parts of the code are clearly separate (parsing DNA settings vs. building and evaluating)
- UI constructs with modes, special cases, etc. can be done in py, heavy lifting still happens in C
- Scripters can easily add own nodes without having to deal with internals
2015-11-01 12:41:49 +01:00
1591616e37 Added first procedural texture node (voronoi). 2015-10-30 10:23:32 +01:00
175e041ddf Texture coordinates node. 2015-10-29 12:31:06 +01:00
846a7c7467 Invalidate the texture bvm program cache when the Tex datablock is updated. 2015-10-29 12:13:07 +01:00
d86fae6d84 Start of a texture node replacement using the bvm system. 2015-10-29 11:19:44 +01:00
a067dccf65 Staged construction of node graphs from bNodeTrees through a "parser".
This wraps mapping of sockets and links in a nice small API.
2015-10-28 17:52:04 +01:00
3692460b5c Added a float4 type for rgba colors mostly. 2015-10-27 12:32:34 +01:00
e0f6b915e8 Internal support for 4x4 matrices in the bvm types. 2015-10-27 10:16:23 +01:00
e5bb9709e6 Renamed 'effector' data to 'point' data. 2015-10-26 13:08:16 +01:00
73de04b202 More vector math node modes. 2015-10-26 12:22:31 +01:00
e3ea07adc4 Effector closest-point node for mesh-based for fields. 2015-10-26 11:32:54 +01:00
2394fe7fbf Merge branch 'master' into object_nodes 2015-10-26 09:34:42 +01:00
5f70cc6c8d Added globals as a distinct argument to the eval function. 2015-10-22 22:52:10 +02:00
bd9f26871e Support for constants as internal node socket inputs.
Constants should never be linked to other nodes (will be ignored).
2015-10-22 14:14:04 +02:00
b229fac8a0 Added an integer type for node sockets. 2015-10-22 13:45:35 +02:00
c9803d3a29 Cleanup: removed unused test code. 2015-10-21 17:24:04 +02:00
abb8eba2ab Fix for multiplicity of internal socket mapping.
A Blender bNode input socket can represent multiple internal node inputs,
so mapping for links must use a set rather than a single socket.
2015-10-21 13:00:38 +02:00
a9f47080d8 First input node: getting basic properties of the "effected" point. 2015-10-21 11:47:26 +02:00
f9f2acfce1 Complementary separate/combine nodes for vectors. 2015-10-21 10:33:42 +02:00
b6e821ee72 Added all the scalar math modes. 2015-10-20 13:57:52 +02:00
76890d8285 Cleanup: Separate folders for compiling nodes and for executing the resulting bvm programs. 2015-10-20 10:46:10 +02:00
8ea69ffbc7 Use a map to ensure proper links between internal nodes.
Socket names usually don't match the internal nodes exactly.
2015-10-19 18:11:29 +02:00
d47b643874 Added a topological sorting pass to make sure nodes are compiled in the right order. 2015-10-19 16:38:05 +02:00
6a890c568e Some simple math nodes to test node connections. 2015-10-19 16:18:05 +02:00
0d751648f8 Test of node conversion from bNodes to internal instruction graph. 2015-10-19 12:16:48 +02:00
e1a6f41fc9 Next compiler step: convert internal node graph to opcode instructions. 2015-10-19 11:17:49 +02:00
e20e6e49ef init/free functions for blenvm to have a place for global initializations. 2015-10-18 16:45:48 +02:00
18815cfaaf First test of the VM evaluation function. 2015-10-18 15:48:09 +02:00
522295f4f7 Create expression return values based on node tree outputs. 2015-10-11 15:02:47 +02:00
b8a4646856 Invoke the BVM expression eval for effectors. 2015-10-11 12:24:55 +02:00
4a239bc2ff Integration of BVM into the effector system for using programmable expressions there. 2015-10-10 10:48:59 +02:00
ec314ae15f Use a dedicated struct EffectorContext for storing results of effector
lookup rather than a plain ListBase.

This paves the way for future inclusion of evaluation context info in
the EffectorContext struct, and hides some of the annoying details of
the ListBase double dereferencing.
2015-10-10 10:26:18 +02:00
bbb5ed35b1 Function for converting a bNodeTree into the internal low-level bvm node graph. 2015-10-09 15:33:08 +02:00
80b6a5e29c Merge branch 'master' into object_nodes 2015-10-09 15:04:09 +02:00
5a5dcc509d Copied the nodegraph classes from the llvm test branch. 2015-10-08 15:11:16 +02:00
f99359418c Added "expressions" as a reduced definition of a function for evaluating instruction lists. 2015-10-08 10:36:30 +02:00
84485606a7 Merge branch 'master' into object_nodes 2015-09-19 08:51:48 +02:00
0590430509 Fix minor error from strict pointer casts. 2015-09-17 10:12:27 +02:00
a358a5734f API for adding and deleting BVM functions. 2015-09-11 14:26:09 +02:00
849b5aec20 New bf library 'BlenVM' ("Blender Virtual Machine", BVM), as a general purpose runtime node backend.
This library provides a way to register modules and functions. Functions are simple
opcode-based descriptions of functionality (programs). They can be evaluated with
a simple interpreter using monolithic kernels, or could be compiled into more
optimized languages via LLVM or OpenCL.
2015-09-11 13:53:34 +02:00
bb5da70b5d Fixed categories for nodes, so only the appropriate nodes for each tree
type are used.
2015-09-11 10:27:28 +02:00
a565324f15 Use the familiar tab/ctrl+tab keymap for opening/closing nodes. 2015-09-11 10:27:28 +02:00
80a149c1eb Some basic nodes for nesting force fields inside the object nodes. 2015-09-11 10:27:28 +02:00
d2442ac1cf Registering an id property type for ObjectNode subclasses is optional. 2015-09-11 10:27:28 +02:00
347e2152db Added an optional poll function for the generic id property of
ObjectNodes.

This allows more detailed polling of ID blocks, beside the basic type.
2015-09-11 10:27:28 +02:00
3694a7bdfc Fix for registering RNA classes with registered parent functions.
The recursive registration for functions uses a simple int array for
flagging found functions. This is shared with the parent, so any child
functions will overwrite parent function flags for the same index
(this is not overloading).

The patch now requires using a larger array that can accomodate all
registerable functions from parents and children. It puts flags for
parents first, then children.
2015-09-11 10:26:06 +02:00
d868990224 A new base type for object nodes.
This includes a generic 'id' pointer for a single ID datablock pointer
in the node. The ID type can be defined using the `bl_id_property_type`
registerable attribute.
2015-09-11 10:25:49 +02:00
4cc10122f2 Context function for getting the object nodes in the node editor. 2015-09-11 10:25:38 +02:00
0cd3fef301 A basic Object node tree pointer property for use as component nodes. 2015-09-11 10:24:59 +02:00
1416 changed files with 64185 additions and 135459 deletions

6
.gitignore vendored
View File

@@ -33,9 +33,3 @@ Desktop.ini
/doc/python_api/sphinx-in-tmp/
/doc/python_api/sphinx-in/
/doc/python_api/sphinx-out/
/doc/python_api/rst/bmesh.ops.rst
/doc/python_api/rst/in_menu.png
/doc/python_api/rst/menu_id.png
/doc/python_api/rst/op_prop.png
/doc/python_api/rst/run_script.png
/doc/python_api/rst/spacebar.png

File diff suppressed because it is too large Load Diff

View File

@@ -25,8 +25,7 @@
ARGS=$( \
getopt \
-o s:i:t:h \
--long source:,install:,tmp:,info:,threads:,help,show-deps,no-sudo,no-build,no-confirm,\
with-all,with-opencollada,\
--long source:,install:,tmp:,info:,threads:,help,show-deps,no-sudo,no-build,no-confirm,with-all,with-opencollada,\
ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,ver-osd:,ver-openvdb:,\
force-all,force-python,force-numpy,force-boost,\
force-ocio,force-openexr,force-oiio,force-llvm,force-osl,force-osd,force-openvdb,\
@@ -282,9 +281,8 @@ SUDO="sudo"
NO_BUILD=false
NO_CONFIRM=false
USE_CXX11=true # Mandatory in blender2.8
PYTHON_VERSION="3.5.2"
PYTHON_VERSION="3.5.1"
PYTHON_VERSION_MIN="3.5"
PYTHON_FORCE_BUILD=false
PYTHON_FORCE_REBUILD=false
@@ -317,7 +315,7 @@ OPENEXR_FORCE_REBUILD=false
OPENEXR_SKIP=false
_with_built_openexr=false
OIIO_VERSION="1.7.8"
OIIO_VERSION="1.6.9"
OIIO_VERSION_MIN="1.6.0"
OIIO_VERSION_MAX="1.9.0" # UNKNOWN currently # Not supported by current OSL...
OIIO_FORCE_BUILD=false
@@ -332,14 +330,14 @@ LLVM_FORCE_REBUILD=false
LLVM_SKIP=false
# OSL needs to be compiled for now!
OSL_VERSION="1.7.5"
OSL_VERSION="1.7.3"
OSL_VERSION_MIN=$OSL_VERSION
OSL_FORCE_BUILD=false
OSL_FORCE_REBUILD=false
OSL_SKIP=false
# OpenSubdiv needs to be compiled for now
OSD_VERSION="3.1.1"
OSD_VERSION="3.0.2"
OSD_VERSION_MIN=$OSD_VERSION
OSD_FORCE_BUILD=false
OSD_FORCE_REBUILD=false
@@ -367,7 +365,7 @@ OPENCOLLADA_FORCE_BUILD=false
OPENCOLLADA_FORCE_REBUILD=false
OPENCOLLADA_SKIP=false
FFMPEG_VERSION="3.2.1"
FFMPEG_VERSION="2.8.4"
FFMPEG_VERSION_MIN="2.8.4"
FFMPEG_FORCE_BUILD=false
FFMPEG_FORCE_REBUILD=false
@@ -705,21 +703,6 @@ if [ "$WITH_ALL" = true -a "$OPENCOLLADA_SKIP" = false ]; then
fi
WARNING "****WARNING****"
PRINT "If you are experiencing issues building Blender, _*TRY A FRESH, CLEAN BUILD FIRST*_!"
PRINT "The same goes for install_deps itself, if you encounter issues, please first erase everything in $SRC and $INST"
PRINT "(provided obviously you did not add anything yourself in those dirs!), and run install_deps.sh again!"
PRINT "Often, changes in the libs built by this script, or in your distro package, cannot be handled simply, so..."
PRINT ""
PRINT "You may also try to use the '--build-foo' options to bypass your distribution's packages"
PRINT "for some troublesome/buggy libraries..."
PRINT ""
PRINT ""
PRINT "Ran with:"
PRINT " install_deps.sh $COMMANDLINE"
PRINT ""
PRINT ""
# This has to be done here, because user might force some versions...
PYTHON_SOURCE=( "https://www.python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSION.tgz" )
@@ -756,7 +739,7 @@ OSL_SOURCE_REPO=( "https://github.com/Nazg-Gul/OpenShadingLanguage.git" )
OSL_SOURCE_REPO_UID="7d40ff5fe8e47b030042afb92d0e955f5aa96f48"
OSL_SOURCE_REPO_BRANCH="blender-fixes"
OSD_USE_REPO=false
OSD_USE_REPO=true
# Script foo to make the version string compliant with the archive name:
# ${Varname//SearchForThisChar/ReplaceWithThisChar}
OSD_SOURCE=( "https://github.com/PixarAnimationStudios/OpenSubdiv/archive/v${OSD_VERSION//./_}.tar.gz" )
@@ -783,20 +766,7 @@ OPENCOLLADA_REPO_BRANCH="master"
FFMPEG_SOURCE=( "http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2" )
CXXFLAGS_BACK=$CXXFLAGS
if [ "$USE_CXX11" = true ]; then
WARNING "C++11 is now mandatory for blender2.8, this *should* go smoothly with any very recent distribution.
However, if you are experiencing linking errors (also when building Blender itself), please try the following:
* Re-run this script with `--build-all --force-all` options.
* Ensure your gcc version is at the very least 4.8, if possible you should really rather use gcc-5.1 or above.
Please note that until the transition to C++11-built libraries if completed in your distribution, situation will
remain fuzzy and incompatibilities may happen..."
PRINT ""
PRINT ""
CXXFLAGS="$CXXFLAGS -std=c++11"
export CXXFLAGS
fi
#### Show Dependencies ####
@@ -809,7 +779,7 @@ Those libraries should be available as packages in all recent distributions (opt
* libjpeg, libpng, libtiff, [libopenjpeg], [libopenal].
* libx11, libxcursor, libxi, libxrandr, libxinerama (and other libx... as needed).
* libsqlite3, libbz2, libssl, libfftw3, libxml2, libtinyxml, yasm, libyaml-cpp.
* libsdl1.2, libglew, [libglewmx].\""
* libsdl1.2, libglew, libglewmx.\""
DEPS_SPECIFIC_INFO="\"BUILDABLE DEPENDENCIES:
@@ -983,7 +953,7 @@ prepare_opt() {
# Check whether the current package needs to be recompiled, based on a dummy file containing a magic number in its name...
magic_compile_check() {
if [ -f $INST/.$1-magiccheck-$2-$USE_CXX11 ]; then
if [ -f $INST/.$1-magiccheck-$2 ]; then
return 0
else
return 1
@@ -992,7 +962,7 @@ magic_compile_check() {
magic_compile_set() {
rm -f $INST/.$1-magiccheck-*
touch $INST/.$1-magiccheck-$2-$USE_CXX11
touch $INST/.$1-magiccheck-$2
}
# Note: should clean nicely in $INST, but not in $SRC, when we switch to a new version of a lib...
@@ -1652,10 +1622,6 @@ compile_OIIO() {
# fi
cmake_d="$cmake_d -D USE_OCIO=OFF"
if [ "$USE_CXX11" = true ]; then
cmake_d="$cmake_d -D OIIO_BUILD_CPP11=ON"
fi
if file /bin/cp | grep -q '32-bit'; then
cflags="-fPIC -m32 -march=i686"
else
@@ -1867,9 +1833,6 @@ compile_OSL() {
cmake_d="$cmake_d -D OSL_BUILD_PLUGINS=OFF"
cmake_d="$cmake_d -D OSL_BUILD_TESTS=OFF"
cmake_d="$cmake_d -D USE_SIMD=sse2"
if [ "$USE_CXX11" = true ]; then
cmake_d="$cmake_d -D OSL_BUILD_CPP11=1"
fi
#~ cmake_d="$cmake_d -D ILMBASE_VERSION=$ILMBASE_VERSION"
@@ -1944,7 +1907,7 @@ compile_OSD() {
fi
# To be changed each time we make edits that would modify the compiled result!
osd_magic=2
osd_magic=1
_init_osd
# Clean install if needed!
@@ -2472,7 +2435,7 @@ compile_FFmpeg() {
--enable-avfilter --disable-vdpau \
--disable-bzlib --disable-libgsm --disable-libspeex \
--enable-pthreads --enable-zlib --enable-stripping --enable-runtime-cpudetect \
--disable-vaapi --disable-nonfree --enable-gpl \
--disable-vaapi --disable-libfaac --disable-nonfree --enable-gpl \
--disable-postproc --disable-librtmp --disable-libopencore-amrnb \
--disable-libopencore-amrwb --disable-libdc1394 --disable-version3 --disable-outdev=sdl \
--disable-libxcb \
@@ -2599,9 +2562,8 @@ install_DEB() {
git libfreetype6-dev libx11-dev flex bison libtbb-dev libxxf86vm-dev \
libxcursor-dev libxi-dev wget libsqlite3-dev libxrandr-dev libxinerama-dev \
libbz2-dev libncurses5-dev libssl-dev liblzma-dev libreadline-dev $OPENJPEG_DEV \
libopenal-dev libglew-dev yasm $THEORA_DEV $VORBIS_DEV $OGG_DEV \
libopenal-dev libglew-dev libglewmx-dev yasm $THEORA_DEV $VORBIS_DEV $OGG_DEV \
libsdl1.2-dev libfftw3-dev patch bzip2 libxml2-dev libtinyxml-dev libjemalloc-dev"
# libglewmx-dev (broken in deb testing currently...)
OPENJPEG_USE=true
VORBIS_USE=true
@@ -4035,6 +3997,9 @@ install_OTHER() {
fi
if [ "$_do_compile_llvm" = true ]; then
install_packages_DEB libffi-dev
# LLVM can't find the debian ffi header dir
_FFI_INCLUDE_DIR=`dpkg -L libffi-dev | grep -e ".*/ffi.h" | sed -r 's/(.*)\/ffi.h/\1/'`
PRINT ""
compile_LLVM
have_llvm=true
@@ -4053,6 +4018,7 @@ install_OTHER() {
if [ "$_do_compile_osl" = true ]; then
if [ "$have_llvm" = true ]; then
install_packages_DEB flex bison libtbb-dev
PRINT ""
compile_OSL
else
@@ -4071,6 +4037,7 @@ install_OTHER() {
fi
if [ "$_do_compile_osd" = true ]; then
install_packages_DEB flex bison libtbb-dev
PRINT ""
compile_OSD
fi
@@ -4087,6 +4054,10 @@ install_OTHER() {
fi
if [ "$_do_compile_collada" = true ]; then
install_packages_DEB libpcre3-dev
# Find path to libxml shared lib...
_XML2_LIB=`dpkg -L libxml2-dev | grep -e ".*/libxml2.so"`
# No package
PRINT ""
compile_OpenCOLLADA
fi
@@ -4171,6 +4142,16 @@ print_info_ffmpeglink() {
}
print_info() {
PRINT ""
PRINT ""
WARNING "****WARNING****"
PRINT "If you are experiencing issues building Blender, _*TRY A FRESH, CLEAN BUILD FIRST*_!"
PRINT "The same goes for install_deps itself, if you encounter issues, please first erase everything in $SRC and $INST"
PRINT "(provided obviously you did not add anything yourself in those dirs!), and run install_deps.sh again!"
PRINT "Often, changes in the libs built by this script, or in your distro package, cannot be handled simply, so..."
PRINT ""
PRINT "You may also try to use the '--build-foo' options to bypass your distribution's packages"
PRINT "for some troublesome/buggy libraries..."
PRINT ""
PRINT ""
PRINT "Ran with:"
@@ -4183,12 +4164,6 @@ print_info() {
_buildargs="$_buildargs -U *OPENCOLORIO* -U *OPENEXR* -U *OPENIMAGEIO* -U *LLVM* -U *CYCLES*"
_buildargs="$_buildargs -U *OPENSUBDIV* -U *OPENVDB* -U *COLLADA* -U *FFMPEG* -U *ALEMBIC*"
if [ "$USE_CXX11" = true ]; then
_1="-D WITH_CXX11=ON"
PRINT " $_1"
_buildargs="$_buildargs $_1"
fi
_1="-D WITH_CODEC_SNDFILE=ON"
PRINT " $_1"
_buildargs="$_buildargs $_1"
@@ -4352,6 +4327,3 @@ PRINT ""
# Switch back to user language.
LANG=LANG_BACK
export LANG
CXXFLAGS=$CXXFLAGS_BACK
export CXXFLAGS

View File

@@ -94,7 +94,6 @@ all_repositories = {
r'git://git.blender.org/blender-translations.git': 'blender-translations',
r'git://git.blender.org/blender-addons.git': 'blender-addons',
r'git://git.blender.org/blender-addons-contrib.git': 'blender-addons-contrib',
r'git://git.blender.org/blender-dev-tools.git': 'blender-dev-tools',
r'https://svn.blender.org/svnroot/bf-blender/': 'lib svn',
}
@@ -129,7 +128,6 @@ def schedule_force_build(name):
forcesched.CodebaseParameter(hide=True, codebase="blender-translations"),
forcesched.CodebaseParameter(hide=True, codebase="blender-addons"),
forcesched.CodebaseParameter(hide=True, codebase="blender-addons-contrib"),
forcesched.CodebaseParameter(hide=True, codebase="blender-dev-tools"),
forcesched.CodebaseParameter(hide=True, codebase="lib svn")],
properties=[]))
@@ -145,7 +143,6 @@ def schedule_build(name, hour, minute=0):
"blender-translations": {"repository": "", "branch": "master"},
"blender-addons": {"repository": "", "branch": "master"},
"blender-addons-contrib": {"repository": "", "branch": "master"},
"blender-dev-tools": {"repository": "", "branch": "master"},
"lib svn": {"repository": "", "branch": "trunk"}},
branch=current_branch,
builderNames=[name],
@@ -267,8 +264,7 @@ def generic_builder(id, libdir='', branch='', rsync=False):
for submodule in ('blender-translations',
'blender-addons',
'blender-addons-contrib',
'blender-dev-tools'):
'blender-addons-contrib'):
f.addStep(git_submodule_step(submodule))
f.addStep(git_step(branch))
@@ -297,14 +293,13 @@ def generic_builder(id, libdir='', branch='', rsync=False):
# Builders
add_builder(c, 'mac_x86_64_10_6_cmake', 'darwin-9.x.universal', generic_builder, hour=5)
# add_builder(c, 'linux_glibc211_i686_cmake', '', generic_builder, hour=1)
# add_builder(c, 'linux_glibc211_x86_64_cmake', '', generic_builder, hour=2)
add_builder(c, 'linux_glibc211_i686_cmake', '', generic_builder, hour=1)
add_builder(c, 'linux_glibc211_x86_64_cmake', '', generic_builder, hour=2)
add_builder(c, 'linux_glibc219_i686_cmake', '', generic_builder, hour=3)
add_builder(c, 'linux_glibc219_x86_64_cmake', '', generic_builder, hour=4)
add_builder(c, 'win32_cmake_vc2013', 'windows_vc12', generic_builder, hour=3)
add_builder(c, 'win64_cmake_vc2013', 'win64_vc12', generic_builder, hour=4)
add_builder(c, 'win32_cmake_vc2015', 'windows_vc14', generic_builder, hour=5)
add_builder(c, 'win64_cmake_vc2015', 'win64_vc14', generic_builder, hour=6)
add_builder(c, 'win64_cmake_vc2015', 'win64_vc14', generic_builder, hour=5)
# STATUS TARGETS
#

View File

@@ -72,11 +72,8 @@ if 'cmake' in builder:
# Set up OSX architecture
if builder.endswith('x86_64_10_6_cmake'):
cmake_extra_options.append('-DCMAKE_OSX_ARCHITECTURES:STRING=x86_64')
cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE=/usr/local/cuda8-hack/bin/nvcc')
cmake_extra_options.append('-DWITH_CODEC_QUICKTIME=OFF')
cmake_extra_options.append('-DCMAKE_OSX_DEPLOYMENT_TARGET=10.6')
build_cubins = False
cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE=/usr/local/cuda-hack/bin/nvcc')
cmake_extra_options.append('-DCUDA_NVCC8_EXECUTABLE=/usr/local/cuda8-hack/bin/nvcc')
elif builder.startswith('win'):
if builder.endswith('_vc2015'):
@@ -93,7 +90,8 @@ if 'cmake' in builder:
elif builder.startswith('win32'):
bits = 32
cmake_options.extend(['-G', 'Visual Studio 12 2013'])
cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE:FILEPATH=C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v8.0/bin/nvcc.exe')
cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE:FILEPATH=C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v7.5/bin/nvcc.exe')
cmake_extra_options.append('-DCUDA_NVCC8_EXECUTABLE:FILEPATH=C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v8.0/bin/nvcc.exe')
elif builder.startswith('linux'):
tokens = builder.split("_")
@@ -113,7 +111,8 @@ if 'cmake' in builder:
cuda_chroot_name = 'buildbot_' + deb_name + '_x86_64'
targets = ['player', 'blender', 'cuda']
cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE=/usr/local/cuda-8.0/bin/nvcc')
cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE=/usr/local/cuda-7.5/bin/nvcc')
cmake_extra_options.append('-DCUDA_NVCC8_EXECUTABLE=/usr/local/cuda-8.0/bin/nvcc')
cmake_options.append("-C" + os.path.join(blender_dir, cmake_config_file))
@@ -183,8 +182,10 @@ if 'cmake' in builder:
print('Condifuration FAILED!')
sys.exit(retcode)
if 'win32' in builder or 'win64' in builder:
command = ['cmake', '--build', '.', '--target', target_name, '--config', 'Release']
if 'win32' in builder:
command = ['msbuild', 'INSTALL.vcxproj', '/Property:PlatformToolset=v120_xp', '/p:Configuration=Release']
elif 'win64' in builder:
command = ['msbuild', 'INSTALL.vcxproj', '/p:Configuration=Release']
else:
command = target_chroot_prefix + ['make', '-s', '-j2', target_name]

View File

@@ -1,15 +1,15 @@
# - Find JACK library
# Find the native JACK includes and library
# - Find Jack library
# Find the native Jack includes and library
# This module defines
# JACK_INCLUDE_DIRS, where to find jack.h, Set when
# JACK_INCLUDE_DIR is found.
# JACK_LIBRARIES, libraries to link against to use JACK.
# JACK_ROOT_DIR, The base directory to search for JACK.
# JACK_LIBRARIES, libraries to link against to use Jack.
# JACK_ROOT_DIR, The base directory to search for Jack.
# This can also be an environment variable.
# JACK_FOUND, If false, do not try to use JACK.
# JACK_FOUND, If false, do not try to use Jack.
#
# also defined, but not for general use are
# JACK_LIBRARY, where to find the JACK library.
# JACK_LIBRARY, where to find the Jack library.
#=============================================================================
# Copyright 2011 Blender Foundation.

View File

@@ -57,6 +57,13 @@ if(NOT LLVM_LIBPATH)
set(LLVM_LIBPATH ${LLVM_LIBPATH} CACHE PATH "Path to the LLVM library path")
mark_as_advanced(LLVM_LIBPATH)
endif()
if(NOT LLVM_INCLUDE_DIRS)
execute_process(COMMAND ${LLVM_CONFIG} --includedir
OUTPUT_VARIABLE LLVM_INCLUDE_DIRS
OUTPUT_STRIP_TRAILING_WHITESPACE)
set(LLVM_INCLUDE_DIRS ${LLVM_INCLUDE_DIRS} CACHE PATH "Path to the LLVM include directory")
mark_as_advanced(LLVM_INCLUDE_DIRS)
endif()
if(LLVM_STATIC)
find_library(LLVM_LIBRARY
@@ -80,6 +87,9 @@ if(LLVM_LIBRARY AND LLVM_ROOT_DIR AND LLVM_LIBPATH)
OUTPUT_VARIABLE LLVM_LIBRARY
OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REPLACE " " ";" LLVM_LIBRARY "${LLVM_LIBRARY}")
# libterminfo is missing in llvm-config --libfiles
set(LLVM_LIBRARY ${LLVM_LIBRARY} tinfo)
endif()
endif()

View File

@@ -27,12 +27,13 @@ if(EXISTS ${SOURCE_DIR}/.git)
OUTPUT_VARIABLE MY_WC_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND git branch --list master blender-v* --contains ${MY_WC_HASH}
execute_process(COMMAND git branch --list master --contains ${MY_WC_HASH}
WORKING_DIRECTORY ${SOURCE_DIR}
OUTPUT_VARIABLE _git_contains_check
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT _git_contains_check STREQUAL "")
STRING(REGEX REPLACE "^[ \t]+" "" _git_contains_check "${_git_contains_check}")
if(_git_contains_check STREQUAL "master")
set(MY_WC_BRANCH "master")
else()
execute_process(COMMAND git show-ref --tags -d
@@ -47,22 +48,6 @@ if(EXISTS ${SOURCE_DIR}/.git)
if(_git_tag_hashes MATCHES "${_git_head_hash}")
set(MY_WC_BRANCH "master")
else()
execute_process(COMMAND git branch --contains ${MY_WC_HASH}
WORKING_DIRECTORY ${SOURCE_DIR}
OUTPUT_VARIABLE _git_contains_branches
OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REGEX REPLACE "^\\*[ \t]+" "" _git_contains_branches "${_git_contains_branches}")
string(REGEX REPLACE "[\r\n]+" ";" _git_contains_branches "${_git_contains_branches}")
string(REGEX REPLACE ";[ \t]+" ";" _git_contains_branches "${_git_contains_branches}")
foreach(_branch ${_git_contains_branches})
if (NOT "${_branch}" MATCHES "\\(HEAD.*")
set(MY_WC_BRANCH "${_branch}")
break()
endif()
endforeach()
unset(_branch)
unset(_git_contains_branches)
endif()
unset(_git_tag_hashes)

View File

@@ -12,7 +12,6 @@ set(WITH_CODEC_FFMPEG ON CACHE BOOL "" FORCE)
set(WITH_CODEC_SNDFILE ON CACHE BOOL "" FORCE)
set(WITH_CYCLES ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_OSL ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_OPENSUBDIV ON CACHE BOOL "" FORCE)
set(WITH_FFTW3 ON CACHE BOOL "" FORCE)
set(WITH_LIBMV ON CACHE BOOL "" FORCE)
set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE)

View File

@@ -16,7 +16,6 @@ set(WITH_CODEC_FFMPEG OFF CACHE BOOL "" FORCE)
set(WITH_CODEC_SNDFILE OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES_OSL OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES_OPENSUBDIV OFF CACHE BOOL "" FORCE)
set(WITH_FFTW3 OFF CACHE BOOL "" FORCE)
set(WITH_LIBMV OFF CACHE BOOL "" FORCE)
set(WITH_LLVM OFF CACHE BOOL "" FORCE)
@@ -49,7 +48,6 @@ set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLORIO OFF CACHE BOOL "" FORCE)
set(WITH_OPENIMAGEIO OFF CACHE BOOL "" FORCE)
set(WITH_OPENMP OFF CACHE BOOL "" FORCE)
set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
set(WITH_OPENVDB OFF CACHE BOOL "" FORCE)
set(WITH_RAYOPTIMIZATION OFF CACHE BOOL "" FORCE)
set(WITH_SDL OFF CACHE BOOL "" FORCE)

View File

@@ -1,79 +0,0 @@
# Turn everything ON thats expected for an official release builds.
#
# Example usage:
# cmake -C../blender/build_files/cmake/config/blender_release.cmake ../blender
#
set(WITH_ALEMBIC ON CACHE BOOL "" FORCE)
set(WITH_BUILDINFO ON CACHE BOOL "" FORCE)
set(WITH_BULLET ON CACHE BOOL "" FORCE)
set(WITH_CODEC_AVI ON CACHE BOOL "" FORCE)
set(WITH_CODEC_FFMPEG ON CACHE BOOL "" FORCE)
set(WITH_CODEC_SNDFILE ON CACHE BOOL "" FORCE)
set(WITH_CYCLES ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_OSL ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_OPENSUBDIV ON CACHE BOOL "" FORCE)
set(WITH_FFTW3 ON CACHE BOOL "" FORCE)
set(WITH_LIBMV ON CACHE BOOL "" FORCE)
set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE)
set(WITH_GAMEENGINE ON CACHE BOOL "" FORCE)
set(WITH_COMPOSITOR ON CACHE BOOL "" FORCE)
set(WITH_FREESTYLE ON CACHE BOOL "" FORCE)
set(WITH_GHOST_XDND ON CACHE BOOL "" FORCE)
set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE)
set(WITH_IK_ITASC ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_CINEON ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_DDS ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_FRAMESERVER ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_HDR ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_OPENEXR ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_OPENJPEG ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_TIFF ON CACHE BOOL "" FORCE)
set(WITH_INPUT_NDOF ON CACHE BOOL "" FORCE)
set(WITH_INTERNATIONAL ON CACHE BOOL "" FORCE)
set(WITH_JACK ON CACHE BOOL "" FORCE)
set(WITH_LZMA ON CACHE BOOL "" FORCE)
set(WITH_LZO ON CACHE BOOL "" FORCE)
set(WITH_MOD_BOOLEAN ON CACHE BOOL "" FORCE)
set(WITH_MOD_FLUID ON CACHE BOOL "" FORCE)
set(WITH_MOD_REMESH ON CACHE BOOL "" FORCE)
set(WITH_MOD_SMOKE ON CACHE BOOL "" FORCE)
set(WITH_MOD_OCEANSIM ON CACHE BOOL "" FORCE)
set(WITH_AUDASPACE ON CACHE BOOL "" FORCE)
set(WITH_OPENAL ON CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE)
set(WITH_OPENCOLORIO ON CACHE BOOL "" FORCE)
set(WITH_OPENMP ON CACHE BOOL "" FORCE)
set(WITH_OPENVDB ON CACHE BOOL "" FORCE)
set(WITH_OPENVDB_BLOSC ON CACHE BOOL "" FORCE)
set(WITH_PYTHON_INSTALL ON CACHE BOOL "" FORCE)
set(WITH_RAYOPTIMIZATION ON CACHE BOOL "" FORCE)
set(WITH_SDL ON CACHE BOOL "" FORCE)
set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE)
set(WITH_X11_XF86VMODE ON CACHE BOOL "" FORCE)
set(WITH_PLAYER ON CACHE BOOL "" FORCE)
set(WITH_MEM_JEMALLOC ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_CUDA_BINARIES ON CACHE BOOL "" FORCE)
set(CYCLES_CUDA_BINARIES_ARCH sm_20;sm_21;sm_30;sm_35;sm_37;sm_50;sm_52;sm_60;sm_61 CACHE STRING "" FORCE)
# platform dependent options
if(UNIX AND NOT APPLE)
set(WITH_JACK ON CACHE BOOL "" FORCE)
set(WITH_DOC_MANPAGE ON CACHE BOOL "" FORCE)
set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
elseif(WIN32)
set(WITH_JACK OFF CACHE BOOL "" FORCE)
if(NOT CMAKE_COMPILER_IS_GNUCC)
set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
else()
# MinGW exceptions
set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
set(WITH_CODEC_SNDFILE OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES_OSL OFF CACHE BOOL "" FORCE)
endif()
elseif(APPLE)
set(WITH_JACK ON CACHE BOOL "" FORCE)
set(WITH_CODEC_QUICKTIME ON CACHE BOOL "" FORCE)
set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
endif()

View File

@@ -359,6 +359,7 @@ function(setup_liblinks
target_link_libraries(
${target}
${PNG_LIBRARIES}
${ZLIB_LIBRARIES}
${FREETYPE_LIBRARY}
)
@@ -415,7 +416,7 @@ function(setup_liblinks
if(WITH_OPENCOLORIO)
target_link_libraries(${target} ${OPENCOLORIO_LIBRARIES})
endif()
if(WITH_OPENSUBDIV OR WITH_CYCLES_OPENSUBDIV)
if(WITH_OPENSUBDIV)
if(WIN32 AND NOT UNIX)
file_list_suffix(OPENSUBDIV_LIBRARIES_DEBUG "${OPENSUBDIV_LIBRARIES}" "_d")
target_link_libraries_debug(${target} "${OPENSUBDIV_LIBRARIES_DEBUG}")
@@ -509,17 +510,11 @@ function(setup_liblinks
endif()
endif()
target_link_libraries(
${target}
${ZLIB_LIBRARIES}
)
#system libraries with no dependencies such as platform link libs or opengl should go last
target_link_libraries(${target}
${BLENDER_GL_LIBRARIES})
#target_link_libraries(${target} ${PLATFORM_LINKLIBS} ${CMAKE_DL_LIBS})
target_link_libraries(${target} ${PLATFORM_LINKLIBS})
target_link_libraries(${target} ${PLATFORM_LINKLIBS} ${CMAKE_DL_LIBS})
endfunction()
@@ -606,6 +601,9 @@ function(SETUP_BLENDER_SORTED_LIBS)
bf_gpu
bf_blenloader
bf_blenkernel
bf_blenvm
bf_blenvm_compile
bf_blenvm_bvm
bf_physics
bf_nodes
bf_rna
@@ -746,7 +744,7 @@ function(SETUP_BLENDER_SORTED_LIBS)
list(APPEND BLENDER_SORTED_LIBS bf_intern_gpudirect)
endif()
if(WITH_OPENSUBDIV OR WITH_CYCLES_OPENSUBDIV)
if(WITH_OPENSUBDIV)
list(APPEND BLENDER_SORTED_LIBS bf_intern_opensubdiv)
endif()
@@ -754,6 +752,10 @@ function(SETUP_BLENDER_SORTED_LIBS)
list(APPEND BLENDER_SORTED_LIBS bf_intern_openvdb)
endif()
if(WITH_LLVM)
list_insert_after(BLENDER_SORTED_LIBS "bf_blenvm" "bf_blenvm_llvm")
endif()
foreach(SORTLIB ${BLENDER_SORTED_LIBS})
set(REMLIB ${SORTLIB})
foreach(SEARCHLIB ${BLENDER_LINK_LIBS})
@@ -1579,26 +1581,3 @@ macro(openmp_delayload
endif(WITH_OPENMP)
endif(MSVC)
endmacro()
MACRO(WINDOWS_SIGN_TARGET target)
if (WITH_WINDOWS_CODESIGN)
if (!SIGNTOOL_EXE)
error("Codesigning is enabled, but signtool is not found")
else()
if (WINDOWS_CODESIGN_PFX_PASSWORD)
set(CODESIGNPASSWORD /p ${WINDOWS_CODESIGN_PFX_PASSWORD})
else()
if ($ENV{PFXPASSWORD})
set(CODESIGNPASSWORD /p $ENV{PFXPASSWORD})
else()
message( FATAL_ERROR "WITH_WINDOWS_CODESIGN is on but WINDOWS_CODESIGN_PFX_PASSWORD not set, and environment variable PFXPASSWORD not found, unable to sign code.")
endif()
endif()
add_custom_command(TARGET ${target}
POST_BUILD
COMMAND ${SIGNTOOL_EXE} sign /f ${WINDOWS_CODESIGN_PFX} ${CODESIGNPASSWORD} $<TARGET_FILE:${target}>
VERBATIM
)
endif()
endif()
ENDMACRO()

View File

@@ -38,21 +38,7 @@ unset(MY_WC_HASH)
# Force Package Name
execute_process(COMMAND date "+%Y%m%d" OUTPUT_VARIABLE CPACK_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER)
if (MSVC)
if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
set(PACKAGE_ARCH windows64)
else()
set(PACKAGE_ARCH windows32)
endif()
else(MSVC)
set(PACKAGE_ARCH ${CMAKE_SYSTEM_PROCESSOR})
endif()
if (CPACK_OVERRIDE_PACKAGENAME)
set(CPACK_PACKAGE_FILE_NAME ${CPACK_OVERRIDE_PACKAGENAME}-${PACKAGE_ARCH})
else()
set(CPACK_PACKAGE_FILE_NAME ${PROJECT_NAME_LOWER}-${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}-git${CPACK_DATE}.${BUILD_REV}-${PACKAGE_ARCH})
endif()
set(CPACK_PACKAGE_FILE_NAME ${PROJECT_NAME_LOWER}-${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}-git${CPACK_DATE}.${BUILD_REV}-${CMAKE_SYSTEM_PROCESSOR})
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
# RPM packages
@@ -97,8 +83,6 @@ if(WIN32)
endif()
set(CPACK_PACKAGE_EXECUTABLES "blender" "blender")
set(CPACK_CREATE_DESKTOP_LINKS "blender" "blender")
include(CPack)
# Target for build_archive.py script, to automatically pass along

View File

@@ -1,468 +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) 2016, Blender Foundation
# All rights reserved.
#
# Contributor(s): Sergey Sharybin.
#
# ***** END GPL LICENSE BLOCK *****
# Libraries configuration for Apple.
if(NOT DEFINED LIBDIR)
if(WITH_CXX11)
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin)
else()
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin-9.x.universal)
endif()
else()
message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
endif()
if(NOT EXISTS "${LIBDIR}/")
message(FATAL_ERROR "Mac OSX requires pre-compiled libs at: '${LIBDIR}'")
endif()
if(WITH_OPENAL)
find_package(OpenAL)
if(OPENAL_FOUND)
set(WITH_OPENAL ON)
set(OPENAL_INCLUDE_DIR "${LIBDIR}/openal/include")
else()
set(WITH_OPENAL OFF)
endif()
endif()
if(WITH_ALEMBIC)
set(ALEMBIC ${LIBDIR}/alembic)
set(ALEMBIC_INCLUDE_DIR ${ALEMBIC}/include)
set(ALEMBIC_INCLUDE_DIRS ${ALEMBIC_INCLUDE_DIR})
set(ALEMBIC_LIBPATH ${ALEMBIC}/lib)
set(ALEMBIC_LIBRARIES Alembic)
endif()
if(WITH_OPENSUBDIV OR WITH_CYCLES_OPENSUBDIV)
set(OPENSUBDIV ${LIBDIR}/opensubdiv)
set(OPENSUBDIV_LIBPATH ${OPENSUBDIV}/lib)
find_library(OSD_LIB_CPU NAMES osdCPU PATHS ${OPENSUBDIV_LIBPATH})
find_library(OSD_LIB_GPU NAMES osdGPU PATHS ${OPENSUBDIV_LIBPATH})
set(OPENSUBDIV_INCLUDE_DIR ${OPENSUBDIV}/include)
set(OPENSUBDIV_INCLUDE_DIRS ${OPENSUBDIV_INCLUDE_DIR})
list(APPEND OPENSUBDIV_LIBRARIES ${OSD_LIB_CPU} ${OSD_LIB_GPU})
endif()
if(WITH_JACK)
find_library(JACK_FRAMEWORK
NAMES jackmp
)
set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers)
if(NOT JACK_FRAMEWORK)
set(WITH_JACK OFF)
endif()
endif()
if(WITH_CODEC_SNDFILE)
set(SNDFILE ${LIBDIR}/sndfile)
set(SNDFILE_INCLUDE_DIRS ${SNDFILE}/include)
set(SNDFILE_LIBRARIES sndfile FLAC ogg vorbis vorbisenc)
set(SNDFILE_LIBPATH ${SNDFILE}/lib ${LIBDIR}/ffmpeg/lib) # TODO, deprecate
endif()
if(WITH_PYTHON)
# we use precompiled libraries for py 3.5 and up by default
set(PYTHON_VERSION 3.5)
if(NOT WITH_PYTHON_MODULE AND NOT WITH_PYTHON_FRAMEWORK)
# normally cached but not since we include them with blender
set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}m")
set(PYTHON_EXECUTABLE "${LIBDIR}/python/bin/python${PYTHON_VERSION}m")
set(PYTHON_LIBRARY python${PYTHON_VERSION}m)
set(PYTHON_LIBPATH "${LIBDIR}/python/lib/python${PYTHON_VERSION}")
# set(PYTHON_LINKFLAGS "-u _PyMac_Error") # won't build with this enabled
else()
# module must be compiled against Python framework
set(_py_framework "/Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}")
set(PYTHON_INCLUDE_DIR "${_py_framework}/include/python${PYTHON_VERSION}m")
set(PYTHON_EXECUTABLE "${_py_framework}/bin/python${PYTHON_VERSION}m")
set(PYTHON_LIBPATH "${_py_framework}/lib/python${PYTHON_VERSION}/config-${PYTHON_VERSION}m")
#set(PYTHON_LIBRARY python${PYTHON_VERSION})
#set(PYTHON_LINKFLAGS "-u _PyMac_Error -framework Python") # won't build with this enabled
unset(_py_framework)
endif()
# uncached vars
set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}")
set(PYTHON_LIBRARIES "${PYTHON_LIBRARY}")
if(NOT EXISTS "${PYTHON_EXECUTABLE}")
message(FATAL_ERROR "Python executable missing: ${PYTHON_EXECUTABLE}")
endif()
endif()
if(WITH_FFTW3)
set(FFTW3 ${LIBDIR}/fftw3)
set(FFTW3_INCLUDE_DIRS ${FFTW3}/include)
set(FFTW3_LIBRARIES fftw3)
set(FFTW3_LIBPATH ${FFTW3}/lib)
endif()
set(PNG_LIBRARIES png)
set(JPEG_LIBRARIES jpeg)
set(ZLIB /usr)
set(ZLIB_INCLUDE_DIRS "${ZLIB}/include")
set(ZLIB_LIBRARIES z bz2)
set(FREETYPE ${LIBDIR}/freetype)
set(FREETYPE_INCLUDE_DIRS ${FREETYPE}/include ${FREETYPE}/include/freetype2)
set(FREETYPE_LIBPATH ${FREETYPE}/lib)
set(FREETYPE_LIBRARY freetype)
if(WITH_IMAGE_OPENEXR)
set(OPENEXR ${LIBDIR}/openexr)
set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include)
set(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR} ${OPENEXR}/include/OpenEXR)
if(WITH_CXX11)
set(OPENEXR_POSTFIX -2_2)
else()
set(OPENEXR_POSTFIX)
endif()
set(OPENEXR_LIBRARIES
Iex${OPENEXR_POSTFIX}
Half
IlmImf${OPENEXR_POSTFIX}
Imath${OPENEXR_POSTFIX}
IlmThread${OPENEXR_POSTFIX})
set(OPENEXR_LIBPATH ${OPENEXR}/lib)
endif()
if(WITH_CODEC_FFMPEG)
set(FFMPEG ${LIBDIR}/ffmpeg)
set(FFMPEG_INCLUDE_DIRS ${FFMPEG}/include)
set(FFMPEG_LIBRARIES
avcodec avdevice avformat avutil
mp3lame swscale x264 xvidcore theora theoradec theoraenc vorbis vorbisenc vorbisfile ogg
)
if(WITH_CXX11)
set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} schroedinger orc vpx webp swresample)
endif()
set(FFMPEG_LIBPATH ${FFMPEG}/lib)
endif()
if(WITH_OPENJPEG OR WITH_CODEC_FFMPEG)
# use openjpeg from libdir that is linked into ffmpeg
if(WITH_CXX11)
set(OPENJPEG ${LIBDIR}/openjpeg)
set(WITH_SYSTEM_OPENJPEG ON)
set(OPENJPEG_INCLUDE_DIRS ${OPENJPEG}/include)
set(OPENJPEG_LIBRARIES ${OPENJPEG}/lib/libopenjpeg.a)
endif()
endif()
find_library(SYSTEMSTUBS_LIBRARY
NAMES
SystemStubs
PATHS
)
mark_as_advanced(SYSTEMSTUBS_LIBRARY)
if(SYSTEMSTUBS_LIBRARY)
list(APPEND PLATFORM_LINKLIBS SystemStubs)
endif()
set(PLATFORM_CFLAGS "-pipe -funsigned-char")
set(PLATFORM_LINKFLAGS
"-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Cocoa -framework Carbon -framework AudioUnit -framework AudioToolbox -framework CoreAudio"
)
if(WITH_CODEC_QUICKTIME)
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -framework QTKit")
if(CMAKE_OSX_ARCHITECTURES MATCHES i386)
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -framework QuickTime")
# libSDL still needs 32bit carbon quicktime
endif()
endif()
if(WITH_CXX11)
list(APPEND PLATFORM_LINKLIBS c++)
else()
list(APPEND PLATFORM_LINKLIBS stdc++)
endif()
if(WITH_JACK)
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -F/Library/Frameworks -weak_framework jackmp")
endif()
if(WITH_PYTHON_MODULE OR WITH_PYTHON_FRAMEWORK)
# force cmake to link right framework
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}/Python")
endif()
if(WITH_OPENCOLLADA)
set(OPENCOLLADA ${LIBDIR}/opencollada)
set(OPENCOLLADA_INCLUDE_DIRS
${LIBDIR}/opencollada/include/COLLADAStreamWriter
${LIBDIR}/opencollada/include/COLLADABaseUtils
${LIBDIR}/opencollada/include/COLLADAFramework
${LIBDIR}/opencollada/include/COLLADASaxFrameworkLoader
${LIBDIR}/opencollada/include/GeneratedSaxParser
)
set(OPENCOLLADA_LIBPATH ${OPENCOLLADA}/lib)
set(OPENCOLLADA_LIBRARIES
OpenCOLLADASaxFrameworkLoader
-lOpenCOLLADAFramework
-lOpenCOLLADABaseUtils
-lOpenCOLLADAStreamWriter
-lMathMLSolver
-lGeneratedSaxParser
-lxml2 -lbuffer -lftoa
)
# Use UTF functions from collada if LLVM is not enabled
if(NOT WITH_LLVM)
list(APPEND OPENCOLLADA_LIBRARIES -lUTF)
endif()
# pcre is bundled with openCollada
#set(PCRE ${LIBDIR}/pcre)
#set(PCRE_LIBPATH ${PCRE}/lib)
set(PCRE_LIBRARIES pcre)
#libxml2 is used
#set(EXPAT ${LIBDIR}/expat)
#set(EXPAT_LIBPATH ${EXPAT}/lib)
set(EXPAT_LIB)
endif()
if(WITH_SDL)
set(SDL ${LIBDIR}/sdl)
set(SDL_INCLUDE_DIR ${SDL}/include)
set(SDL_LIBRARY SDL2)
set(SDL_LIBPATH ${SDL}/lib)
if(WITH_CXX11)
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -framework ForceFeedback")
else()
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -lazy_framework ForceFeedback")
endif()
endif()
set(PNG "${LIBDIR}/png")
set(PNG_INCLUDE_DIRS "${PNG}/include")
set(PNG_LIBPATH ${PNG}/lib)
set(JPEG "${LIBDIR}/jpeg")
set(JPEG_INCLUDE_DIR "${JPEG}/include")
set(JPEG_LIBPATH ${JPEG}/lib)
if(WITH_IMAGE_TIFF)
set(TIFF ${LIBDIR}/tiff)
set(TIFF_INCLUDE_DIR ${TIFF}/include)
set(TIFF_LIBRARY tiff)
set(TIFF_LIBPATH ${TIFF}/lib)
endif()
if(WITH_BOOST)
set(BOOST ${LIBDIR}/boost)
set(BOOST_INCLUDE_DIR ${BOOST}/include)
if(WITH_CXX11)
set(BOOST_POSTFIX)
else()
set(BOOST_POSTFIX -mt)
endif()
set(BOOST_LIBRARIES
boost_date_time${BOOST_POSTFIX}
boost_filesystem${BOOST_POSTFIX}
boost_regex${BOOST_POSTFIX}
boost_system${BOOST_POSTFIX}
boost_thread${BOOST_POSTFIX}
boost_wave${BOOST_POSTFIX}
)
if(WITH_INTERNATIONAL)
list(APPEND BOOST_LIBRARIES boost_locale${BOOST_POSTFIX})
endif()
if(WITH_CYCLES_NETWORK)
list(APPEND BOOST_LIBRARIES boost_serialization${BOOST_POSTFIX})
endif()
if(WITH_OPENVDB)
list(APPEND BOOST_LIBRARIES boost_iostreams${BOOST_POSTFIX})
endif()
set(BOOST_LIBPATH ${BOOST}/lib)
set(BOOST_DEFINITIONS)
endif()
if(WITH_INTERNATIONAL OR WITH_CODEC_FFMPEG)
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -liconv") # boost_locale and ffmpeg needs it !
endif()
if(WITH_OPENIMAGEIO)
set(OPENIMAGEIO ${LIBDIR}/openimageio)
set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include)
set(OPENIMAGEIO_LIBRARIES
${OPENIMAGEIO}/lib/libOpenImageIO.a
${PNG_LIBRARIES}
${JPEG_LIBRARIES}
${TIFF_LIBRARY}
${OPENEXR_LIBRARIES}
${ZLIB_LIBRARIES}
)
if(WITH_CXX11)
set(OPENIMAGEIO_LIBRARIES ${OPENIMAGEIO_LIBRARIES} ${LIBDIR}/ffmpeg/lib/libwebp.a)
endif()
set(OPENIMAGEIO_LIBPATH
${OPENIMAGEIO}/lib
${JPEG_LIBPATH}
${PNG_LIBPATH}
${TIFF_LIBPATH}
${OPENEXR_LIBPATH}
${ZLIB_LIBPATH}
)
set(OPENIMAGEIO_DEFINITIONS "-DOIIO_STATIC_BUILD")
set(OPENIMAGEIO_IDIFF "${LIBDIR}/openimageio/bin/idiff")
endif()
if(WITH_OPENCOLORIO)
set(OPENCOLORIO ${LIBDIR}/opencolorio)
set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include)
set(OPENCOLORIO_LIBRARIES OpenColorIO tinyxml yaml-cpp)
set(OPENCOLORIO_LIBPATH ${OPENCOLORIO}/lib)
endif()
if(WITH_OPENVDB)
set(OPENVDB ${LIBDIR}/openvdb)
set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include)
set(TBB_INCLUDE_DIRS ${LIBDIR}/tbb/include)
set(TBB_LIBRARIES ${LIBDIR}/tbb/lib/libtbb.a)
set(OPENVDB_LIBRARIES openvdb blosc ${TBB_LIBRARIES})
set(OPENVDB_LIBPATH ${LIBDIR}/openvdb/lib)
set(OPENVDB_DEFINITIONS)
endif()
if(WITH_LLVM)
set(LLVM_ROOT_DIR ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation")
set(LLVM_VERSION "3.4" CACHE STRING "Version of LLVM to use")
if(EXISTS "${LLVM_ROOT_DIR}/bin/llvm-config")
set(LLVM_CONFIG "${LLVM_ROOT_DIR}/bin/llvm-config")
else()
set(LLVM_CONFIG llvm-config)
endif()
execute_process(COMMAND ${LLVM_CONFIG} --version
OUTPUT_VARIABLE LLVM_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND ${LLVM_CONFIG} --prefix
OUTPUT_VARIABLE LLVM_ROOT_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND ${LLVM_CONFIG} --libdir
OUTPUT_VARIABLE LLVM_LIBPATH
OUTPUT_STRIP_TRAILING_WHITESPACE)
find_library(LLVM_LIBRARY
NAMES LLVMAnalysis # first of a whole bunch of libs to get
PATHS ${LLVM_LIBPATH})
if(LLVM_LIBRARY AND LLVM_ROOT_DIR AND LLVM_LIBPATH)
if(LLVM_STATIC)
# if static LLVM libraries were requested, use llvm-config to generate
# the list of what libraries we need, and substitute that in the right
# way for LLVM_LIBRARY.
execute_process(COMMAND ${LLVM_CONFIG} --libfiles
OUTPUT_VARIABLE LLVM_LIBRARY
OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REPLACE " " ";" LLVM_LIBRARY ${LLVM_LIBRARY})
else()
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -lLLVM-3.4")
endif()
else()
message(FATAL_ERROR "LLVM not found.")
endif()
endif()
if(WITH_CYCLES_OSL)
set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation")
find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib)
find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib)
find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib)
# WARNING! depends on correct order of OSL libs linking
list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} -force_load ${OSL_LIB_EXEC} ${OSL_LIB_QUERY})
find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin)
if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER)
set(OSL_FOUND TRUE)
else()
message(STATUS "OSL not found")
set(WITH_CYCLES_OSL OFF)
endif()
endif()
if(WITH_OPENMP)
execute_process(COMMAND ${CMAKE_C_COMPILER} --version OUTPUT_VARIABLE COMPILER_VENDOR)
string(SUBSTRING "${COMPILER_VENDOR}" 0 5 VENDOR_NAME) # truncate output
if(${VENDOR_NAME} MATCHES "Apple") # Apple does not support OpenMP reliable with gcc and not with clang
set(WITH_OPENMP OFF)
else() # vanilla gcc or clang_omp support OpenMP
message(STATUS "Using special OpenMP enabled compiler !") # letting find_package(OpenMP) module work for gcc
if(CMAKE_C_COMPILER_ID MATCHES "Clang") # clang-omp in darwin libs
set(OPENMP_FOUND ON)
set(OpenMP_C_FLAGS "-fopenmp" CACHE STRING "C compiler flags for OpenMP parallization" FORCE)
set(OpenMP_CXX_FLAGS "-fopenmp" CACHE STRING "C++ compiler flags for OpenMP parallization" FORCE)
include_directories(${LIBDIR}/openmp/include)
link_directories(${LIBDIR}/openmp/lib)
# This is a workaround for our helperbinaries ( datatoc, masgfmt, ... ),
# They are linked also to omp lib, so we need it in builddir for runtime exexcution,
# TODO: remove all unneeded dependencies from these
# for intermediate binaries, in respect to lib ID
execute_process(
COMMAND ditto -arch ${CMAKE_OSX_ARCHITECTURES}
${LIBDIR}/openmp/lib/libiomp5.dylib
${CMAKE_BINARY_DIR}/Resources/lib/libiomp5.dylib)
endif()
endif()
endif()
set(EXETYPE MACOSX_BUNDLE)
set(CMAKE_C_FLAGS_DEBUG "-fno-strict-aliasing -g")
set(CMAKE_CXX_FLAGS_DEBUG "-fno-strict-aliasing -g")
if(CMAKE_OSX_ARCHITECTURES MATCHES "x86_64" OR CMAKE_OSX_ARCHITECTURES MATCHES "i386")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -mdynamic-no-pic -msse -msse2 -msse3 -mssse3")
set(CMAKE_C_FLAGS_RELEASE "-O2 -mdynamic-no-pic -msse -msse2 -msse3 -mssse3")
if(NOT CMAKE_C_COMPILER_ID MATCHES "Clang")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -ftree-vectorize -fvariable-expansion-in-unroller")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ftree-vectorize -fvariable-expansion-in-unroller")
endif()
else()
set(CMAKE_C_FLAGS_RELEASE "-mdynamic-no-pic -fno-strict-aliasing")
set(CMAKE_CXX_FLAGS_RELEASE "-mdynamic-no-pic -fno-strict-aliasing")
endif()
if(${XCODE_VERSION} VERSION_EQUAL 5 OR ${XCODE_VERSION} VERSION_GREATER 5)
# Xcode 5 is always using CLANG, which has too low template depth of 128 for libmv
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth=1024")
endif()
# Get rid of eventually clashes, we export some symbols explicite as local
set(PLATFORM_LINKFLAGS
"${PLATFORM_LINKFLAGS} -Xlinker -unexported_symbols_list -Xlinker ${CMAKE_SOURCE_DIR}/source/creator/osx_locals.map"
)
if(WITH_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -stdlib=libc++")
endif()
# Suppress ranlib "has no symbols" warnings (workaround for T48250)
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
set(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")

View File

@@ -1,428 +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) 2016, Blender Foundation
# All rights reserved.
#
# Contributor(s): Sergey Sharybin.
#
# ***** END GPL LICENSE BLOCK *****
# Libraries configuration for any *nix system including Linux and Unix.
macro(find_package_wrapper)
if(WITH_STATIC_LIBS)
find_package_static(${ARGV})
else()
find_package(${ARGV})
endif()
endmacro()
find_package_wrapper(JPEG REQUIRED)
find_package_wrapper(PNG REQUIRED)
find_package_wrapper(ZLIB REQUIRED)
find_package_wrapper(Freetype REQUIRED)
if(WITH_LZO AND WITH_SYSTEM_LZO)
find_package_wrapper(LZO)
if(NOT LZO_FOUND)
message(FATAL_ERROR "Failed finding system LZO version!")
endif()
endif()
if(WITH_SYSTEM_EIGEN3)
find_package_wrapper(Eigen3)
if(NOT EIGEN3_FOUND)
message(FATAL_ERROR "Failed finding system Eigen3 version!")
endif()
endif()
# else values are set below for all platforms
if(WITH_PYTHON)
# No way to set py35, remove for now.
# find_package(PythonLibs)
# Use our own instead, since without py is such a rare case,
# require this package
# XXX Linking errors with debian static python :/
# find_package_wrapper(PythonLibsUnix REQUIRED)
find_package(PythonLibsUnix REQUIRED)
endif()
if(WITH_IMAGE_OPENEXR)
find_package_wrapper(OpenEXR) # our own module
if(NOT OPENEXR_FOUND)
set(WITH_IMAGE_OPENEXR OFF)
endif()
endif()
if(WITH_IMAGE_OPENJPEG)
find_package_wrapper(OpenJPEG)
if(NOT OPENJPEG_FOUND)
set(WITH_IMAGE_OPENJPEG OFF)
endif()
endif()
if(WITH_IMAGE_TIFF)
# XXX Linking errors with debian static tiff :/
# find_package_wrapper(TIFF)
find_package(TIFF)
if(NOT TIFF_FOUND)
set(WITH_IMAGE_TIFF OFF)
endif()
endif()
# Audio IO
if(WITH_SYSTEM_AUDASPACE)
find_package_wrapper(Audaspace)
if(NOT AUDASPACE_FOUND OR NOT AUDASPACE_C_FOUND)
message(FATAL_ERROR "Audaspace external library not found!")
endif()
endif()
if(WITH_OPENAL)
find_package_wrapper(OpenAL)
if(NOT OPENAL_FOUND)
set(WITH_OPENAL OFF)
endif()
endif()
if(WITH_SDL)
if(WITH_SDL_DYNLOAD)
set(SDL_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extern/sdlew/include/SDL2")
set(SDL_LIBRARY)
else()
find_package_wrapper(SDL2)
if(SDL2_FOUND)
# Use same names for both versions of SDL until we move to 2.x.
set(SDL_INCLUDE_DIR "${SDL2_INCLUDE_DIR}")
set(SDL_LIBRARY "${SDL2_LIBRARY}")
set(SDL_FOUND "${SDL2_FOUND}")
else()
find_package_wrapper(SDL)
endif()
mark_as_advanced(
SDL_INCLUDE_DIR
SDL_LIBRARY
)
# unset(SDLMAIN_LIBRARY CACHE)
if(NOT SDL_FOUND)
set(WITH_SDL OFF)
endif()
endif()
endif()
if(WITH_JACK)
find_package_wrapper(Jack)
if(NOT JACK_FOUND)
set(WITH_JACK OFF)
endif()
endif()
# Codecs
if(WITH_CODEC_SNDFILE)
find_package_wrapper(SndFile)
if(NOT SNDFILE_FOUND)
set(WITH_CODEC_SNDFILE OFF)
endif()
endif()
if(WITH_CODEC_FFMPEG)
set(FFMPEG /usr CACHE PATH "FFMPEG Directory")
set(FFMPEG_LIBRARIES avformat avcodec avutil avdevice swscale CACHE STRING "FFMPEG Libraries")
mark_as_advanced(FFMPEG)
# lame, but until we have proper find module for ffmpeg
set(FFMPEG_INCLUDE_DIRS ${FFMPEG}/include)
if(EXISTS "${FFMPEG}/include/ffmpeg/")
list(APPEND FFMPEG_INCLUDE_DIRS "${FFMPEG}/include/ffmpeg")
endif()
# end lameness
mark_as_advanced(FFMPEG_LIBRARIES)
set(FFMPEG_LIBPATH ${FFMPEG}/lib)
endif()
if(WITH_FFTW3)
find_package_wrapper(Fftw3)
if(NOT FFTW3_FOUND)
set(WITH_FFTW3 OFF)
endif()
endif()
if(WITH_OPENCOLLADA)
find_package_wrapper(OpenCOLLADA)
if(OPENCOLLADA_FOUND)
find_package_wrapper(XML2)
find_package_wrapper(PCRE)
else()
set(WITH_OPENCOLLADA OFF)
endif()
endif()
if(WITH_MEM_JEMALLOC)
find_package_wrapper(JeMalloc)
if(NOT JEMALLOC_FOUND)
set(WITH_MEM_JEMALLOC OFF)
endif()
endif()
if(WITH_INPUT_NDOF)
find_package_wrapper(Spacenav)
if(SPACENAV_FOUND)
# use generic names within blenders buildsystem.
set(NDOF_INCLUDE_DIRS ${SPACENAV_INCLUDE_DIRS})
set(NDOF_LIBRARIES ${SPACENAV_LIBRARIES})
else()
set(WITH_INPUT_NDOF OFF)
endif()
endif()
if(WITH_CYCLES_OSL)
set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation")
if(NOT OSL_ROOT)
set(OSL_ROOT ${CYCLES_OSL})
endif()
find_package_wrapper(OpenShadingLanguage)
if(OSL_FOUND)
if(${OSL_LIBRARY_VERSION_MAJOR} EQUAL "1" AND ${OSL_LIBRARY_VERSION_MINOR} LESS "6")
# Note: --whole-archive is needed to force loading of all symbols in liboslexec,
# otherwise LLVM is missing the osl_allocate_closure_component function
set(OSL_LIBRARIES
${OSL_OSLCOMP_LIBRARY}
-Wl,--whole-archive ${OSL_OSLEXEC_LIBRARY}
-Wl,--no-whole-archive ${OSL_OSLQUERY_LIBRARY}
)
endif()
else()
message(STATUS "OSL not found, disabling it from Cycles")
set(WITH_CYCLES_OSL OFF)
endif()
endif()
if(WITH_OPENVDB)
find_package_wrapper(OpenVDB)
find_package_wrapper(TBB)
if(NOT OPENVDB_FOUND OR NOT TBB_FOUND)
set(WITH_OPENVDB OFF)
set(WITH_OPENVDB_BLOSC OFF)
message(STATUS "OpenVDB not found, disabling it")
endif()
endif()
if(WITH_ALEMBIC)
find_package_wrapper(Alembic)
if(WITH_ALEMBIC_HDF5)
set(HDF5_ROOT_DIR ${LIBDIR}/hdf5)
find_package_wrapper(HDF5)
endif()
if(NOT ALEMBIC_FOUND OR (WITH_ALEMBIC_HDF5 AND NOT HDF5_FOUND))
set(WITH_ALEMBIC OFF)
set(WITH_ALEMBIC_HDF5 OFF)
endif()
endif()
if(WITH_BOOST)
# uses in build instructions to override include and library variables
if(NOT BOOST_CUSTOM)
if(WITH_STATIC_LIBS)
set(Boost_USE_STATIC_LIBS ON)
endif()
set(Boost_USE_MULTITHREADED ON)
set(__boost_packages filesystem regex thread date_time)
if(WITH_CYCLES_OSL)
if(NOT (${OSL_LIBRARY_VERSION_MAJOR} EQUAL "1" AND ${OSL_LIBRARY_VERSION_MINOR} LESS "6"))
list(APPEND __boost_packages wave)
else()
endif()
endif()
if(WITH_INTERNATIONAL)
list(APPEND __boost_packages locale)
endif()
if(WITH_CYCLES_NETWORK)
list(APPEND __boost_packages serialization)
endif()
if(WITH_OPENVDB)
list(APPEND __boost_packages iostreams)
endif()
list(APPEND __boost_packages system)
find_package(Boost 1.48 COMPONENTS ${__boost_packages})
if(NOT Boost_FOUND)
# try to find non-multithreaded if -mt not found, this flag
# doesn't matter for us, it has nothing to do with thread
# safety, but keep it to not disturb build setups
set(Boost_USE_MULTITHREADED OFF)
find_package(Boost 1.48 COMPONENTS ${__boost_packages})
endif()
unset(__boost_packages)
if(Boost_USE_STATIC_LIBS AND WITH_BOOST_ICU)
find_package(IcuLinux)
endif()
mark_as_advanced(Boost_DIR) # why doesnt boost do this?
endif()
set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS})
set(BOOST_LIBRARIES ${Boost_LIBRARIES})
set(BOOST_LIBPATH ${Boost_LIBRARY_DIRS})
set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB")
endif()
if(WITH_OPENIMAGEIO)
find_package_wrapper(OpenImageIO)
if(NOT OPENIMAGEIO_PUGIXML_FOUND AND WITH_CYCLES_STANDALONE)
find_package_wrapper(PugiXML)
else()
set(PUGIXML_INCLUDE_DIR "${OPENIMAGEIO_INCLUDE_DIR/OpenImageIO}")
set(PUGIXML_LIBRARIES "")
endif()
set(OPENIMAGEIO_LIBRARIES
${OPENIMAGEIO_LIBRARIES}
${PNG_LIBRARIES}
${JPEG_LIBRARIES}
${ZLIB_LIBRARIES}
${BOOST_LIBRARIES}
)
set(OPENIMAGEIO_LIBPATH) # TODO, remove and reference the absolute path everywhere
set(OPENIMAGEIO_DEFINITIONS "")
if(WITH_IMAGE_TIFF)
list(APPEND OPENIMAGEIO_LIBRARIES "${TIFF_LIBRARY}")
endif()
if(WITH_IMAGE_OPENEXR)
list(APPEND OPENIMAGEIO_LIBRARIES "${OPENEXR_LIBRARIES}")
endif()
if(NOT OPENIMAGEIO_FOUND)
set(WITH_OPENIMAGEIO OFF)
message(STATUS "OpenImageIO not found, disabling WITH_CYCLES")
endif()
endif()
if(WITH_OPENCOLORIO)
find_package_wrapper(OpenColorIO)
set(OPENCOLORIO_LIBRARIES ${OPENCOLORIO_LIBRARIES})
set(OPENCOLORIO_LIBPATH) # TODO, remove and reference the absolute path everywhere
set(OPENCOLORIO_DEFINITIONS)
if(NOT OPENCOLORIO_FOUND)
set(WITH_OPENCOLORIO OFF)
message(STATUS "OpenColorIO not found")
endif()
endif()
if(WITH_LLVM)
find_package_wrapper(LLVM)
if(NOT LLVM_FOUND)
set(WITH_LLVM OFF)
message(STATUS "LLVM not found")
endif()
endif()
if(WITH_LLVM OR WITH_SDL_DYNLOAD)
# Fix for conflict with Mesa llvmpipe
set(PLATFORM_LINKFLAGS
"${PLATFORM_LINKFLAGS} -Wl,--version-script='${CMAKE_SOURCE_DIR}/source/creator/blender.map'"
)
endif()
if(WITH_OPENSUBDIV OR WITH_CYCLES_OPENSUBDIV)
find_package_wrapper(OpenSubdiv)
set(OPENSUBDIV_LIBRARIES ${OPENSUBDIV_LIBRARIES})
set(OPENSUBDIV_LIBPATH) # TODO, remove and reference the absolute path everywhere
if(NOT OPENSUBDIV_FOUND)
set(WITH_OPENSUBDIV OFF)
set(WITH_CYCLES_OPENSUBDIV OFF)
message(STATUS "OpenSubdiv not found")
endif()
endif()
# OpenSuse needs lutil, ArchLinux not, for now keep, can avoid by using --as-needed
list(APPEND PLATFORM_LINKLIBS -lutil -lc -lm)
find_package(Threads REQUIRED)
list(APPEND PLATFORM_LINKLIBS ${CMAKE_THREAD_LIBS_INIT})
# used by other platforms
set(PTHREADS_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
if(CMAKE_DL_LIBS)
list(APPEND PLATFORM_LINKLIBS ${CMAKE_DL_LIBS})
endif()
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
if(NOT WITH_PYTHON_MODULE)
# binreloc is linux only
set(BINRELOC_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extern/binreloc/include)
set(WITH_BINRELOC ON)
endif()
endif()
# lfs on glibc, all compilers should use
add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE)
# GNU Compiler
if(CMAKE_COMPILER_IS_GNUCC)
set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing")
if(WITH_LINKER_GOLD)
execute_process(
COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version
ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
if("${LD_VERSION}" MATCHES "GNU gold")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=gold")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=gold")
else()
message(STATUS "GNU gold linker isn't available, using the default system linker.")
endif()
unset(LD_VERSION)
endif()
# CLang is the same as GCC for now.
elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing")
# Solaris CC
elseif(CMAKE_C_COMPILER_ID MATCHES "SunPro")
set(PLATFORM_CFLAGS "-pipe -features=extensions -fPIC -D__FUNCTION__=__func__")
# Intel C++ Compiler
elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
# think these next two are broken
find_program(XIAR xiar)
if(XIAR)
set(CMAKE_AR "${XIAR}")
endif()
mark_as_advanced(XIAR)
find_program(XILD xild)
if(XILD)
set(CMAKE_LINKER "${XILD}")
endif()
mark_as_advanced(XILD)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fp-model precise -prec_div -parallel")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fp-model precise -prec_div -parallel")
# set(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} -diag-enable sc3")
set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing")
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -static-intel")
endif()

View File

@@ -1,87 +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) 2016, Blender Foundation
# All rights reserved.
#
# Contributor(s): Sergey Sharybin.
#
# ***** END GPL LICENSE BLOCK *****
# Libraries configuration for Windows.
add_definitions(-DWIN32)
if(MSVC)
include(platform_win32_msvc)
elseif(CMAKE_COMPILER_IS_GNUCC)
include(platform_win32_mingw)
endif()
# Things common to both mingw and MSVC should go here
set(WINTAB_INC ${LIBDIR}/wintab/include)
if(WITH_OPENAL)
set(OPENAL ${LIBDIR}/openal)
set(OPENALDIR ${LIBDIR}/openal)
set(OPENAL_INCLUDE_DIR ${OPENAL}/include)
if(MSVC)
set(OPENAL_LIBRARY openal32)
else()
set(OPENAL_LIBRARY wrap_oal)
endif()
set(OPENAL_LIBPATH ${OPENAL}/lib)
endif()
if(WITH_CODEC_SNDFILE)
set(SNDFILE ${LIBDIR}/sndfile)
set(SNDFILE_INCLUDE_DIRS ${SNDFILE}/include)
set(SNDFILE_LIBRARIES libsndfile-1)
set(SNDFILE_LIBPATH ${SNDFILE}/lib) # TODO, deprecate
endif()
if(WITH_RAYOPTIMIZATION AND SUPPORT_SSE_BUILD)
add_definitions(-D__SSE__ -D__MMX__)
endif()
if(WITH_CYCLES_OSL)
set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation")
find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib)
find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib)
find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib)
find_library(OSL_LIB_EXEC_DEBUG NAMES oslexec_d PATHS ${CYCLES_OSL}/lib)
find_library(OSL_LIB_COMP_DEBUG NAMES oslcomp_d PATHS ${CYCLES_OSL}/lib)
find_library(OSL_LIB_QUERY_DEBUG NAMES oslquery_d PATHS ${CYCLES_OSL}/lib)
list(APPEND OSL_LIBRARIES
optimized ${OSL_LIB_COMP}
optimized ${OSL_LIB_EXEC}
optimized ${OSL_LIB_QUERY}
debug ${OSL_LIB_EXEC_DEBUG}
debug ${OSL_LIB_COMP_DEBUG}
debug ${OSL_LIB_QUERY_DEBUG}
)
find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin)
if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER)
set(OSL_FOUND TRUE)
else()
message(STATUS "OSL not found")
set(WITH_CYCLES_OSL OFF)
endif()
endif()

View File

@@ -1,302 +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) 2016, Blender Foundation
# All rights reserved.
#
# Contributor(s): Sergey Sharybin.
#
# ***** END GPL LICENSE BLOCK *****
# Libraries configuration for Windows when compiling with MinGW.
# keep GCC specific stuff here
include(CheckCSourceCompiles)
# Setup 64bit and 64bit windows systems
CHECK_C_SOURCE_COMPILES("
#ifndef __MINGW64__
#error
#endif
int main(void) { return 0; }
"
WITH_MINGW64
)
if(NOT DEFINED LIBDIR)
if(WITH_MINGW64)
message(STATUS "Compiling for 64 bit with MinGW-w64.")
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/mingw64)
else()
message(STATUS "Compiling for 32 bit with MinGW-w32.")
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/mingw32)
if(WITH_RAYOPTIMIZATION)
message(WARNING "MinGW-w32 is known to be unstable with 'WITH_RAYOPTIMIZATION' option enabled.")
endif()
endif()
else()
message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
endif()
if(NOT EXISTS "${LIBDIR}/")
message(FATAL_ERROR "Windows requires pre-compiled libs at: '${LIBDIR}'")
endif()
list(APPEND PLATFORM_LINKLIBS
-lshell32 -lshfolder -lgdi32 -lmsvcrt -lwinmm -lmingw32 -lm -lws2_32
-lz -lstdc++ -lole32 -luuid -lwsock32 -lpsapi -ldbghelp
)
if(WITH_INPUT_IME)
list(APPEND PLATFORM_LINKLIBS -limm32)
endif()
set(PLATFORM_CFLAGS "-pipe -funsigned-char -fno-strict-aliasing")
if(WITH_MINGW64)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive")
list(APPEND PLATFORM_LINKLIBS -lpthread)
add_definitions(-DFREE_WINDOWS64 -DMS_WIN64)
endif()
add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE)
add_definitions(-DFREE_WINDOWS)
set(PNG "${LIBDIR}/png")
set(PNG_INCLUDE_DIRS "${PNG}/include")
set(PNG_LIBPATH ${PNG}/lib) # not cmake defined
if(WITH_MINGW64)
set(JPEG_LIBRARIES jpeg)
else()
set(JPEG_LIBRARIES libjpeg)
endif()
set(PNG_LIBRARIES png)
set(ZLIB ${LIBDIR}/zlib)
set(ZLIB_INCLUDE_DIRS ${ZLIB}/include)
set(ZLIB_LIBPATH ${ZLIB}/lib)
set(ZLIB_LIBRARIES z)
set(JPEG "${LIBDIR}/jpeg")
set(JPEG_INCLUDE_DIR "${JPEG}/include")
set(JPEG_LIBPATH ${JPEG}/lib) # not cmake defined
# comes with own pthread library
if(NOT WITH_MINGW64)
set(PTHREADS ${LIBDIR}/pthreads)
#set(PTHREADS_INCLUDE_DIRS ${PTHREADS}/include)
set(PTHREADS_LIBPATH ${PTHREADS}/lib)
set(PTHREADS_LIBRARIES pthreadGC2)
endif()
set(FREETYPE ${LIBDIR}/freetype)
set(FREETYPE_INCLUDE_DIRS ${FREETYPE}/include ${FREETYPE}/include/freetype2)
set(FREETYPE_LIBPATH ${FREETYPE}/lib)
set(FREETYPE_LIBRARY freetype)
if(WITH_FFTW3)
set(FFTW3 ${LIBDIR}/fftw3)
set(FFTW3_LIBRARIES fftw3)
set(FFTW3_INCLUDE_DIRS ${FFTW3}/include)
set(FFTW3_LIBPATH ${FFTW3}/lib)
endif()
if(WITH_OPENCOLLADA)
set(OPENCOLLADA ${LIBDIR}/opencollada)
set(OPENCOLLADA_INCLUDE_DIRS
${OPENCOLLADA}/include/opencollada/COLLADAStreamWriter
${OPENCOLLADA}/include/opencollada/COLLADABaseUtils
${OPENCOLLADA}/include/opencollada/COLLADAFramework
${OPENCOLLADA}/include/opencollada/COLLADASaxFrameworkLoader
${OPENCOLLADA}/include/opencollada/GeneratedSaxParser
)
set(OPENCOLLADA_LIBPATH ${OPENCOLLADA}/lib/opencollada)
set(OPENCOLLADA_LIBRARIES
OpenCOLLADAStreamWriter
OpenCOLLADASaxFrameworkLoader
OpenCOLLADAFramework
OpenCOLLADABaseUtils
GeneratedSaxParser
UTF MathMLSolver buffer ftoa xml
)
set(PCRE_LIBRARIES pcre)
endif()
if(WITH_CODEC_FFMPEG)
set(FFMPEG ${LIBDIR}/ffmpeg)
set(FFMPEG_INCLUDE_DIRS ${FFMPEG}/include)
if(WITH_MINGW64)
set(FFMPEG_LIBRARIES avcodec.dll avformat.dll avdevice.dll avutil.dll swscale.dll swresample.dll)
else()
set(FFMPEG_LIBRARIES avcodec-55 avformat-55 avdevice-55 avutil-52 swscale-2)
endif()
set(FFMPEG_LIBPATH ${FFMPEG}/lib)
endif()
if(WITH_IMAGE_OPENEXR)
set(OPENEXR ${LIBDIR}/openexr)
set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include)
set(OPENEXR_INCLUDE_DIRS ${OPENEXR}/include/OpenEXR)
set(OPENEXR_LIBRARIES Half IlmImf Imath IlmThread Iex)
set(OPENEXR_LIBPATH ${OPENEXR}/lib)
endif()
if(WITH_IMAGE_TIFF)
set(TIFF ${LIBDIR}/tiff)
set(TIFF_LIBRARY tiff)
set(TIFF_INCLUDE_DIR ${TIFF}/include)
set(TIFF_LIBPATH ${TIFF}/lib)
endif()
if(WITH_JACK)
set(JACK ${LIBDIR}/jack)
set(JACK_INCLUDE_DIRS ${JACK}/include/jack ${JACK}/include)
set(JACK_LIBRARIES jack)
set(JACK_LIBPATH ${JACK}/lib)
# TODO, gives linking errors, force off
set(WITH_JACK OFF)
endif()
if(WITH_PYTHON)
# normally cached but not since we include them with blender
set(PYTHON_VERSION 3.5) # CACHE STRING)
string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}") # CACHE PATH)
set(PYTHON_LIBRARY "${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}mw.lib") # CACHE FILEPATH)
unset(_PYTHON_VERSION_NO_DOTS)
# uncached vars
set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}")
set(PYTHON_LIBRARIES "${PYTHON_LIBRARY}")
endif()
if(WITH_BOOST)
set(BOOST ${LIBDIR}/boost)
set(BOOST_INCLUDE_DIR ${BOOST}/include)
if(WITH_MINGW64)
set(BOOST_POSTFIX "mgw47-mt-s-1_49")
set(BOOST_DEBUG_POSTFIX "mgw47-mt-sd-1_49")
else()
set(BOOST_POSTFIX "mgw46-mt-s-1_49")
set(BOOST_DEBUG_POSTFIX "mgw46-mt-sd-1_49")
endif()
set(BOOST_LIBRARIES
optimized boost_date_time-${BOOST_POSTFIX} boost_filesystem-${BOOST_POSTFIX}
boost_regex-${BOOST_POSTFIX}
boost_system-${BOOST_POSTFIX} boost_thread-${BOOST_POSTFIX}
debug boost_date_time-${BOOST_DEBUG_POSTFIX} boost_filesystem-${BOOST_DEBUG_POSTFIX}
boost_regex-${BOOST_DEBUG_POSTFIX}
boost_system-${BOOST_DEBUG_POSTFIX} boost_thread-${BOOST_DEBUG_POSTFIX})
if(WITH_INTERNATIONAL)
set(BOOST_LIBRARIES ${BOOST_LIBRARIES}
optimized boost_locale-${BOOST_POSTFIX}
debug boost_locale-${BOOST_DEBUG_POSTFIX}
)
endif()
if(WITH_CYCLES_OSL)
set(BOOST_LIBRARIES ${BOOST_LIBRARIES}
optimized boost_wave-${BOOST_POSTFIX}
debug boost_wave-${BOOST_DEBUG_POSTFIX}
)
endif()
set(BOOST_LIBPATH ${BOOST}/lib)
set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB -DBOOST_THREAD_USE_LIB ")
endif()
if(WITH_OPENIMAGEIO)
set(OPENIMAGEIO ${LIBDIR}/openimageio)
set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include)
set(OPENIMAGEIO_LIBRARIES OpenImageIO)
set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib)
set(OPENIMAGEIO_DEFINITIONS "")
set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe")
endif()
if(WITH_LLVM)
set(LLVM_ROOT_DIR ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation")
set(LLVM_LIBPATH ${LLVM_ROOT_DIR}/lib)
# Explicitly set llvm lib order.
#---- WARNING ON GCC ORDER OF LIBS IS IMPORTANT, DO NOT CHANGE! ---------
set(LLVM_LIBRARY LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMAnalysis LLVMArchive
LLVMAsmParser LLVMAsmPrinter
LLVMBitReader LLVMBitWriter
LLVMDebugInfo LLVMExecutionEngine
LLVMInstCombine LLVMInstrumentation
LLVMInterpreter LLVMJIT
LLVMLinker LLVMMC
LLVMMCDisassembler LLVMMCJIT
LLVMMCParser LLVMObject
LLVMRuntimeDyld
LLVMSupport
LLVMTableGen LLVMTarget
LLVMTransformUtils LLVMVectorize
LLVMX86AsmParser LLVMX86AsmPrinter
LLVMX86CodeGen LLVMX86Desc
LLVMX86Disassembler LLVMX86Info
LLVMX86Utils LLVMipa
LLVMipo LLVMCore)
# imagehelp is needed by LLVM 3.1 on MinGW, check lib\Support\Windows\Signals.inc
list(APPEND PLATFORM_LINKLIBS -limagehlp)
endif()
if(WITH_OPENCOLORIO)
set(OPENCOLORIO ${LIBDIR}/opencolorio)
set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include)
set(OPENCOLORIO_LIBRARIES OpenColorIO)
set(OPENCOLORIO_LIBPATH ${OPENCOLORIO}/lib)
set(OPENCOLORIO_DEFINITIONS)
endif()
if(WITH_SDL)
set(SDL ${LIBDIR}/sdl)
set(SDL_INCLUDE_DIR ${SDL}/include)
set(SDL_LIBRARY SDL)
set(SDL_LIBPATH ${SDL}/lib)
endif()
if(WITH_OPENVDB)
set(OPENVDB ${LIBDIR}/openvdb)
set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include)
set(OPENVDB_LIBRARIES openvdb ${TBB_LIBRARIES})
set(OPENVDB_LIBPATH ${LIBDIR}/openvdb/lib)
set(OPENVDB_DEFINITIONS)
endif()
if(WITH_ALEMBIC)
# TODO(sergey): For until someone drops by and compiles libraries for
# MinGW we allow users to compile their own Alembic library and use
# that via find_package(),
#
# Once precompiled libraries are there we'll use hardcoded locations.
find_package_wrapper(Alembic)
if(WITH_ALEMBIC_HDF5)
set(HDF5_ROOT_DIR ${LIBDIR}/hdf5)
find_package_wrapper(HDF5)
endif()
if(NOT ALEMBIC_FOUND OR (WITH_ALEMBIC_HDF5 AND NOT HDF5_FOUND))
set(WITH_ALEMBIC OFF)
set(WITH_ALEMBIC_HDF5 OFF)
endif()
endif()
set(PLATFORM_LINKFLAGS "-Xlinker --stack=2097152")
## DISABLE - causes linking errors
## for re-distribution, so users dont need mingw installed
# set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -static-libgcc -static-libstdc++")

View File

@@ -1,490 +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) 2016, Blender Foundation
# All rights reserved.
#
# Contributor(s): Sergey Sharybin.
#
# ***** END GPL LICENSE BLOCK *****
# Libraries configuration for Windows when compiling with MSVC.
macro(warn_hardcoded_paths package_name
)
if(WITH_WINDOWS_FIND_MODULES)
message(WARNING "Using HARDCODED ${package_name} locations")
endif(WITH_WINDOWS_FIND_MODULES)
endmacro()
macro(windows_find_package package_name
)
if(WITH_WINDOWS_FIND_MODULES)
find_package( ${package_name})
endif(WITH_WINDOWS_FIND_MODULES)
endmacro()
add_definitions(-DWIN32)
# Minimum MSVC Version
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
if(MSVC_VERSION EQUAL 1800)
set(_min_ver "18.0.31101")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${_min_ver})
message(FATAL_ERROR
"Visual Studio 2013 (Update 4, ${_min_ver}) required, "
"found (${CMAKE_CXX_COMPILER_VERSION})")
endif()
endif()
if(MSVC_VERSION EQUAL 1900)
set(_min_ver "19.0.24210")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${_min_ver})
message(FATAL_ERROR
"Visual Studio 2015 (Update 3, ${_min_ver}) required, "
"found (${CMAKE_CXX_COMPILER_VERSION})")
endif()
endif()
endif()
unset(_min_ver)
# needed for some MSVC installations
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO")
list(APPEND PLATFORM_LINKLIBS
ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32
advapi32 shfolder shell32 ole32 oleaut32 uuid psapi Dbghelp
)
if(WITH_INPUT_IME)
list(APPEND PLATFORM_LINKLIBS imm32)
endif()
add_definitions(
-D_CRT_NONSTDC_NO_DEPRECATE
-D_CRT_SECURE_NO_DEPRECATE
-D_SCL_SECURE_NO_DEPRECATE
-D_CONSOLE
-D_LIB
)
# MSVC11 needs _ALLOW_KEYWORD_MACROS to build
add_definitions(-D_ALLOW_KEYWORD_MACROS)
# We want to support Vista level ABI
add_definitions(-D_WIN32_WINNT=0x600)
# Make cmake find the msvc redistributables
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
include(InstallRequiredSystemLibraries)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /nologo /J /Gd /MP /EHsc")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd /MP")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT")
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MT")
set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} /MT")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MT")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /MT")
set(PLATFORM_LINKFLAGS "/SUBSYSTEM:CONSOLE /STACK:2097152 /INCREMENTAL:NO ")
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:msvcmrt.lib /NODEFAULTLIB:msvcurt.lib /NODEFAULTLIB:msvcrtd.lib ")
# Ignore meaningless for us linker warnings.
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /ignore:4049 /ignore:4217 /ignore:4221")
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221")
# MSVC only, Mingw doesnt need
if(CMAKE_CL_64)
set(PLATFORM_LINKFLAGS "/MACHINE:X64 ${PLATFORM_LINKFLAGS}")
else()
set(PLATFORM_LINKFLAGS "/MACHINE:IX86 /LARGEADDRESSAWARE ${PLATFORM_LINKFLAGS}")
endif()
set(PLATFORM_LINKFLAGS_DEBUG "/IGNORE:4099 /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libc.lib")
if(NOT DEFINED LIBDIR)
# Setup 64bit and 64bit windows systems
if(CMAKE_CL_64)
message(STATUS "64 bit compiler detected.")
set(LIBDIR_BASE "win64")
else()
message(STATUS "32 bit compiler detected.")
set(LIBDIR_BASE "windows")
endif()
if(MSVC_VERSION EQUAL 1910)
message(STATUS "Visual Studio 2017 detected.")
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc14)
elseif(MSVC_VERSION EQUAL 1900)
message(STATUS "Visual Studio 2015 detected.")
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc14)
else()
message(STATUS "Visual Studio 2013 detected.")
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc12)
endif()
else()
message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
endif()
if(NOT EXISTS "${LIBDIR}/")
message(FATAL_ERROR "Windows requires pre-compiled libs at: '${LIBDIR}'")
endif()
# Add each of our libraries to our cmake_prefix_path so find_package() could work
file(GLOB children RELATIVE ${LIBDIR} ${LIBDIR}/*)
foreach(child ${children})
if(IS_DIRECTORY ${LIBDIR}/${child})
list(APPEND CMAKE_PREFIX_PATH ${LIBDIR}/${child})
endif()
endforeach()
set(ZLIB_INCLUDE_DIRS ${LIBDIR}/zlib/include)
set(ZLIB_LIBRARIES ${LIBDIR}/zlib/lib/libz_st.lib)
set(ZLIB_INCLUDE_DIR ${LIBDIR}/zlib/include)
set(ZLIB_LIBRARY ${LIBDIR}/zlib/lib/libz_st.lib)
set(ZLIB_DIR ${LIBDIR}/zlib)
windows_find_package(zlib) # we want to find before finding things that depend on it like png
windows_find_package(png)
if(NOT PNG_FOUND)
warn_hardcoded_paths(libpng)
set(PNG_PNG_INCLUDE_DIR ${LIBDIR}/png/include)
set(PNG_LIBRARIES libpng)
set(PNG "${LIBDIR}/png")
set(PNG_INCLUDE_DIRS "${PNG}/include")
set(PNG_LIBPATH ${PNG}/lib) # not cmake defined
endif()
set(JPEG_NAMES ${JPEG_NAMES} libjpeg)
windows_find_package(jpeg REQUIRED)
if(NOT JPEG_FOUND)
warn_hardcoded_paths(jpeg)
set(JPEG_INCLUDE_DIR ${LIBDIR}/jpeg/include)
set(JPEG_LIBRARIES ${LIBDIR}/jpeg/lib/libjpeg.lib)
endif()
set(PTHREADS_INCLUDE_DIRS ${LIBDIR}/pthreads/include)
set(PTHREADS_LIBRARIES ${LIBDIR}/pthreads/lib/pthreadVC2.lib)
set(FREETYPE ${LIBDIR}/freetype)
set(FREETYPE_INCLUDE_DIRS
${LIBDIR}/freetype/include
${LIBDIR}/freetype/include/freetype2
)
set(FREETYPE_LIBRARY ${LIBDIR}/freetype/lib/freetype2ST.lib)
windows_find_package(freetype REQUIRED)
if(WITH_FFTW3)
set(FFTW3 ${LIBDIR}/fftw3)
set(FFTW3_LIBRARIES libfftw)
set(FFTW3_INCLUDE_DIRS ${FFTW3}/include)
set(FFTW3_LIBPATH ${FFTW3}/lib)
endif()
if(WITH_OPENCOLLADA)
set(OPENCOLLADA ${LIBDIR}/opencollada)
set(OPENCOLLADA_INCLUDE_DIRS
${OPENCOLLADA}/include/opencollada/COLLADAStreamWriter
${OPENCOLLADA}/include/opencollada/COLLADABaseUtils
${OPENCOLLADA}/include/opencollada/COLLADAFramework
${OPENCOLLADA}/include/opencollada/COLLADASaxFrameworkLoader
${OPENCOLLADA}/include/opencollada/GeneratedSaxParser
)
set(OPENCOLLADA_LIBRARIES
${OPENCOLLADA}/lib/opencollada/OpenCOLLADASaxFrameworkLoader.lib
${OPENCOLLADA}/lib/opencollada/OpenCOLLADAFramework.lib
${OPENCOLLADA}/lib/opencollada/OpenCOLLADABaseUtils.lib
${OPENCOLLADA}/lib/opencollada/OpenCOLLADAStreamWriter.lib
${OPENCOLLADA}/lib/opencollada/MathMLSolver.lib
${OPENCOLLADA}/lib/opencollada/GeneratedSaxParser.lib
${OPENCOLLADA}/lib/opencollada/xml.lib
${OPENCOLLADA}/lib/opencollada/buffer.lib
${OPENCOLLADA}/lib/opencollada/ftoa.lib
)
if(NOT WITH_LLVM)
list(APPEND OPENCOLLADA_LIBRARIES ${OPENCOLLADA}/lib/opencollada/UTF.lib)
endif()
set(PCRE_LIBRARIES
${OPENCOLLADA}/lib/opencollada/pcre.lib
)
endif()
if(WITH_CODEC_FFMPEG)
set(FFMPEG_INCLUDE_DIRS
${LIBDIR}/ffmpeg/include
${LIBDIR}/ffmpeg/include/msvc
)
windows_find_package(FFMPEG)
if(NOT FFMPEG_FOUND)
warn_hardcoded_paths(ffmpeg)
set(FFMPEG_LIBRARY_VERSION 57)
set(FFMPEG_LIBRARY_VERSION_AVU 55)
set(FFMPEG_LIBRARIES
${LIBDIR}/ffmpeg/lib/avcodec.lib
${LIBDIR}/ffmpeg/lib/avformat.lib
${LIBDIR}/ffmpeg/lib/avdevice.lib
${LIBDIR}/ffmpeg/lib/avutil.lib
${LIBDIR}/ffmpeg/lib/swscale.lib
)
endif()
endif()
if(WITH_IMAGE_OPENEXR)
set(OPENEXR_ROOT_DIR ${LIBDIR}/openexr)
set(OPENEXR_VERSION "2.1")
windows_find_package(OPENEXR REQUIRED)
if(NOT OPENEXR_FOUND)
warn_hardcoded_paths(OpenEXR)
set(OPENEXR ${LIBDIR}/openexr)
set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include)
set(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR} ${OPENEXR}/include/OpenEXR)
set(OPENEXR_LIBPATH ${OPENEXR}/lib)
set(OPENEXR_LIBRARIES
optimized ${OPENEXR_LIBPATH}/Iex-2_2.lib
optimized ${OPENEXR_LIBPATH}/Half.lib
optimized ${OPENEXR_LIBPATH}/IlmImf-2_2.lib
optimized ${OPENEXR_LIBPATH}/Imath-2_2.lib
optimized ${OPENEXR_LIBPATH}/IlmThread-2_2.lib
debug ${OPENEXR_LIBPATH}/Iex-2_2_d.lib
debug ${OPENEXR_LIBPATH}/Half_d.lib
debug ${OPENEXR_LIBPATH}/IlmImf-2_2_d.lib
debug ${OPENEXR_LIBPATH}/Imath-2_2_d.lib
debug ${OPENEXR_LIBPATH}/IlmThread-2_2_d.lib
)
endif()
endif()
if(WITH_IMAGE_TIFF)
# Try to find tiff first then complain and set static and maybe wrong paths
windows_find_package(TIFF)
if(NOT TIFF_FOUND)
warn_hardcoded_paths(libtiff)
set(TIFF_LIBRARY ${LIBDIR}/tiff/lib/libtiff.lib)
set(TIFF_INCLUDE_DIR ${LIBDIR}/tiff/include)
endif()
endif()
if(WITH_JACK)
set(JACK_INCLUDE_DIRS
${LIBDIR}/jack/include/jack
${LIBDIR}/jack/include
)
set(JACK_LIBRARIES optimized ${LIBDIR}/jack/lib/libjack.lib debug ${LIBDIR}/jack/lib/libjack_d.lib)
endif()
if(WITH_PYTHON)
set(PYTHON_VERSION 3.5) # CACHE STRING)
string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
# Use shared libs for vc2008 and vc2010 until we actually have vc2010 libs
set(PYTHON_LIBRARY ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}.lib)
unset(_PYTHON_VERSION_NO_DOTS)
# Shared includes for both vc2008 and vc2010
set(PYTHON_INCLUDE_DIR ${LIBDIR}/python/include/python${PYTHON_VERSION})
# uncached vars
set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}")
set(PYTHON_LIBRARIES "${PYTHON_LIBRARY}")
endif()
if(WITH_BOOST)
if(WITH_CYCLES_OSL)
set(boost_extra_libs wave)
endif()
if(WITH_INTERNATIONAL)
list(APPEND boost_extra_libs locale)
endif()
if(WITH_OPENVDB)
list(APPEND boost_extra_libs iostreams)
endif()
set(Boost_USE_STATIC_RUNTIME ON) # prefix lib
set(Boost_USE_MULTITHREADED ON) # suffix -mt
set(Boost_USE_STATIC_LIBS ON) # suffix -s
if (WITH_WINDOWS_FIND_MODULES)
find_package(Boost COMPONENTS date_time filesystem thread regex system ${boost_extra_libs})
endif (WITH_WINDOWS_FIND_MODULES)
if(NOT Boost_FOUND)
warn_hardcoded_paths(BOOST)
set(BOOST ${LIBDIR}/boost)
set(BOOST_INCLUDE_DIR ${BOOST}/include)
if(MSVC12)
set(BOOST_LIBPATH ${BOOST}/lib)
set(BOOST_POSTFIX "vc120-mt-s-1_60.lib")
set(BOOST_DEBUG_POSTFIX "vc120-mt-sgd-1_60.lib")
else()
set(BOOST_LIBPATH ${BOOST}/lib)
set(BOOST_POSTFIX "vc140-mt-s-1_60.lib")
set(BOOST_DEBUG_POSTFIX "vc140-mt-sgd-1_60.lib")
endif()
set(BOOST_LIBRARIES
optimized libboost_date_time-${BOOST_POSTFIX}
optimized libboost_filesystem-${BOOST_POSTFIX}
optimized libboost_regex-${BOOST_POSTFIX}
optimized libboost_system-${BOOST_POSTFIX}
optimized libboost_thread-${BOOST_POSTFIX}
debug libboost_date_time-${BOOST_DEBUG_POSTFIX}
debug libboost_filesystem-${BOOST_DEBUG_POSTFIX}
debug libboost_regex-${BOOST_DEBUG_POSTFIX}
debug libboost_system-${BOOST_DEBUG_POSTFIX}
debug libboost_thread-${BOOST_DEBUG_POSTFIX}
)
if(WITH_CYCLES_OSL)
set(BOOST_LIBRARIES ${BOOST_LIBRARIES}
optimized libboost_wave-${BOOST_POSTFIX}
debug libboost_wave-${BOOST_DEBUG_POSTFIX})
endif()
if(WITH_INTERNATIONAL)
set(BOOST_LIBRARIES ${BOOST_LIBRARIES}
optimized libboost_locale-${BOOST_POSTFIX}
debug libboost_locale-${BOOST_DEBUG_POSTFIX})
endif()
else() # we found boost using find_package
set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS})
set(BOOST_LIBRARIES ${Boost_LIBRARIES})
set(BOOST_LIBPATH ${Boost_LIBRARY_DIRS})
endif()
set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB")
endif()
if(WITH_OPENIMAGEIO)
windows_find_package(OpenImageIO)
set(OPENIMAGEIO ${LIBDIR}/openimageio)
set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include)
set(OIIO_OPTIMIZED optimized OpenImageIO optimized OpenImageIO_Util)
set(OIIO_DEBUG debug OpenImageIO_d debug OpenImageIO_Util_d)
set(OPENIMAGEIO_LIBRARIES ${OIIO_OPTIMIZED} ${OIIO_DEBUG})
set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib)
set(OPENIMAGEIO_DEFINITIONS "-DUSE_TBB=0")
set(OPENCOLORIO_DEFINITIONS "-DOCIO_STATIC_BUILD")
set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe")
add_definitions(-DOIIO_STATIC_BUILD)
add_definitions(-DOIIO_NO_SSE=1)
endif()
if(WITH_LLVM)
set(LLVM_ROOT_DIR ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation")
file(GLOB LLVM_LIBRARY_OPTIMIZED ${LLVM_ROOT_DIR}/lib/*.lib)
if(EXISTS ${LLVM_ROOT_DIR}/debug/lib)
foreach(LLVM_OPTIMIZED_LIB ${LLVM_LIBRARY_OPTIMIZED})
get_filename_component(LIBNAME ${LLVM_OPTIMIZED_LIB} ABSOLUTE)
list(APPEND LLVM_LIBS optimized ${LIBNAME})
endforeach(LLVM_OPTIMIZED_LIB)
file(GLOB LLVM_LIBRARY_DEBUG ${LLVM_ROOT_DIR}/debug/lib/*.lib)
foreach(LLVM_DEBUG_LIB ${LLVM_LIBRARY_DEBUG})
get_filename_component(LIBNAME ${LLVM_DEBUG_LIB} ABSOLUTE)
list(APPEND LLVM_LIBS debug ${LIBNAME})
endforeach(LLVM_DEBUG_LIB)
set(LLVM_LIBRARY ${LLVM_LIBS})
else()
message(WARNING "LLVM debug libs not present on this system. Using release libs for debug builds.")
set(LLVM_LIBRARY ${LLVM_LIBRARY_OPTIMIZED})
endif()
endif()
if(WITH_OPENCOLORIO)
set(OPENCOLORIO ${LIBDIR}/opencolorio)
set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include)
set(OPENCOLORIO_LIBRARIES OpenColorIO)
set(OPENCOLORIO_LIBPATH ${LIBDIR}/opencolorio/lib)
set(OPENCOLORIO_DEFINITIONS)
endif()
if(WITH_OPENVDB)
set(BLOSC_LIBRARIES optimized ${LIBDIR}/blosc/lib/libblosc.lib debug ${LIBDIR}/blosc/lib/libblosc_d.lib)
set(TBB_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbb.lib debug ${LIBDIR}/tbb/lib/tbb_debug.lib)
set(TBB_INCLUDE_DIR ${LIBDIR}/tbb/include)
set(OPENVDB ${LIBDIR}/openvdb)
set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include ${TBB_INCLUDE_DIR})
set(OPENVDB_LIBRARIES optimized openvdb debug openvdb_d ${TBB_LIBRARIES} ${BLOSC_LIBRARIES})
set(OPENVDB_LIBPATH ${LIBDIR}/openvdb/lib)
endif()
if(WITH_ALEMBIC)
set(ALEMBIC ${LIBDIR}/alembic)
set(ALEMBIC_INCLUDE_DIR ${ALEMBIC}/include)
set(ALEMBIC_INCLUDE_DIRS ${ALEMBIC_INCLUDE_DIR})
set(ALEMBIC_LIBPATH ${ALEMBIC}/lib)
set(ALEMBIC_LIBRARIES optimized alembic debug alembic_d)
endif()
if(WITH_MOD_CLOTH_ELTOPO)
set(LAPACK ${LIBDIR}/lapack)
# set(LAPACK_INCLUDE_DIR ${LAPACK}/include)
set(LAPACK_LIBPATH ${LAPACK}/lib)
set(LAPACK_LIBRARIES
${LIBDIR}/lapack/lib/libf2c.lib
${LIBDIR}/lapack/lib/clapack_nowrap.lib
${LIBDIR}/lapack/lib/BLAS_nowrap.lib
)
endif()
if(WITH_OPENSUBDIV OR WITH_CYCLES_OPENSUBDIV)
set(OPENSUBDIV_INCLUDE_DIR ${LIBDIR}/opensubdiv/include)
set(OPENSUBDIV_LIBPATH ${LIBDIR}/opensubdiv/lib)
set(OPENSUBDIV_LIBRARIES ${OPENSUBDIV_LIBPATH}/osdCPU.lib ${OPENSUBDIV_LIBPATH}/osdGPU.lib)
find_package(OpenSubdiv)
endif()
if(WITH_SDL)
set(SDL ${LIBDIR}/sdl)
set(SDL_INCLUDE_DIR ${SDL}/include)
set(SDL_LIBPATH ${SDL}/lib)
# MinGW TODO: Update MinGW to SDL2
if(NOT CMAKE_COMPILER_IS_GNUCC)
set(SDL_LIBRARY SDL2)
else()
set(SDL_LIBRARY SDL)
endif()
endif()
# Audio IO
if(WITH_SYSTEM_AUDASPACE)
set(AUDASPACE_INCLUDE_DIRS ${LIBDIR}/audaspace/include/audaspace)
set(AUDASPACE_LIBRARIES ${LIBDIR}/audaspace/lib/audaspace.lib)
set(AUDASPACE_C_INCLUDE_DIRS ${LIBDIR}/audaspace/include/audaspace)
set(AUDASPACE_C_LIBRARIES ${LIBDIR}/audaspace/lib/audaspace-c.lib)
set(AUDASPACE_PY_INCLUDE_DIRS ${LIBDIR}/audaspace/include/audaspace)
set(AUDASPACE_PY_LIBRARIES ${LIBDIR}/audaspace/lib/audaspace-py.lib)
endif()
# used in many places so include globally, like OpenGL
blender_include_dirs_sys("${PTHREADS_INCLUDE_DIRS}")
#find signtool
SET(ProgramFilesX86_NAME "ProgramFiles(x86)") #env dislikes the ( )
find_program(SIGNTOOL_EXE signtool
HINTS
"$ENV{${ProgramFilesX86_NAME}}/Windows Kits/10/bin/x86/"
"$ENV{ProgramFiles}/Windows Kits/10/bin/x86/"
"$ENV{${ProgramFilesX86_NAME}}/Windows Kits/8.1/bin/x86/"
"$ENV{ProgramFiles}/Windows Kits/8.1/bin/x86/"
"$ENV{${ProgramFilesX86_NAME}}/Windows Kits/8.0/bin/x86/"
"$ENV{ProgramFiles}/Windows Kits/8.0/bin/x86/"
)

View File

@@ -6,10 +6,10 @@
BASE_DIR="$PWD"
blender_srcdir=$(dirname -- $0)/../..
blender_version=$(grep "BLENDER_VERSION\s" "$blender_srcdir/source/blender/blenkernel/BKE_blender_version.h" | awk '{print $3}')
blender_version_char=$(grep "BLENDER_VERSION_CHAR\s" "$blender_srcdir/source/blender/blenkernel/BKE_blender_version.h" | awk '{print $3}')
blender_version_cycle=$(grep "BLENDER_VERSION_CYCLE\s" "$blender_srcdir/source/blender/blenkernel/BKE_blender_version.h" | awk '{print $3}')
blender_subversion=$(grep "BLENDER_SUBVERSION\s" "$blender_srcdir/source/blender/blenkernel/BKE_blender_version.h" | awk '{print $3}')
blender_version=$(grep "BLENDER_VERSION\s" "$blender_srcdir/source/blender/blenkernel/BKE_blender.h" | awk '{print $3}')
blender_version_char=$(grep "BLENDER_VERSION_CHAR\s" "$blender_srcdir/source/blender/blenkernel/BKE_blender.h" | awk '{print $3}')
blender_version_cycle=$(grep "BLENDER_VERSION_CYCLE\s" "$blender_srcdir/source/blender/blenkernel/BKE_blender.h" | awk '{print $3}')
blender_subversion=$(grep "BLENDER_SUBVERSION\s" "$blender_srcdir/source/blender/blenkernel/BKE_blender.h" | awk '{print $3}')
if [ "$blender_version_cycle" = "release" ] ; then
VERSION=$(expr $blender_version / 100).$(expr $blender_version % 100)$blender_version_char

View File

@@ -187,7 +187,7 @@ The next table describes the information in the file-header.
</table>
<p>
<a href="https://en.wikipedia.org/wiki/Endianness">Endianness</a> addresses the way values are ordered in a sequence of bytes(see the <a href="#example-endianess">example</a> below):
<a href="http://en.wikipedia.org/wiki/Endianness">Endianness</a> addresses the way values are ordered in a sequence of bytes(see the <a href="#example-endianess">example</a> below):
</p>
<ul>

View File

@@ -38,7 +38,7 @@ PROJECT_NAME = Blender
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = "V2.8x"
PROJECT_NUMBER = "V2.7x"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@@ -699,7 +699,7 @@ LAYOUT_FILE =
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib
# extension is automatically appended if omitted. This requires the bibtex tool
# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
# For LaTeX the style of the bibliography can be controlled using
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. See also \cite for info how to create references.
@@ -1145,7 +1145,7 @@ HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to
# this color. Hue is specified as an angle on a colorwheel, see
# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
# purple, and 360 is red again.
# Minimum value: 0, maximum value: 359, default value: 220.
@@ -1752,7 +1752,7 @@ LATEX_SOURCE_CODE = NO
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. See
# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
# The default value is: plain.
# This tag requires that the tag GENERATE_LATEX is set to YES.

View File

@@ -4,7 +4,7 @@ Persistent Handler Example
By default handlers are freed when loading new files, in some cases you may
wan't the handler stay running across multiple files (when the handler is
part of an add-on for example).
part of an addon for example).
For this the :data:`bpy.app.handlers.persistent` decorator needs to be used.
"""

View File

@@ -5,7 +5,7 @@ Intro
.. warning::
Most of this object should only be useful if you actually manipulate i18n stuff from Python.
If you are a regular add-on, you should only bother about :const:`contexts` member,
If you are a regular addon, you should only bother about :const:`contexts` member,
and the :func:`register`/:func:`unregister` functions! The :func:`pgettext` family of functions
should only be used in rare, specific cases (like e.g. complex "composited" UI strings...).
@@ -21,11 +21,11 @@ Intro
Then, call ``bpy.app.translations.register(__name__, your_dict)`` in your ``register()`` function, and
``bpy.app.translations.unregister(__name__)`` in your ``unregister()`` one.
The ``Manage UI translations`` add-on has several functions to help you collect strings to translate, and
The ``Manage UI translations`` addon has several functions to help you collect strings to translate, and
generate the needed python code (the translation dictionary), as well as optional intermediary po files
if you want some... See
`How to Translate Blender <https://wiki.blender.org/index.php/Dev:Doc/Process/Translate_Blender>`_ and
`Using i18n in Blender Code <https://wiki.blender.org/index.php/Dev:Source/Interface/Internationalization>`_
`How to Translate Blender <http://wiki.blender.org/index.php/Dev:Doc/Process/Translate_Blender>`_ and
`Using i18n in Blender Code <http://wiki.blender.org/index.php/Dev:Source/Interface/Internationalization>`_
for more info.
Module References

View File

@@ -1,10 +1,10 @@
bl_info = {
"name": "Example Add-on Preferences",
"name": "Example Addon Preferences",
"author": "Your Name Here",
"version": (1, 0),
"blender": (2, 65, 0),
"location": "SpaceBar Search -> Add-on Preferences Example",
"description": "Example Add-on",
"location": "SpaceBar Search -> Addon Preferences Example",
"description": "Example Addon",
"warning": "",
"wiki_url": "",
"tracker_url": "",
@@ -18,7 +18,7 @@ from bpy.props import StringProperty, IntProperty, BoolProperty
class ExampleAddonPreferences(AddonPreferences):
# this must match the add-on name, use '__package__'
# this must match the addon name, use '__package__'
# when defining this in a submodule of a python package.
bl_idname = __name__
@@ -37,7 +37,7 @@ class ExampleAddonPreferences(AddonPreferences):
def draw(self, context):
layout = self.layout
layout.label(text="This is a preferences view for our add-on")
layout.label(text="This is a preferences view for our addon")
layout.prop(self, "filepath")
layout.prop(self, "number")
layout.prop(self, "boolean")
@@ -46,7 +46,7 @@ class ExampleAddonPreferences(AddonPreferences):
class OBJECT_OT_addon_prefs_example(Operator):
"""Display example preferences"""
bl_idname = "object.addon_prefs_example"
bl_label = "Add-on Preferences Example"
bl_label = "Addon Preferences Example"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):

View File

@@ -2,9 +2,9 @@
Extending Menus
+++++++++++++++
When creating menus for add-ons you can't reference menus
in Blender's default scripts.
Instead, the add-on can add menu items to existing menus.
When creating menus for addons you can't reference menus in Blender's default
scripts.
Instead, the addon can add menu items to existing menus.
The function menu_draw acts like :class:`Menu.draw`.
"""

View File

@@ -13,7 +13,7 @@ be animated, accessed from the user interface and from python.
definitions are not, this means whenever you load blender the class needs
to be registered too.
This is best done by creating an add-on which loads on startup and registers
This is best done by creating an addon which loads on startup and registers
your properties.
.. note::

View File

@@ -49,7 +49,7 @@ vec2d[:] = vec3d[:2]
# Vectors support 'swizzle' operations
# See https://en.wikipedia.org/wiki/Swizzling_(computer_graphics)
# See http://en.wikipedia.org/wiki/Swizzling_(computer_graphics)
vec.xyz = vec.zyx
vec.xy = vec4d.zw
vec.xyz = vec4d.wzz

View File

@@ -405,7 +405,7 @@ base class --- :class:`SCA_IObject`
.. note::
This attribute is experimental and may be removed (but probably wont be).
This attribute is experemental and may be removed (but probably wont be).
.. note::
@@ -419,7 +419,7 @@ base class --- :class:`SCA_IObject`
.. note::
This attribute is experimental and may be removed (but probably wont be).
This attribute is experemental and may be removed (but probably wont be).
.. note::
@@ -453,7 +453,7 @@ base class --- :class:`SCA_IObject`
.. attribute:: childrenRecursive
all children of this object including children's children, (read-only).
all children of this object including childrens children, (read-only).
:type: :class:`CListValue` of :class:`KX_GameObject`'s
@@ -536,7 +536,7 @@ base class --- :class:`SCA_IObject`
.. method:: getAxisVect(vect)
Returns the axis vector rotates by the object's worldspace orientation.
Returns the axis vector rotates by the objects worldspace orientation.
This is the equivalent of multiplying the vector by the orientation matrix.
:arg vect: a vector to align the axis.
@@ -596,7 +596,7 @@ base class --- :class:`SCA_IObject`
Gets the game object's linear velocity.
This method returns the game object's velocity through it's center of mass, ie no angular velocity component.
This method returns the game object's velocity through it's centre of mass, ie no angular velocity component.
:arg local:
* False: you get the "global" velocity ie: relative to world orientation.
@@ -609,7 +609,7 @@ base class --- :class:`SCA_IObject`
Sets the game object's linear velocity.
This method sets game object's velocity through it's center of mass,
This method sets game object's velocity through it's centre of mass,
ie no angular velocity component.
This requires a dynamic object.
@@ -814,7 +814,7 @@ base class --- :class:`SCA_IObject`
# do something
pass
The face parameter determines the orientation of the normal.
The face paremeter determines the orientation of the normal.
* 0 => hit normal is always oriented towards the ray origin (as if you casted the ray from outside)
* 1 => hit normal is the real face normal (only for mesh object, otherwise face has no effect)
@@ -911,7 +911,7 @@ base class --- :class:`SCA_IObject`
.. note::
The gameObject argument has an advantage that it can convert from a mesh with modifiers applied (such as the Subdivision Surface modifier).
The gameObject argument has an advantage that it can convert from a mesh with modifiers applied (such as subsurf).
.. warning::
@@ -919,7 +919,7 @@ base class --- :class:`SCA_IObject`
.. warning::
If the object is a part of a compound object it will fail (parent or child)
If the object is a part of a combound object it will fail (parent or child)
.. warning::

File diff suppressed because it is too large Load Diff

View File

@@ -23,7 +23,7 @@ The features exposed closely follow the C API,
giving python access to the functions used by blenders own mesh editing tools.
For an overview of BMesh data types and how they reference each other see:
`BMesh Design Document <https://wiki.blender.org/index.php/Dev:Source/Modeling/BMesh/Design>`_ .
`BMesh Design Document <http://wiki.blender.org/index.php/Dev:2.6/Source/Modeling/BMesh/Design>`_ .
.. note::
@@ -31,12 +31,13 @@ For an overview of BMesh data types and how they reference each other see:
**Disk** and **Radial** data is not exposed by the python api since this is for internal use only.
.. warning:: TODO items are...
.. warning::
TODO items are...
* add access to BMesh **walkers**
* add custom-data manipulation functions add/remove/rename.
Example Script
--------------

View File

@@ -204,7 +204,7 @@ Lets say we want to access the texture of a brush via Python, to adjust its ``co
- Start in the default scene and enable 'Sculpt' mode from the 3D-View header.
- From the toolbar expand the **Texture** panel and add a new texture.
*Notice the texture button its self doesn't have very useful links (you can check the tooltips).*
*Notice the texture button its self doesn't have very useful links (you can check the tool-tips).*
- The contrast setting isn't exposed in the sculpt toolbar, so view the texture in the properties panel...
- In the properties button select the Texture context.

View File

@@ -18,7 +18,7 @@ amongst our own scripts and make it easier to use python scripts from other proj
Using our style guide for your own scripts makes it easier if you eventually want to contribute them to blender.
This style guide is known as pep8 and can be found `here <https://www.python.org/dev/peps/pep-0008/>`_
This style guide is known as pep8 and can be found `here <http://www.python.org/dev/peps/pep-0008>`_
A brief listing of pep8 criteria.
@@ -316,7 +316,7 @@ use to join a list of strings (the list may be temporary). In the following exam
Join is fastest on many strings,
`string formatting <https://wiki.blender.org/index.php/Dev:Source/Modeling/BMesh/Design>`__
`string formatting <http://docs.python.org/py3k/library/string.html#string-formatting>`__
is quite fast too (better for converting data types). String arithmetic is slowest.

View File

@@ -1,4 +1,3 @@
*******
Gotchas
*******
@@ -39,6 +38,7 @@ but some operators are more picky about when they run.
In most cases you can figure out what context an operator needs
simply be seeing how it's used in Blender and thinking about what it does.
Unfortunately if you're still stuck - the only way to **really** know
whats going on is to read the source code for the poll function and see what its checking.
@@ -82,6 +82,7 @@ it should be reported to the bug tracker.
Stale Data
==========
No updates after setting values
-------------------------------
@@ -173,8 +174,8 @@ In this situation you can...
.. _info_gotcha_mesh_faces:
N-Gons and Tessellation Faces
=============================
NGons and Tessellation Faces
============================
Since 2.63 NGons are supported, this adds some complexity
since in some cases you need to access triangles/quads still (some exporters for example).
@@ -508,7 +509,7 @@ Unicode Problems
Python supports many different encodings so there is nothing stopping you from
writing a script in ``latin1`` or ``iso-8859-15``.
See `pep-0263 <https://www.python.org/dev/peps/pep-0263/>`_
See `pep-0263 <http://www.python.org/dev/peps/pep-0263/>`_
However this complicates matters for Blender's Python API because ``.blend`` files don't have an explicit encoding.
@@ -656,7 +657,7 @@ Here are some general hints to avoid running into these problems.
.. note::
To find the line of your script that crashes you can use the ``faulthandler`` module.
See the `faulthandler docs <https://docs.python.org/dev/library/faulthandler.html>`_.
See `faulthandler docs <http://docs.python.org/dev/library/faulthandler.html>`_.
While the crash may be in Blenders C/C++ code,
this can help a lot to track down the area of the script that causes the crash.

View File

@@ -19,7 +19,7 @@ This is a typical Python environment so tutorials on how to write Python scripts
will work running the scripts in Blender too.
Blender provides the :mod:`bpy` module to the Python interpreter.
This module can be imported in a script and gives access to Blender data, classes, and functions.
Scripts that deal with Blender data will need to import this module.
Scripts that deal with Blender data will need to import this module.
Here is a simple example of moving a vertex of the object named **Cube**:
@@ -43,7 +43,8 @@ scene manipulation, automation, defining your own toolset and customization.
On startup Blender scans the ``scripts/startup/`` directory for Python modules and imports them.
The exact location of this directory depends on your installation.
See the :ref:`directory layout docs <blender_manual:getting-started_installing-config-directories>`.
`See the directory layout docs
<https://www.blender.org/manual/getting_started/installing_blender/directorylayout.html>`__
Script Loading
@@ -76,22 +77,22 @@ To run as modules:
- The obvious way, ``import some_module`` command from the text window or interactive console.
- Open as a text block and tick "Register" option, this will load with the blend file.
- copy into one of the directories ``scripts/startup``, where they will be automatically imported on startup.
- define as an add-on, enabling the add-on will load it as a Python module.
- define as an addon, enabling the addon will load it as a Python module.
Add-ons
-------
Addons
------
Some of Blenders functionality is best kept optional,
alongside scripts loaded at startup we have add-ons which are kept in their own directory ``scripts/addons``,
alongside scripts loaded at startup we have addons which are kept in their own directory ``scripts/addons``,
and only load on startup if selected from the user preferences.
The only difference between add-ons and built-in Python modules is that add-ons must contain a ``bl_info``
The only difference between addons and built-in Python modules is that addons must contain a ``bl_info``
variable which Blender uses to read metadata such as name, author, category and URL.
The User Preferences add-on listing uses **bl_info** to display information about each add-on.
The user preferences addon listing uses **bl_info** to display information about each addon.
`See Add-ons <https://wiki.blender.org/index.php/Dev:Py/Scripts/Guidelines/Addons>`__
`See Addons <http://wiki.blender.org/index.php/Dev:2.5/Py/Scripts/Guidelines/Addons>`__
for details on the ``bl_info`` dictionary.
@@ -213,7 +214,7 @@ A simple Blender/Python module can look like this:
bpy.utils.register_class(SimpleOperator)
def unregister():
bpy.utils.unregister_class(SimpleOperator)
bpy.utils.unregister_class(SimpleOperator)
if __name__ == "__main__":
register()
@@ -222,7 +223,7 @@ These functions usually appear at the bottom of the script containing class regi
You can also use them for internal purposes setting up data for your own tools but take care
since register won't re-run when a new blend file is loaded.
The register/unregister calls are used so it's possible to toggle add-ons and reload scripts while Blender runs.
The register/unregister calls are used so it's possible to toggle addons and reload scripts while Blender runs.
If the register calls were placed in the body of the script, registration would be called on import,
meaning there would be no distinction between importing a module or loading its classes into Blender.
@@ -327,7 +328,7 @@ Say you want to store material settings for a custom engine.
.. note::
*The class must be registered before being used in a property, failing to do so will raise an error:*
``ValueError: bpy_struct "Material" registration error: my_custom_props could not register``
@@ -429,3 +430,4 @@ Calling these operators:
>>> bpy.ops.object.operator_2()
Hello World OBJECT_OT_operator_2
{'FINISHED'}

View File

@@ -51,7 +51,8 @@ A quick list of helpful things to know before starting:
| ``scripts/startup/bl_operators`` for operators.
Exact location depends on platform, see:
:ref:`Configuration and Data Paths <blender_manual:getting-started_installing-config-directories>`.
`Configuration and Data Paths
<https://www.blender.org/manual/getting_started/installing_blender/directorylayout.html>`__.
Running Scripts

View File

@@ -27,7 +27,7 @@ There are 3 main uses for the terminal, these are:
.. note::
For Linux and macOS users this means starting the terminal first, then running Blender from within it.
For Linux and OSX users this means starting the terminal first, then running Blender from within it.
On Windows the terminal can be enabled from the help menu.
@@ -306,7 +306,7 @@ Advantages include:
This is marked advanced because to run Blender as a Python module requires a special build option.
For instructions on building see
`Building Blender as a Python module <https://wiki.blender.org/index.php/User:Ideasman42/BlenderAsPyModule>`_
`Building Blender as a Python module <http://wiki.blender.org/index.php/User:Ideasman42/BlenderAsPyModule>`_
Python Safety (Build Option)

View File

@@ -1,6 +1,6 @@
Add-on Tutorial
###############
Addon Tutorial
##############
************
Introduction
@@ -36,7 +36,6 @@ Suggested reading before starting this tutorial.
To best troubleshoot any error message Python prints while writing scripts you run blender with from a terminal,
see :ref:`Use The Terminal <use_the_terminal>`.
Documentation Links
===================
@@ -47,48 +46,51 @@ While going through the tutorial you may want to look into our reference documen
- :mod:`bpy.context` api reference. -
*Handy to have a list of available items your script may operate on.*
- :class:`bpy.types.Operator`. -
*The following add-ons define operators, these docs give details and more examples of operators.*
*The following addons define operators, these docs give details and more examples of operators.*
*******
Add-ons
*******
******
Addons
******
What is an Add-on?
==================
An add-on is simply a Python module with some additional requirements so Blender can display it in a list with useful
What is an Addon?
=================
An addon is simply a Python module with some additional requirements so Blender can display it in a list with useful
information.
To give an example, here is the simplest possible add-on.
To give an example, here is the simplest possible addon.
.. code-block:: python
bl_info = {"name": "My Test Add-on", "category": "Object"}
bl_info = {"name": "My Test Addon", "category": "Object"}
def register():
print("Hello World")
def unregister():
print("Goodbye World")
- ``bl_info`` is a dictionary containing add-on metadata such as the title,
version and author to be displayed in the user preferences add-on list.
- ``register`` is a function which only runs when enabling the add-on,
this means the module can be loaded without activating the add-on.
- ``unregister`` is a function to unload anything setup by ``register``, this is called when the add-on is disabled.
- ``bl_info`` is a dictionary containing addon meta-data such as the title, version and author to be displayed in the
user preferences addon list.
- ``register`` is a function which only runs when enabling the addon, this means the module can be loaded without
activating the addon.
- ``unregister`` is a function to unload anything setup by ``register``, this is called when the addon is disabled.
Notice this add-on does not do anything related to Blender, (the :mod:`bpy` module is not imported for example).
This is a contrived example of an add-on that serves to illustrate the point
that the base requirements of an add-on are simple.
Notice this addon does not do anything related to Blender, (the :mod:`bpy` module is not imported for example).
An add-on will typically register operators, panels, menu items etc, but its worth noting that _any_ script can do this,
This is a contrived example of an addon that serves to illustrate the point
that the base requirements of an addon are simple.
An addon will typically register operators, panels, menu items etc, but its worth noting that _any_ script can do this,
when executed from the text editor or even the interactive console - there is nothing inherently different about an
add-on that allows it to integrate with Blender, such functionality is just provided by the :mod:`bpy` module for any
addon that allows it to integrate with Blender, such functionality is just provided by the :mod:`bpy` module for any
script to access.
So an add-on is just a way to encapsulate a Python module in a way a user can easily utilize.
So an addon is just a way to encapsulate a Python module in a way a user can easily utilize.
.. note::
@@ -97,14 +99,14 @@ So an add-on is just a way to encapsulate a Python module in a way a user can ea
Messages will be printed when enabling and disabling.
Your First Add-on
=================
Your First Addon
================
The simplest possible add-on above is useful as an example but not much else.
This next add-on is simple but shows how to integrate a script into Blender using an ``Operator``
The simplest possible addon above was useful as an example but not much else.
This next addon is simple but shows how to integrate a script into Blender using an ``Operator``
which is the typical way to define a tool accessed from menus, buttons and keyboard shortcuts.
For the first example we will make a script that simply moves all objects in a scene.
For the first example we'll make a script that simply moves all objects in a scene.
Write The Script
@@ -121,14 +123,20 @@ Add the following script to the text editor in Blender.
obj.location.x += 1.0
Click the :ref:`Run Script button <blender_manual:editors-text-run-script>`,
all objects in the active scene are moved by 1.0 Blender unit.
.. image:: run_script.png
:width: 924px
:align: center
:height: 574px
:alt: Run Script button
Click the Run Script button, all objects in the active scene are moved by 1.0 Blender unit.
Next we'll make this script into an addon.
Write the Add-on (Simple)
-------------------------
Write the Addon (Simple)
------------------------
This add-on takes the body of the script above, and adds them to an operator's ``execute()`` function.
This addon takes the body of the script above, and adds them to an operator's ``execute()`` function.
.. code-block:: python
@@ -165,7 +173,7 @@ This add-on takes the body of the script above, and adds them to an operator's `
# This allows you to run the script directly from blenders text editor
# to test the add-on without having to install it.
# to test the addon without having to install it.
if __name__ == "__main__":
register()
@@ -198,33 +206,33 @@ Do this by pressing :kbd:`Spacebar` to bring up the operator search dialog and t
The objects should move as before.
*Keep this add-on open in Blender for the next step - Installing.*
*Keep this addon open in Blender for the next step - Installing.*
Install The Add-on
------------------
Install The Addon
-----------------
Once you have your add-on within in Blender's text editor,
Once you have your addon within in Blender's text editor,
you will want to be able to install it so it can be enabled in the user preferences to load on startup.
Even though the add-on above is a test, lets go through the steps anyway so you know how to do it for later.
Even though the addon above is a test, lets go through the steps anyway so you know how to do it for later.
To install the Blender text as an add-on you will first have to save it to disk, take care to obey the naming
To install the Blender text as an addon you will first have to save it to disk, take care to obey the naming
restrictions that apply to Python modules and end with a ``.py`` extension.
Once the file is on disk, you can install it as you would for an add-on downloaded online.
Once the file is on disk, you can install it as you would for an addon downloaded online.
Open the user :menuselection:`File --> User Preferences`,
Select the *Add-on* section, press *Install Add-on...* and select the file.
Open the user :menuselection:`File -> User Preferences`,
Select the *Addon* section, press *Install Addon...* and select the file.
Now the add-on will be listed and you can enable it by pressing the check-box,
Now the addon will be listed and you can enable it by pressing the check-box,
if you want it to be enabled on restart, press *Save as Default*.
.. note::
The destination of the add-on depends on your Blender configuration.
When installing an add-on the source and destination path are printed in the console.
You can also find add-on path locations by running this in the Python console.
The destination of the addon depends on your Blender configuration.
When installing an addon the source and destination path are printed in the console.
You can also find addon path locations by running this in the Python console.
.. code-block:: python
@@ -232,20 +240,20 @@ if you want it to be enabled on restart, press *Save as Default*.
print(addon_utils.paths())
More is written on this topic here:
:ref:`Directory Layout <blender_manual:getting-started_installing-config-directories>`.
`Directory Layout <https://www.blender.org/manual/getting_started/installing_blender/directorylayout.html>`_
Your Second Add-on
==================
Your Second Addon
=================
For our second add-on, we will focus on object instancing - this is - to make linked copies of an object in a
For our second addon, we will focus on object instancing - this is - to make linked copies of an object in a
similar way to what you may have seen with the array modifier.
Write The Script
----------------
As before, first we will start with a script, develop it, then convert into an add-on.
As before, first we will start with a script, develop it, then convert into an addon.
.. code-block:: python
@@ -316,17 +324,17 @@ allows vectors to be multiplied by numbers and matrices.
If you are interested in this area, read into :class:`mathutils.Vector` - there are many handy utility functions
such as getting the angle between vectors, cross product, dot products
as well as more advanced functions in :mod:`mathutils.geometry` such as zier Spline interpolation and
as well as more advanced functions in :mod:`mathutils.geometry` such as bezier spline interpolation and
ray-triangle intersection.
For now we will focus on making this script an add-on, but its good to know that this 3D math module is available and
For now we'll focus on making this script an addon, but its good to know that this 3D math module is available and
can help you with more advanced functionality later on.
Write the Add-on
----------------
Write the Addon
---------------
The first step is to convert the script as-is into an add-on.
The first step is to convert the script as-is into an addon.
.. code-block:: python
@@ -373,7 +381,7 @@ The first step is to convert the script as-is into an add-on.
register()
Everything here has been covered in the previous steps, you may want to try run the add-on still
Everything here has been covered in the previous steps, you may want to try run the addon still
and consider what could be done to make it more useful.
@@ -426,7 +434,7 @@ however the link above includes examples of more advanced property usage.
Menu Item
^^^^^^^^^
Add-ons can add to the user interface of existing panels, headers and menus defined in Python.
Addons can add to the user interface of existing panels, headers and menus defined in Python.
For this example we'll add to an existing menu.
@@ -456,7 +464,7 @@ For docs on extending menus see: :doc:`bpy.types.Menu`.
Keymap
^^^^^^
In Blender, add-ons have their own keymaps so as not to interfere with Blenders built in key-maps.
In Blender addons have their own key-maps so as not to interfere with Blenders built in key-maps.
In the example below, a new object-mode :class:`bpy.types.KeyMap` is added,
then a :class:`bpy.types.KeyMapItem` is added to the key-map which references our newly added operator,
@@ -494,7 +502,7 @@ this allows you to have multiple keys accessing the same operator with different
.. note::
While :kbd:`Ctrl-Shift-Space` isn't a default Blender key shortcut, its hard to make sure add-ons won't
While :kbd:`Ctrl-Shift-Space` isn't a default Blender key shortcut, its hard to make sure addons won't
overwrite each others keymaps, At least take care when assigning keys that they don't
conflict with important functionality within Blender.
@@ -598,14 +606,14 @@ After selecting it from the menu, you can choose how many instance of the cube y
.. note::
Directly executing the script multiple times will add the menu each time too.
While not useful behavior, theres nothing to worry about since add-ons won't register them selves multiple
While not useful behavior, theres nothing to worry about since addons won't register them selves multiple
times when enabled through the user preferences.
Conclusions
===========
Add-ons can encapsulate certain functionality neatly for writing tools to improve your work-flow or for writing utilities
Addons can encapsulate certain functionality neatly for writing tools to improve your work-flow or for writing utilities
for others to use.
While there are limits to what Python can do within Blender, there is certainly a lot that can be achieved without
@@ -628,8 +636,8 @@ Here are some sites you might like to check on after completing this tutorial.
*For more background details on Blender/Python integration.*
- `How to Think Like a Computer Scientist <http://interactivepython.org/courselib/static/thinkcspy/index.html>`_ -
*Great info for those who are still learning Python.*
- `Blender Development (Wiki) <https://wiki.blender.org/index.php/Dev:Contents>`_ -
- `Blender Development (Wiki) <http://wiki.blender.org/index.php/Dev:Contents>`_ -
*Blender Development, general information and helpful links.*
- `Blender Artists (Coding Section) <https://blenderartists.org/forum/forumdisplay.php?47-Coding>`_ -
- `Blender Artists (Coding Section) <http://blenderartists.org/forum/forumdisplay.php?47-Coding>`_ -
*forum where people ask Python development questions*

View File

@@ -27,7 +27,7 @@ output from this tool should be added into "doc/python_api/rst/change_log.rst"
blender --background --python doc/python_api/sphinx_changelog_gen.py -- --dump
# create changelog
blender --background --factory-startup --python doc/python_api/sphinx_changelog_gen.py -- \
blender --background --python doc/python_api/sphinx_changelog_gen.py -- \
--api_from blender_2_63_0.py \
--api_to blender_2_64_0.py \
--api_out changes.rst
@@ -331,7 +331,7 @@ def main():
# When --help or no args are given, print this help
usage_text = "Run blender in background mode with this script: "
"blender --background --factory-startup --python %s -- [options]" % os.path.basename(__file__)
"blender --background --python %s -- [options]" % os.path.basename(__file__)
epilog = "Run this before releases"

View File

@@ -26,16 +26,16 @@ API dump in RST files
---------------------
Run this script from Blender's root path once you have compiled Blender
blender --background --factory-startup -noaudio --python doc/python_api/sphinx_doc_gen.py
./blender.bin --background -noaudio --python doc/python_api/sphinx_doc_gen.py
This will generate python files in doc/python_api/sphinx-in/
providing ./blender is or links to the blender executable
providing ./blender.bin is or links to the blender executable
To choose sphinx-in directory:
blender --background --factory-startup --python doc/python_api/sphinx_doc_gen.py -- --output ../python_api
./blender.bin --background --python doc/python_api/sphinx_doc_gen.py -- --output ../python_api
For quick builds:
blender --background --factory-startup --python doc/python_api/sphinx_doc_gen.py -- --partial bmesh.*
./blender.bin --background --python doc/python_api/sphinx_doc_gen.py -- --partial bmesh.*
Sphinx: HTML generation
@@ -46,6 +46,8 @@ Sphinx: HTML generation
cd doc/python_api
sphinx-build sphinx-in sphinx-out
This requires sphinx 1.0.7 to be installed.
Sphinx: PDF generation
----------------------
@@ -66,7 +68,7 @@ except ImportError:
import sys
sys.exit()
import rna_info # Blender module
import rna_info # Blender module
def rna_info_BuildRNAInfo_cache():
@@ -84,7 +86,7 @@ import shutil
import logging
from platform import platform
PLATFORM = platform().split('-')[0].lower() # 'linux', 'darwin', 'windows'
PLATFORM = platform().split('-')[0].lower() # 'linux', 'darwin', 'windows'
SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
@@ -206,12 +208,12 @@ BPY_LOGGER.setLevel(logging.DEBUG)
"""
# for quick rebuilds
rm -rf /b/doc/python_api/sphinx-* && \
./blender -b -noaudio --factory-startup -P doc/python_api/sphinx_doc_gen.py && \
./blender.bin -b -noaudio --factory-startup -P doc/python_api/sphinx_doc_gen.py && \
sphinx-build doc/python_api/sphinx-in doc/python_api/sphinx-out
or
./blender -b -noaudio --factory-startup -P doc/python_api/sphinx_doc_gen.py -- -f -B
./blender.bin -b -noaudio --factory-startup -P doc/python_api/sphinx_doc_gen.py -- -f -B
"""
# Switch for quick testing so doc-builds don't take so long
@@ -363,7 +365,7 @@ INFO_DOCS = (
("info_overview.rst",
"Blender/Python API Overview: a more complete explanation of Python integration"),
("info_tutorial_addon.rst",
"Blender/Python Add-on Tutorial: a step by step guide on how to write an add-on from scratch"),
"Blender/Python Addon Tutorial: a step by step guide on how to write an addon from scratch"),
("info_api_reference.rst",
"Blender/Python API Reference Usage: examples of how to use the API reference docs"),
("info_best_practice.rst",
@@ -418,7 +420,7 @@ MODULE_GROUPING = {
blender_version_strings = [str(v) for v in bpy.app.version]
# converting bytes to strings, due to T30154
# converting bytes to strings, due to #30154
BLENDER_REVISION = str(bpy.app.build_hash, 'utf_8')
BLENDER_DATE = str(bpy.app.build_date, 'utf_8')
@@ -1012,9 +1014,6 @@ context_type_map = {
"active_bone": ("EditBone", False),
"active_gpencil_frame": ("GreasePencilLayer", True),
"active_gpencil_layer": ("GPencilLayer", True),
"active_gpencil_brush": ("GPencilSculptBrush", False),
"active_gpencil_palette": ("GPencilPalette", True),
"active_gpencil_palettecolor": ("GPencilPaletteColor", True),
"active_node": ("Node", False),
"active_object": ("Object", False),
"active_operator": ("Operator", False),
@@ -1565,9 +1564,9 @@ def pyrna2sphinx(basepath):
# operators
def write_ops():
API_BASEURL = "https://developer.blender.org/diffusion/B/browse/master/release/scripts "
API_BASEURL_ADDON = "https://developer.blender.org/diffusion/BA"
API_BASEURL_ADDON_CONTRIB = "https://developer.blender.org/diffusion/BAC"
API_BASEURL = "http://svn.blender.org/svnroot/bf-blender/trunk/blender/release/scripts"
API_BASEURL_ADDON = "http://svn.blender.org/svnroot/bf-extensions/trunk/py/scripts"
API_BASEURL_ADDON_CONTRIB = "http://svn.blender.org/svnroot/bf-extensions/contrib/py/scripts"
op_modules = {}
for op in ops.values():
@@ -1632,9 +1631,6 @@ def write_sphinx_conf_py(basepath):
file = open(filepath, "w", encoding="utf-8")
fw = file.write
fw("import sys, os\n\n")
fw("extensions = ['sphinx.ext.intersphinx']\n\n")
fw("intersphinx_mapping = {'blender_manual': ('https://docs.blender.org/manual/en/dev/', None)}\n\n")
fw("project = 'Blender'\n")
# fw("master_doc = 'index'\n")
fw("copyright = u'Blender Foundation'\n")
@@ -1646,21 +1642,16 @@ def write_sphinx_conf_py(basepath):
if ARGS.sphinx_theme == "blender-org":
fw("html_theme_path = ['../']\n")
# copied with the theme, exclude else we get an error [T28873]
# copied with the theme, exclude else we get an error [#28873]
fw("html_favicon = 'favicon.ico'\n") # in <theme>/static/
# not helpful since the source is generated, adds to upload size.
fw("html_copy_source = False\n")
fw("html_show_sphinx = False\n")
fw("html_split_index = True\n")
fw("\n")
# needed for latex, pdf gen
fw("latex_elements = {\n")
fw(" 'papersize': 'a4paper',\n")
fw("}\n\n")
fw("latex_documents = [ ('contents', 'contents.tex', 'Blender Index', 'Blender Foundation', 'manual'), ]\n")
fw("latex_paper_size = 'a4paper'\n")
file.close()

View File

@@ -1,186 +0,0 @@
#!/usr/bin/env python3
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# Contributor(s): Bastien Montagne
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
"""
This is a helper script to generate Blender Python API documentation (using Sphinx), and update server data using rsync.
You'll need to specify your user login and password, obviously.
Example usage:
./sphinx_doc_update.py --mirror ../../../docs/remote_api_backup/ --source ../.. --blender ../../../build_cmake/bin/blender --user foobar --password barfoo
"""
import os
import shutil
import subprocess
import sys
import tempfile
import zipfile
DEFAULT_RSYNC_SERVER = "docs.blender.org"
DEFAULT_RSYNC_ROOT = "/api/"
DEFAULT_SYMLINK_ROOT = "/data/www/vhosts/docs.blender.org/api"
def argparse_create():
import argparse
global __doc__
# When --help or no args are given, print this help
usage_text = __doc__
parser = argparse.ArgumentParser(description=usage_text,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument(
"--mirror", dest="mirror_dir",
metavar='PATH', required=True,
help="Path to local rsync mirror of api doc server")
parser.add_argument(
"--source", dest="source_dir",
metavar='PATH', required=True,
help="Path to Blender git repository")
parser.add_argument(
"--blender", dest="blender",
metavar='PATH', required=True,
help="Path to Blender executable")
parser.add_argument(
"--rsync-server", dest="rsync_server", default=DEFAULT_RSYNC_SERVER,
metavar='RSYNCSERVER', type=str, required=False,
help=("rsync server address"))
parser.add_argument(
"--rsync-root", dest="rsync_root", default=DEFAULT_RSYNC_ROOT,
metavar='RSYNCROOT', type=str, required=False,
help=("Root path of API doc on rsync server"))
parser.add_argument(
"--user", dest="user",
metavar='USER', type=str, required=True,
help=("User to login on rsync server"))
parser.add_argument(
"--password", dest="password",
metavar='PASSWORD', type=str, required=True,
help=("Password to login on rsync server"))
return parser
def main():
# ----------
# Parse Args
args = argparse_create().parse_args()
rsync_base = "rsync://%s@%s:%s" % (args.user, args.rsync_server, args.rsync_root)
# I) Update local mirror using rsync.
rsync_mirror_cmd = ("rsync", "--delete-after", "-avzz", rsync_base, args.mirror_dir)
subprocess.run(rsync_mirror_cmd, env=dict(os.environ, RSYNC_PASSWORD=args.password))
with tempfile.TemporaryDirectory() as tmp_dir:
# II) Generate doc source in temp dir.
doc_gen_cmd = (args.blender, "--background", "-noaudio", "--factory-startup", "--python-exit-code", "1",
"--python", "%s/doc/python_api/sphinx_doc_gen.py" % args.source_dir, "--",
"--output", tmp_dir)
subprocess.run(doc_gen_cmd)
# III) Get Blender version info.
blenver = blenver_zip = ""
getver_file = os.path.join(tmp_dir, "blendver.txt")
getver_script = (""
"import sys, bpy\n"
"with open(sys.argv[-1], 'w') as f:\n"
" f.write('%d_%d%s_release\\n' % (bpy.app.version[0], bpy.app.version[1], bpy.app.version_char)\n"
" if bpy.app.version_cycle in {'rc', 'release'} else '%d_%d_%d\\n' % bpy.app.version)\n"
" f.write('%d_%d_%d' % bpy.app.version)\n")
get_ver_cmd = (args.blender, "--background", "-noaudio", "--factory-startup", "--python-exit-code", "1",
"--python-expr", getver_script, "--", getver_file)
subprocess.run(get_ver_cmd)
with open(getver_file) as f:
blenver, blenver_zip = f.read().split("\n")
os.remove(getver_file)
# IV) Build doc.
curr_dir = os.getcwd()
os.chdir(tmp_dir)
sphinx_cmd = ("sphinx-build", "-b", "html", "sphinx-in", "sphinx-out")
subprocess.run(sphinx_cmd)
shutil.rmtree(os.path.join("sphinx-out", ".doctrees"))
os.chdir(curr_dir)
# V) Cleanup existing matching dir in server mirror (if any), and copy new doc.
api_name = "blender_python_api_%s" % blenver
api_dir = os.path.join(args.mirror_dir, api_name)
if os.path.exists(api_dir):
shutil.rmtree(api_dir)
os.rename(os.path.join(tmp_dir, "sphinx-out"), api_dir)
# VI) Create zip archive.
zip_name = "blender_python_reference_%s" % blenver_zip # We can't use 'release' postfix here...
zip_path = os.path.join(args.mirror_dir, zip_name)
with zipfile.ZipFile(zip_path, 'w') as zf:
for dirname, _, filenames in os.walk(api_dir):
for filename in filenames:
filepath = os.path.join(dirname, filename)
zip_filepath = os.path.join(zip_name, os.path.relpath(filepath, api_dir))
zf.write(filepath, arcname=zip_filepath)
os.rename(zip_path, os.path.join(api_dir, "%s.zip" % zip_name))
# VII) Create symlinks and html redirects.
#~ os.symlink(os.path.join(DEFAULT_SYMLINK_ROOT, api_name, "contents.html"), os.path.join(api_dir, "index.html"))
os.symlink("./contents.html", os.path.join(api_dir, "index.html"))
if blenver.endswith("release"):
symlink = os.path.join(args.mirror_dir, "blender_python_api_current")
os.remove(symlink)
os.symlink("./%s" % api_name, symlink)
with open(os.path.join(args.mirror_dir, "250PythonDoc/index.html"), 'w') as f:
f.write("<html><head><title>Redirecting...</title><meta http-equiv=\"REFRESH\""
"content=\"0;url=../%s/\"></head><body>Redirecting...</body></html>" % api_name)
else:
symlink = os.path.join(args.mirror_dir, "blender_python_api_master")
os.remove(symlink)
os.symlink("./%s" % api_name, symlink)
with open(os.path.join(args.mirror_dir, "blender_python_api/index.html"), 'w') as f:
f.write("<html><head><title>Redirecting...</title><meta http-equiv=\"REFRESH\""
"content=\"0;url=../%s/\"></head><body>Redirecting...</body></html>" % api_name)
# VIII) Upload (first do a dry-run so user can ensure everything is OK).
print("Doc generated in local mirror %s, please check it before uploading "
"(hit [Enter] to continue, [Ctrl-C] to exit):" % api_dir)
sys.stdin.read(1)
rsync_mirror_cmd = ("rsync", "--dry-run", "--delete-after", "-avzz", args.mirror_dir, rsync_base)
subprocess.run(rsync_mirror_cmd, env=dict(os.environ, RSYNC_PASSWORD=args.password))
print("Rsync upload simulated, please check every thing is OK (hit [Enter] to continue, [Ctrl-C] to exit):")
sys.stdin.read(1)
rsync_mirror_cmd = ("rsync", "--delete-after", "-avzz", args.mirror_dir, rsync_base)
subprocess.run(rsync_mirror_cmd, env=dict(os.environ, RSYNC_PASSWORD=args.password))
if __name__ == "__main__":
main()

View File

@@ -77,7 +77,7 @@ namespace std {
void resize(size_type new_size)
{ resize(new_size, T()); }
#if defined(_VECTOR_) && (_MSC_VER<1910)
#if defined(_VECTOR_)
// workaround MSVC std::vector implementation
void resize(size_type new_size, const value_type& x)
{
@@ -110,7 +110,7 @@ namespace std {
vector_base::insert(vector_base::end(), new_size - vector_base::size(), x);
}
#else
// either GCC 4.1, MSVC2017 or non-GCC
// either GCC 4.1 or non-GCC
// default implementation which should always work.
void resize(size_type new_size, const value_type& x)
{

View File

@@ -151,8 +151,8 @@ static btScalar EdgeSeparation(const btBox2dShape* poly1, const btTransform& xf1
int index = 0;
btScalar minDot = BT_LARGE_FLOAT;
if( count2 > 0 )
index = (int) normal1.minDot( vertices2, count2, minDot);
if( count2 > 0 )
index = (int) normal1.minDot( vertices2, count2, minDot);
btVector3 v1 = b2Mul(xf1, vertices1[edge1]);
btVector3 v2 = b2Mul(xf2, vertices2[index]);
@@ -174,9 +174,9 @@ static btScalar FindMaxSeparation(int* edgeIndex,
// Find edge normal on poly1 that has the largest projection onto d.
int edge = 0;
btScalar maxDot;
if( count1 > 0 )
edge = (int) dLocal1.maxDot( normals1, count1, maxDot);
btScalar maxDot;
if( count1 > 0 )
edge = (int) dLocal1.maxDot( normals1, count1, maxDot);
// Get the separation for the edge normal.
btScalar s = EdgeSeparation(poly1, xf1, edge, poly2, xf2);

View File

@@ -232,8 +232,8 @@ void btCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrap
m_compoundShapeRevision = compoundShape->getUpdateRevision();
}
if (m_childCollisionAlgorithms.size()==0)
return;
if (m_childCollisionAlgorithms.size()==0)
return;
const btDbvt* tree = compoundShape->getDynamicAabbTree();
//use a dynamic aabb tree to cull potential child-overlaps

View File

@@ -73,12 +73,10 @@ set(SRC
internal/ceres/file.cc
internal/ceres/generated/partitioned_matrix_view_d_d_d.cc
internal/ceres/generated/schur_eliminator_d_d_d.cc
internal/ceres/gradient_checker.cc
internal/ceres/gradient_checking_cost_function.cc
internal/ceres/gradient_problem.cc
internal/ceres/gradient_problem_solver.cc
internal/ceres/implicit_schur_complement.cc
internal/ceres/is_close.cc
internal/ceres/iterative_schur_complement_solver.cc
internal/ceres/lapack.cc
internal/ceres/levenberg_marquardt_strategy.cc
@@ -118,7 +116,6 @@ set(SRC
internal/ceres/triplet_sparse_matrix.cc
internal/ceres/trust_region_minimizer.cc
internal/ceres/trust_region_preprocessor.cc
internal/ceres/trust_region_step_evaluator.cc
internal/ceres/trust_region_strategy.cc
internal/ceres/types.cc
internal/ceres/wall_time.cc
@@ -207,7 +204,6 @@ set(SRC
internal/ceres/householder_vector.h
internal/ceres/implicit_schur_complement.h
internal/ceres/integral_types.h
internal/ceres/is_close.h
internal/ceres/iterative_schur_complement_solver.h
internal/ceres/lapack.h
internal/ceres/levenberg_marquardt_strategy.h
@@ -252,7 +248,6 @@ set(SRC
internal/ceres/triplet_sparse_matrix.h
internal/ceres/trust_region_minimizer.h
internal/ceres/trust_region_preprocessor.h
internal/ceres/trust_region_step_evaluator.h
internal/ceres/trust_region_strategy.h
internal/ceres/visibility_based_preconditioner.h
internal/ceres/wall_time.h

1091
extern/ceres/ChangeLog vendored

File diff suppressed because it is too large Load Diff

View File

@@ -173,5 +173,26 @@ if(WITH_OPENMP)
)
endif()
TEST_UNORDERED_MAP_SUPPORT()
if(HAVE_STD_UNORDERED_MAP_HEADER)
if(HAVE_UNORDERED_MAP_IN_STD_NAMESPACE)
add_definitions(-DCERES_STD_UNORDERED_MAP)
else()
if(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
add_definitions(-DCERES_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
else()
add_definitions(-DCERES_NO_UNORDERED_MAP)
message(STATUS "Replacing unordered_map/set with map/set (warning: slower!)")
endif()
endif()
else()
if(HAVE_UNORDERED_MAP_IN_TR1_NAMESPACE)
add_definitions(-DCERES_TR1_UNORDERED_MAP)
else()
add_definitions(-DCERES_NO_UNORDERED_MAP)
message(STATUS "Replacing unordered_map/set with map/set (warning: slower!)")
endif()
endif()
blender_add_lib(extern_ceres "\${SRC}" "\${INC}" "\${INC_SYS}")
EOF

View File

@@ -149,7 +149,6 @@ internal/ceres/generated/schur_eliminator_4_4_d.cc
internal/ceres/generated/schur_eliminator_d_d_d.cc
internal/ceres/generate_eliminator_specialization.py
internal/ceres/generate_partitioned_matrix_view_specializations.py
internal/ceres/gradient_checker.cc
internal/ceres/gradient_checking_cost_function.cc
internal/ceres/gradient_checking_cost_function.h
internal/ceres/gradient_problem.cc
@@ -161,8 +160,6 @@ internal/ceres/householder_vector.h
internal/ceres/implicit_schur_complement.cc
internal/ceres/implicit_schur_complement.h
internal/ceres/integral_types.h
internal/ceres/is_close.cc
internal/ceres/is_close.h
internal/ceres/iterative_schur_complement_solver.cc
internal/ceres/iterative_schur_complement_solver.h
internal/ceres/lapack.cc
@@ -246,8 +243,6 @@ internal/ceres/trust_region_minimizer.cc
internal/ceres/trust_region_minimizer.h
internal/ceres/trust_region_preprocessor.cc
internal/ceres/trust_region_preprocessor.h
internal/ceres/trust_region_step_evaluator.cc
internal/ceres/trust_region_step_evaluator.h
internal/ceres/trust_region_strategy.cc
internal/ceres/trust_region_strategy.h
internal/ceres/types.cc

View File

@@ -130,8 +130,7 @@ class CostFunctionToFunctor {
const int num_parameter_blocks =
(N0 > 0) + (N1 > 0) + (N2 > 0) + (N3 > 0) + (N4 > 0) +
(N5 > 0) + (N6 > 0) + (N7 > 0) + (N8 > 0) + (N9 > 0);
CHECK_EQ(static_cast<int>(parameter_block_sizes.size()),
num_parameter_blocks);
CHECK_EQ(parameter_block_sizes.size(), num_parameter_blocks);
CHECK_EQ(N0, parameter_block_sizes[0]);
if (parameter_block_sizes.size() > 1) CHECK_EQ(N1, parameter_block_sizes[1]); // NOLINT

View File

@@ -357,28 +357,6 @@ class CERES_EXPORT Covariance {
const double*> >& covariance_blocks,
Problem* problem);
// Compute a part of the covariance matrix.
//
// The vector parameter_blocks contains the parameter blocks that
// are used for computing the covariance matrix. From this vector
// all covariance pairs are generated. This allows the covariance
// estimation algorithm to only compute and store these blocks.
//
// parameter_blocks cannot contain duplicates. Bad things will
// happen if they do.
//
// Note that the list of covariance_blocks is only used to determine
// what parts of the covariance matrix are computed. The full
// Jacobian is used to do the computation, i.e. they do not have an
// impact on what part of the Jacobian is used for computation.
//
// The return value indicates the success or failure of the
// covariance computation. Please see the documentation for
// Covariance::Options for more on the conditions under which this
// function returns false.
bool Compute(const std::vector<const double*>& parameter_blocks,
Problem* problem);
// Return the block of the cross-covariance matrix corresponding to
// parameter_block1 and parameter_block2.
//
@@ -416,40 +394,6 @@ class CERES_EXPORT Covariance {
const double* parameter_block2,
double* covariance_block) const;
// Return the covariance matrix corresponding to all parameter_blocks.
//
// Compute must be called before calling GetCovarianceMatrix and all
// parameter_blocks must have been present in the vector
// parameter_blocks when Compute was called. Otherwise
// GetCovarianceMatrix returns false.
//
// covariance_matrix must point to a memory location that can store
// the size of the covariance matrix. The covariance matrix will be
// a square matrix whose row and column count is equal to the sum of
// the sizes of the individual parameter blocks. The covariance
// matrix will be a row-major matrix.
bool GetCovarianceMatrix(const std::vector<const double *> &parameter_blocks,
double *covariance_matrix);
// Return the covariance matrix corresponding to parameter_blocks
// in the tangent space if a local parameterization is associated
// with one of the parameter blocks else returns the covariance
// matrix in the ambient space.
//
// Compute must be called before calling GetCovarianceMatrix and all
// parameter_blocks must have been present in the vector
// parameters_blocks when Compute was called. Otherwise
// GetCovarianceMatrix returns false.
//
// covariance_matrix must point to a memory location that can store
// the size of the covariance matrix. The covariance matrix will be
// a square matrix whose row and column count is equal to the sum of
// the sizes of the tangent spaces of the individual parameter
// blocks. The covariance matrix will be a row-major matrix.
bool GetCovarianceMatrixInTangentSpace(
const std::vector<const double*>& parameter_blocks,
double* covariance_matrix);
private:
internal::scoped_ptr<internal::CovarianceImpl> impl_;
};

View File

@@ -85,6 +85,22 @@ class DynamicNumericDiffCostFunction : public CostFunction {
options_(options) {
}
// Deprecated. New users should avoid using this constructor. Instead, use the
// constructor with NumericDiffOptions.
DynamicNumericDiffCostFunction(
const CostFunctor* functor,
Ownership ownership,
double relative_step_size)
: functor_(functor),
ownership_(ownership),
options_() {
LOG(WARNING) << "This constructor is deprecated and will be removed in "
"a future version. Please use the NumericDiffOptions "
"constructor instead.";
options_.relative_step_size = relative_step_size;
}
virtual ~DynamicNumericDiffCostFunction() {
if (ownership_ != TAKE_OWNERSHIP) {
functor_.release();
@@ -122,19 +138,19 @@ class DynamicNumericDiffCostFunction : public CostFunction {
std::vector<double> parameters_copy(parameters_size);
std::vector<double*> parameters_references_copy(block_sizes.size());
parameters_references_copy[0] = &parameters_copy[0];
for (size_t block = 1; block < block_sizes.size(); ++block) {
for (int block = 1; block < block_sizes.size(); ++block) {
parameters_references_copy[block] = parameters_references_copy[block - 1]
+ block_sizes[block - 1];
}
// Copy the parameters into the local temp space.
for (size_t block = 0; block < block_sizes.size(); ++block) {
for (int block = 0; block < block_sizes.size(); ++block) {
memcpy(parameters_references_copy[block],
parameters[block],
block_sizes[block] * sizeof(*parameters[block]));
}
for (size_t block = 0; block < block_sizes.size(); ++block) {
for (int block = 0; block < block_sizes.size(); ++block) {
if (jacobians[block] != NULL &&
!NumericDiff<CostFunctor, method, DYNAMIC,
DYNAMIC, DYNAMIC, DYNAMIC, DYNAMIC, DYNAMIC,

View File

@@ -27,121 +27,194 @@
// POSSIBILITY OF SUCH DAMAGE.
// Copyright 2007 Google Inc. All Rights Reserved.
//
// Authors: wjr@google.com (William Rucklidge),
// keir@google.com (Keir Mierle),
// dgossow@google.com (David Gossow)
// Author: wjr@google.com (William Rucklidge)
//
// This file contains a class that exercises a cost function, to make sure
// that it is computing reasonable derivatives. It compares the Jacobians
// computed by the cost function with those obtained by finite
// differences.
#ifndef CERES_PUBLIC_GRADIENT_CHECKER_H_
#define CERES_PUBLIC_GRADIENT_CHECKER_H_
#include <cstddef>
#include <algorithm>
#include <vector>
#include <string>
#include "ceres/cost_function.h"
#include "ceres/dynamic_numeric_diff_cost_function.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/fixed_array.h"
#include "ceres/internal/macros.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/local_parameterization.h"
#include "ceres/numeric_diff_cost_function.h"
#include "glog/logging.h"
namespace ceres {
// GradientChecker compares the Jacobians returned by a cost function against
// derivatives estimated using finite differencing.
// An object that exercises a cost function, to compare the answers that it
// gives with derivatives estimated using finite differencing.
//
// The condition enforced is that
//
// (J_actual(i, j) - J_numeric(i, j))
// ------------------------------------ < relative_precision
// max(J_actual(i, j), J_numeric(i, j))
//
// where J_actual(i, j) is the jacobian as computed by the supplied cost
// function (by the user) multiplied by the local parameterization Jacobian
// and J_numeric is the jacobian as computed by finite differences, multiplied
// by the local parameterization Jacobian as well.
// The only likely usage of this is for testing.
//
// How to use: Fill in an array of pointers to parameter blocks for your
// CostFunction, and then call Probe(). Check that the return value is 'true'.
// CostFunction, and then call Probe(). Check that the return value is
// 'true'. See prober_test.cc for an example.
//
// This is templated similarly to NumericDiffCostFunction, as it internally
// uses that.
template <typename CostFunctionToProbe,
int M = 0, int N0 = 0, int N1 = 0, int N2 = 0, int N3 = 0, int N4 = 0>
class GradientChecker {
public:
// This will not take ownership of the cost function or local
// parameterizations.
//
// function: The cost function to probe.
// local_parameterization: A vector of local parameterizations for each
// parameter. May be NULL or contain NULL pointers to indicate that the
// respective parameter does not have a local parameterization.
// options: Options to use for numerical differentiation.
GradientChecker(
const CostFunction* function,
const std::vector<const LocalParameterization*>* local_parameterizations,
const NumericDiffOptions& options);
// Here we stash some results from the probe, for later
// inspection.
struct GradientCheckResults {
// Computed cost.
Vector cost;
// Contains results from a call to Probe for later inspection.
struct ProbeResults {
// The return value of the cost function.
bool return_value;
// Computed residual vector.
Vector residuals;
// The sizes of the Jacobians below are dictated by the cost function's
// parameter block size and residual block sizes. If a parameter block
// has a local parameterization associated with it, the size of the "local"
// Jacobian will be determined by the local parameterization dimension and
// residual block size, otherwise it will be identical to the regular
// Jacobian.
// The sizes of these matrices are dictated by the cost function's
// parameter and residual block sizes. Each vector's length will
// term->parameter_block_sizes().size(), and each matrix is the
// Jacobian of the residual with respect to the corresponding parameter
// block.
// Derivatives as computed by the cost function.
std::vector<Matrix> jacobians;
std::vector<Matrix> term_jacobians;
// Derivatives as computed by the cost function in local space.
std::vector<Matrix> local_jacobians;
// Derivatives as computed by finite differencing.
std::vector<Matrix> finite_difference_jacobians;
// Derivatives as computed by nuerical differentiation in local space.
std::vector<Matrix> numeric_jacobians;
// Derivatives as computed by nuerical differentiation in local space.
std::vector<Matrix> local_numeric_jacobians;
// Contains the maximum relative error found in the local Jacobians.
double maximum_relative_error;
// If an error was detected, this will contain a detailed description of
// that error.
std::string error_log;
// Infinity-norm of term_jacobians - finite_difference_jacobians.
double error_jacobians;
};
// Call the cost function, compute alternative Jacobians using finite
// differencing and compare results. If local parameterizations are given,
// the Jacobians will be multiplied by the local parameterization Jacobians
// before performing the check, which effectively means that all errors along
// the null space of the local parameterization will be ignored.
// Returns false if the Jacobians don't match, the cost function return false,
// or if the cost function returns different residual when called with a
// Jacobian output argument vs. calling it without. Otherwise returns true.
// Checks the Jacobian computed by a cost function.
//
// parameters: The parameter values at which to probe.
// relative_precision: A threshold for the relative difference between the
// Jacobians. If the Jacobians differ by more than this amount, then the
// probe fails.
// results: On return, the Jacobians (and other information) will be stored
// here. May be NULL.
// probe_point: The parameter values at which to probe.
// error_tolerance: A threshold for the infinity-norm difference
// between the Jacobians. If the Jacobians differ by more than
// this amount, then the probe fails.
//
// term: The cost function to test. Not retained after this call returns.
//
// results: On return, the two Jacobians (and other information)
// will be stored here. May be NULL.
//
// Returns true if no problems are detected and the difference between the
// Jacobians is less than error_tolerance.
bool Probe(double const* const* parameters,
double relative_precision,
ProbeResults* results) const;
static bool Probe(double const* const* probe_point,
double error_tolerance,
CostFunctionToProbe *term,
GradientCheckResults* results) {
CHECK_NOTNULL(probe_point);
CHECK_NOTNULL(term);
LOG(INFO) << "-------------------- Starting Probe() --------------------";
// We need a GradientCheckeresults, whether or not they supplied one.
internal::scoped_ptr<GradientCheckResults> owned_results;
if (results == NULL) {
owned_results.reset(new GradientCheckResults);
results = owned_results.get();
}
// Do a consistency check between the term and the template parameters.
CHECK_EQ(M, term->num_residuals());
const int num_residuals = M;
const std::vector<int32>& block_sizes = term->parameter_block_sizes();
const int num_blocks = block_sizes.size();
CHECK_LE(num_blocks, 5) << "Unable to test functions that take more "
<< "than 5 parameter blocks";
if (N0) {
CHECK_EQ(N0, block_sizes[0]);
CHECK_GE(num_blocks, 1);
} else {
CHECK_LT(num_blocks, 1);
}
if (N1) {
CHECK_EQ(N1, block_sizes[1]);
CHECK_GE(num_blocks, 2);
} else {
CHECK_LT(num_blocks, 2);
}
if (N2) {
CHECK_EQ(N2, block_sizes[2]);
CHECK_GE(num_blocks, 3);
} else {
CHECK_LT(num_blocks, 3);
}
if (N3) {
CHECK_EQ(N3, block_sizes[3]);
CHECK_GE(num_blocks, 4);
} else {
CHECK_LT(num_blocks, 4);
}
if (N4) {
CHECK_EQ(N4, block_sizes[4]);
CHECK_GE(num_blocks, 5);
} else {
CHECK_LT(num_blocks, 5);
}
results->term_jacobians.clear();
results->term_jacobians.resize(num_blocks);
results->finite_difference_jacobians.clear();
results->finite_difference_jacobians.resize(num_blocks);
internal::FixedArray<double*> term_jacobian_pointers(num_blocks);
internal::FixedArray<double*>
finite_difference_jacobian_pointers(num_blocks);
for (int i = 0; i < num_blocks; i++) {
results->term_jacobians[i].resize(num_residuals, block_sizes[i]);
term_jacobian_pointers[i] = results->term_jacobians[i].data();
results->finite_difference_jacobians[i].resize(
num_residuals, block_sizes[i]);
finite_difference_jacobian_pointers[i] =
results->finite_difference_jacobians[i].data();
}
results->cost.resize(num_residuals, 1);
CHECK(term->Evaluate(probe_point, results->cost.data(),
term_jacobian_pointers.get()));
NumericDiffCostFunction<CostFunctionToProbe, CENTRAL, M, N0, N1, N2, N3, N4>
numeric_term(term, DO_NOT_TAKE_OWNERSHIP);
CHECK(numeric_term.Evaluate(probe_point, results->cost.data(),
finite_difference_jacobian_pointers.get()));
results->error_jacobians = 0;
for (int i = 0; i < num_blocks; i++) {
Matrix jacobian_difference = results->term_jacobians[i] -
results->finite_difference_jacobians[i];
results->error_jacobians =
std::max(results->error_jacobians,
jacobian_difference.lpNorm<Eigen::Infinity>());
}
LOG(INFO) << "========== term-computed derivatives ==========";
for (int i = 0; i < num_blocks; i++) {
LOG(INFO) << "term_computed block " << i;
LOG(INFO) << "\n" << results->term_jacobians[i];
}
LOG(INFO) << "========== finite-difference derivatives ==========";
for (int i = 0; i < num_blocks; i++) {
LOG(INFO) << "finite_difference block " << i;
LOG(INFO) << "\n" << results->finite_difference_jacobians[i];
}
LOG(INFO) << "========== difference ==========";
for (int i = 0; i < num_blocks; i++) {
LOG(INFO) << "difference block " << i;
LOG(INFO) << (results->term_jacobians[i] -
results->finite_difference_jacobians[i]);
}
LOG(INFO) << "||difference|| = " << results->error_jacobians;
return results->error_jacobians < error_tolerance;
}
private:
CERES_DISALLOW_IMPLICIT_CONSTRUCTORS(GradientChecker);
std::vector<const LocalParameterization*> local_parameterizations_;
const CostFunction* function_;
internal::scoped_ptr<CostFunction> finite_diff_cost_function_;
};
} // namespace ceres

View File

@@ -33,8 +33,9 @@
// This file needs to compile as c code.
#ifdef __cplusplus
#include <cstddef>
#include "ceres/internal/config.h"
#if defined(CERES_TR1_MEMORY_HEADER)
#include <tr1/memory>
#else
@@ -49,25 +50,6 @@ using std::tr1::shared_ptr;
using std::shared_ptr;
#endif
// We allocate some Eigen objects on the stack and other places they
// might not be aligned to 16-byte boundaries. If we have C++11, we
// can specify their alignment anyway, and thus can safely enable
// vectorization on those matrices; in C++99, we are out of luck. Figure out
// what case we're in and write macros that do the right thing.
#ifdef CERES_USE_CXX11
namespace port_constants {
static constexpr size_t kMaxAlignBytes =
// Work around a GCC 4.8 bug
// (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56019) where
// std::max_align_t is misplaced.
#if defined (__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 8
alignof(::max_align_t);
#else
alignof(std::max_align_t);
#endif
} // namespace port_constants
#endif
} // namespace ceres
#endif // __cplusplus

View File

@@ -69,7 +69,7 @@ struct CERES_EXPORT IterationSummary {
// Step was numerically valid, i.e., all values are finite and the
// step reduces the value of the linearized model.
//
// Note: step_is_valid is always true when iteration = 0.
// Note: step_is_valid is false when iteration = 0.
bool step_is_valid;
// Step did not reduce the value of the objective function
@@ -77,7 +77,7 @@ struct CERES_EXPORT IterationSummary {
// acceptance criterion used by the non-monotonic trust region
// algorithm.
//
// Note: step_is_nonmonotonic is always false when iteration = 0;
// Note: step_is_nonmonotonic is false when iteration = 0;
bool step_is_nonmonotonic;
// Whether or not the minimizer accepted this step or not. If the
@@ -89,7 +89,7 @@ struct CERES_EXPORT IterationSummary {
// relative decrease is not sufficient, the algorithm may accept the
// step and the step is declared successful.
//
// Note: step_is_successful is always true when iteration = 0.
// Note: step_is_successful is false when iteration = 0.
bool step_is_successful;
// Value of the objective function.

View File

@@ -164,7 +164,6 @@
#include "Eigen/Core"
#include "ceres/fpclassify.h"
#include "ceres/internal/port.h"
namespace ceres {
@@ -228,23 +227,21 @@ struct Jet {
T a;
// The infinitesimal part.
// We allocate Jets on the stack and other places they
// might not be aligned to 16-byte boundaries. If we have C++11, we
// can specify their alignment anyway, and thus can safely enable
// vectorization on those matrices; in C++99, we are out of luck. Figure out
// what case we're in and do the right thing.
#ifndef CERES_USE_CXX11
// fall back to safe version:
//
// Note the Eigen::DontAlign bit is needed here because this object
// gets allocated on the stack and as part of other arrays and
// structs. Forcing the right alignment there is the source of much
// pain and suffering. Even if that works, passing Jets around to
// functions by value has problems because the C++ ABI does not
// guarantee alignment for function arguments.
//
// Setting the DontAlign bit prevents Eigen from using SSE for the
// various operations on Jets. This is a small performance penalty
// since the AutoDiff code will still expose much of the code as
// statically sized loops to the compiler. But given the subtle
// issues that arise due to alignment, especially when dealing with
// multiple platforms, it seems to be a trade off worth making.
Eigen::Matrix<T, N, 1, Eigen::DontAlign> v;
#else
static constexpr bool kShouldAlignMatrix =
16 <= ::ceres::port_constants::kMaxAlignBytes;
static constexpr int kAlignHint = kShouldAlignMatrix ?
Eigen::AutoAlign : Eigen::DontAlign;
static constexpr size_t kAlignment = kShouldAlignMatrix ? 16 : 1;
alignas(kAlignment) Eigen::Matrix<T, N, 1, kAlignHint> v;
#endif
};
// Unary +
@@ -391,8 +388,6 @@ inline double atan (double x) { return std::atan(x); }
inline double sinh (double x) { return std::sinh(x); }
inline double cosh (double x) { return std::cosh(x); }
inline double tanh (double x) { return std::tanh(x); }
inline double floor (double x) { return std::floor(x); }
inline double ceil (double x) { return std::ceil(x); }
inline double pow (double x, double y) { return std::pow(x, y); }
inline double atan2(double y, double x) { return std::atan2(y, x); }
@@ -487,51 +482,10 @@ Jet<T, N> tanh(const Jet<T, N>& f) {
return Jet<T, N>(tanh_a, tmp * f.v);
}
// The floor function should be used with extreme care as this operation will
// result in a zero derivative which provides no information to the solver.
//
// floor(a + h) ~= floor(a) + 0
template <typename T, int N> inline
Jet<T, N> floor(const Jet<T, N>& f) {
return Jet<T, N>(floor(f.a));
}
// The ceil function should be used with extreme care as this operation will
// result in a zero derivative which provides no information to the solver.
//
// ceil(a + h) ~= ceil(a) + 0
template <typename T, int N> inline
Jet<T, N> ceil(const Jet<T, N>& f) {
return Jet<T, N>(ceil(f.a));
}
// Bessel functions of the first kind with integer order equal to 0, 1, n.
//
// Microsoft has deprecated the j[0,1,n]() POSIX Bessel functions in favour of
// _j[0,1,n](). Where available on MSVC, use _j[0,1,n]() to avoid deprecated
// function errors in client code (the specific warning is suppressed when
// Ceres itself is built).
inline double BesselJ0(double x) {
#if defined(_MSC_VER) && defined(_j0)
return _j0(x);
#else
return j0(x);
#endif
}
inline double BesselJ1(double x) {
#if defined(_MSC_VER) && defined(_j1)
return _j1(x);
#else
return j1(x);
#endif
}
inline double BesselJn(int n, double x) {
#if defined(_MSC_VER) && defined(_jn)
return _jn(n, x);
#else
return jn(n, x);
#endif
}
inline double BesselJ0(double x) { return j0(x); }
inline double BesselJ1(double x) { return j1(x); }
inline double BesselJn(int n, double x) { return jn(n, x); }
// For the formulae of the derivatives of the Bessel functions see the book:
// Olver, Lozier, Boisvert, Clark, NIST Handbook of Mathematical Functions,
@@ -789,15 +743,7 @@ template<typename T, int N> inline Jet<T, N> ei_pow (const Jet<T, N>& x,
// strange compile errors.
template <typename T, int N>
inline std::ostream &operator<<(std::ostream &s, const Jet<T, N>& z) {
s << "[" << z.a << " ; ";
for (int i = 0; i < N; ++i) {
s << z.v[i];
if (i != N - 1) {
s << ", ";
}
}
s << "]";
return s;
return s << "[" << z.a << " ; " << z.v.transpose() << "]";
}
} // namespace ceres
@@ -811,7 +757,6 @@ struct NumTraits<ceres::Jet<T, N> > {
typedef ceres::Jet<T, N> Real;
typedef ceres::Jet<T, N> NonInteger;
typedef ceres::Jet<T, N> Nested;
typedef ceres::Jet<T, N> Literal;
static typename ceres::Jet<T, N> dummy_precision() {
return ceres::Jet<T, N>(1e-12);
@@ -832,21 +777,6 @@ struct NumTraits<ceres::Jet<T, N> > {
HasFloatingPoint = 1,
RequireInitialization = 1
};
template<bool Vectorized>
struct Div {
enum {
#if defined(EIGEN_VECTORIZE_AVX)
AVX = true,
#else
AVX = false,
#endif
// Assuming that for Jets, division is as expensive as
// multiplication.
Cost = 3
};
};
};
} // namespace Eigen

View File

@@ -211,28 +211,6 @@ class CERES_EXPORT QuaternionParameterization : public LocalParameterization {
virtual int LocalSize() const { return 3; }
};
// Implements the quaternion local parameterization for Eigen's representation
// of the quaternion. Eigen uses a different internal memory layout for the
// elements of the quaternion than what is commonly used. Specifically, Eigen
// stores the elements in memory as [x, y, z, w] where the real part is last
// whereas it is typically stored first. Note, when creating an Eigen quaternion
// through the constructor the elements are accepted in w, x, y, z order. Since
// Ceres operates on parameter blocks which are raw double pointers this
// difference is important and requires a different parameterization.
//
// Plus(x, delta) = [sin(|delta|) delta / |delta|, cos(|delta|)] * x
// with * being the quaternion multiplication operator.
class EigenQuaternionParameterization : public ceres::LocalParameterization {
public:
virtual ~EigenQuaternionParameterization() {}
virtual bool Plus(const double* x,
const double* delta,
double* x_plus_delta) const;
virtual bool ComputeJacobian(const double* x,
double* jacobian) const;
virtual int GlobalSize() const { return 4; }
virtual int LocalSize() const { return 3; }
};
// This provides a parameterization for homogeneous vectors which are commonly
// used in Structure for Motion problems. One example where they are used is

View File

@@ -206,6 +206,29 @@ class NumericDiffCostFunction
}
}
// Deprecated. New users should avoid using this constructor. Instead, use the
// constructor with NumericDiffOptions.
NumericDiffCostFunction(CostFunctor* functor,
Ownership ownership,
int num_residuals,
const double relative_step_size)
:functor_(functor),
ownership_(ownership),
options_() {
LOG(WARNING) << "This constructor is deprecated and will be removed in "
"a future version. Please use the NumericDiffOptions "
"constructor instead.";
if (kNumResiduals == DYNAMIC) {
SizedCostFunction<kNumResiduals,
N0, N1, N2, N3, N4,
N5, N6, N7, N8, N9>
::set_num_residuals(num_residuals);
}
options_.relative_step_size = relative_step_size;
}
~NumericDiffCostFunction() {
if (ownership_ != TAKE_OWNERSHIP) {
functor_.release();

View File

@@ -309,9 +309,6 @@ class CERES_EXPORT Problem {
// Allow the indicated parameter block to vary during optimization.
void SetParameterBlockVariable(double* values);
// Returns true if a parameter block is set constant, and false otherwise.
bool IsParameterBlockConstant(double* values) const;
// Set the local parameterization for one of the parameter blocks.
// The local_parameterization is owned by the Problem by default. It
// is acceptable to set the same parameterization for multiple
@@ -464,10 +461,6 @@ class CERES_EXPORT Problem {
// parameter block has a local parameterization, then it contributes
// "LocalSize" entries to the gradient vector (and the number of
// columns in the jacobian).
//
// Note 3: This function cannot be called while the problem is being
// solved, for example it cannot be called from an IterationCallback
// at the end of an iteration during a solve.
bool Evaluate(const EvaluateOptions& options,
double* cost,
std::vector<double>* residuals,

View File

@@ -48,6 +48,7 @@
#include <algorithm>
#include <cmath>
#include <limits>
#include "glog/logging.h"
namespace ceres {
@@ -417,6 +418,7 @@ template <typename T>
inline void EulerAnglesToRotationMatrix(const T* euler,
const int row_stride_parameter,
T* R) {
CHECK_EQ(row_stride_parameter, 3);
EulerAnglesToRotationMatrix(euler, RowMajorAdapter3x3(R));
}
@@ -494,6 +496,7 @@ void QuaternionToRotation(const T q[4],
QuaternionToScaledRotation(q, R);
T normalizer = q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3];
CHECK_NE(normalizer, T(0));
normalizer = T(1) / normalizer;
for (int i = 0; i < 3; ++i) {

View File

@@ -134,7 +134,7 @@ class CERES_EXPORT Solver {
trust_region_problem_dump_format_type = TEXTFILE;
check_gradients = false;
gradient_check_relative_precision = 1e-8;
gradient_check_numeric_derivative_relative_step_size = 1e-6;
numeric_derivative_relative_step_size = 1e-6;
update_state_every_iteration = false;
}
@@ -701,22 +701,12 @@ class CERES_EXPORT Solver {
// this number, then the jacobian for that cost term is dumped.
double gradient_check_relative_precision;
// WARNING: This option only applies to the to the numeric
// differentiation used for checking the user provided derivatives
// when when Solver::Options::check_gradients is true. If you are
// using NumericDiffCostFunction and are interested in changing
// the step size for numeric differentiation in your cost
// function, please have a look at
// include/ceres/numeric_diff_options.h.
// Relative shift used for taking numeric derivatives. For finite
// differencing, each dimension is evaluated at slightly shifted
// values; for the case of central difference, this is what gets
// evaluated:
//
// Relative shift used for taking numeric derivatives when
// Solver::Options::check_gradients is true.
//
// For finite differencing, each dimension is evaluated at
// slightly shifted values; for the case of central difference,
// this is what gets evaluated:
//
// delta = gradient_check_numeric_derivative_relative_step_size;
// delta = numeric_derivative_relative_step_size;
// f_initial = f(x)
// f_forward = f((1 + delta) * x)
// f_backward = f((1 - delta) * x)
@@ -733,7 +723,7 @@ class CERES_EXPORT Solver {
// theory a good choice is sqrt(eps) * x, which for doubles means
// about 1e-8 * x. However, I have found this number too
// optimistic. This number should be exposed for users to change.
double gradient_check_numeric_derivative_relative_step_size;
double numeric_derivative_relative_step_size;
// If true, the user's parameter blocks are updated at the end of
// every Minimizer iteration, otherwise they are updated when the
@@ -811,13 +801,6 @@ class CERES_EXPORT Solver {
// Number of times inner iterations were performed.
int num_inner_iteration_steps;
// Total number of iterations inside the line search algorithm
// across all invocations. We call these iterations "steps" to
// distinguish them from the outer iterations of the line search
// and trust region minimizer algorithms which call the line
// search algorithm as a subroutine.
int num_line_search_steps;
// All times reported below are wall times.
// When the user calls Solve, before the actual optimization

View File

@@ -32,7 +32,7 @@
#define CERES_PUBLIC_VERSION_H_
#define CERES_VERSION_MAJOR 1
#define CERES_VERSION_MINOR 12
#define CERES_VERSION_MINOR 11
#define CERES_VERSION_REVISION 0
// Classic CPP stringifcation; the extra level of indirection allows the

View File

@@ -46,7 +46,6 @@ namespace internal {
using std::make_pair;
using std::pair;
using std::vector;
using std::adjacent_find;
void CompressedRowJacobianWriter::PopulateJacobianRowAndColumnBlockVectors(
const Program* program, CompressedRowSparseMatrix* jacobian) {
@@ -141,21 +140,12 @@ SparseMatrix* CompressedRowJacobianWriter::CreateJacobian() const {
// Sort the parameters by their position in the state vector.
sort(parameter_indices.begin(), parameter_indices.end());
if (adjacent_find(parameter_indices.begin(), parameter_indices.end()) !=
parameter_indices.end()) {
std::string parameter_block_description;
for (int j = 0; j < num_parameter_blocks; ++j) {
ParameterBlock* parameter_block = residual_block->parameter_blocks()[j];
parameter_block_description +=
parameter_block->ToString() + "\n";
}
LOG(FATAL) << "Ceres internal error: "
<< "Duplicate parameter blocks detected in a cost function. "
<< "This should never happen. Please report this to "
<< "the Ceres developers.\n"
<< "Residual Block: " << residual_block->ToString() << "\n"
<< "Parameter Blocks: " << parameter_block_description;
}
CHECK(unique(parameter_indices.begin(), parameter_indices.end()) ==
parameter_indices.end())
<< "Ceres internal error: "
<< "Duplicate parameter blocks detected in a cost function. "
<< "This should never happen. Please report this to "
<< "the Ceres developers.";
// Update the row indices.
const int num_residuals = residual_block->NumResiduals();

View File

@@ -38,7 +38,6 @@
namespace ceres {
using std::make_pair;
using std::pair;
using std::vector;
@@ -55,12 +54,6 @@ bool Covariance::Compute(
return impl_->Compute(covariance_blocks, problem->problem_impl_.get());
}
bool Covariance::Compute(
const vector<const double*>& parameter_blocks,
Problem* problem) {
return impl_->Compute(parameter_blocks, problem->problem_impl_.get());
}
bool Covariance::GetCovarianceBlock(const double* parameter_block1,
const double* parameter_block2,
double* covariance_block) const {
@@ -80,20 +73,4 @@ bool Covariance::GetCovarianceBlockInTangentSpace(
covariance_block);
}
bool Covariance::GetCovarianceMatrix(
const vector<const double*>& parameter_blocks,
double* covariance_matrix) {
return impl_->GetCovarianceMatrixInTangentOrAmbientSpace(parameter_blocks,
true, // ambient
covariance_matrix);
}
bool Covariance::GetCovarianceMatrixInTangentSpace(
const std::vector<const double *>& parameter_blocks,
double *covariance_matrix) {
return impl_->GetCovarianceMatrixInTangentOrAmbientSpace(parameter_blocks,
false, // tangent
covariance_matrix);
}
} // namespace ceres

View File

@@ -36,8 +36,6 @@
#include <algorithm>
#include <cstdlib>
#include <numeric>
#include <sstream>
#include <utility>
#include <vector>
@@ -45,7 +43,6 @@
#include "Eigen/SparseQR"
#include "Eigen/SVD"
#include "ceres/collections_port.h"
#include "ceres/compressed_col_sparse_matrix_utils.h"
#include "ceres/compressed_row_sparse_matrix.h"
#include "ceres/covariance.h"
@@ -54,7 +51,6 @@
#include "ceres/map_util.h"
#include "ceres/parameter_block.h"
#include "ceres/problem_impl.h"
#include "ceres/residual_block.h"
#include "ceres/suitesparse.h"
#include "ceres/wall_time.h"
#include "glog/logging.h"
@@ -65,7 +61,6 @@ namespace internal {
using std::make_pair;
using std::map;
using std::pair;
using std::sort;
using std::swap;
using std::vector;
@@ -91,38 +86,8 @@ CovarianceImpl::CovarianceImpl(const Covariance::Options& options)
CovarianceImpl::~CovarianceImpl() {
}
template <typename T> void CheckForDuplicates(vector<T> blocks) {
sort(blocks.begin(), blocks.end());
typename vector<T>::iterator it =
std::adjacent_find(blocks.begin(), blocks.end());
if (it != blocks.end()) {
// In case there are duplicates, we search for their location.
map<T, vector<int> > blocks_map;
for (int i = 0; i < blocks.size(); ++i) {
blocks_map[blocks[i]].push_back(i);
}
std::ostringstream duplicates;
while (it != blocks.end()) {
duplicates << "(";
for (int i = 0; i < blocks_map[*it].size() - 1; ++i) {
duplicates << blocks_map[*it][i] << ", ";
}
duplicates << blocks_map[*it].back() << ")";
it = std::adjacent_find(it + 1, blocks.end());
if (it < blocks.end()) {
duplicates << " and ";
}
}
LOG(FATAL) << "Covariance::Compute called with duplicate blocks at "
<< "indices " << duplicates.str();
}
}
bool CovarianceImpl::Compute(const CovarianceBlocks& covariance_blocks,
ProblemImpl* problem) {
CheckForDuplicates<pair<const double*, const double*> >(covariance_blocks);
problem_ = problem;
parameter_block_to_row_index_.clear();
covariance_matrix_.reset(NULL);
@@ -132,20 +97,6 @@ bool CovarianceImpl::Compute(const CovarianceBlocks& covariance_blocks,
return is_valid_;
}
bool CovarianceImpl::Compute(const vector<const double*>& parameter_blocks,
ProblemImpl* problem) {
CheckForDuplicates<const double*>(parameter_blocks);
CovarianceBlocks covariance_blocks;
for (int i = 0; i < parameter_blocks.size(); ++i) {
for (int j = i; j < parameter_blocks.size(); ++j) {
covariance_blocks.push_back(make_pair(parameter_blocks[i],
parameter_blocks[j]));
}
}
return Compute(covariance_blocks, problem);
}
bool CovarianceImpl::GetCovarianceBlockInTangentOrAmbientSpace(
const double* original_parameter_block1,
const double* original_parameter_block2,
@@ -169,17 +120,9 @@ bool CovarianceImpl::GetCovarianceBlockInTangentOrAmbientSpace(
ParameterBlock* block2 =
FindOrDie(parameter_map,
const_cast<double*>(original_parameter_block2));
const int block1_size = block1->Size();
const int block2_size = block2->Size();
const int block1_local_size = block1->LocalSize();
const int block2_local_size = block2->LocalSize();
if (!lift_covariance_to_ambient_space) {
MatrixRef(covariance_block, block1_local_size, block2_local_size)
.setZero();
} else {
MatrixRef(covariance_block, block1_size, block2_size).setZero();
}
MatrixRef(covariance_block, block1_size, block2_size).setZero();
return true;
}
@@ -297,94 +240,6 @@ bool CovarianceImpl::GetCovarianceBlockInTangentOrAmbientSpace(
return true;
}
bool CovarianceImpl::GetCovarianceMatrixInTangentOrAmbientSpace(
const vector<const double*>& parameters,
bool lift_covariance_to_ambient_space,
double* covariance_matrix) const {
CHECK(is_computed_)
<< "Covariance::GetCovarianceMatrix called before Covariance::Compute";
CHECK(is_valid_)
<< "Covariance::GetCovarianceMatrix called when Covariance::Compute "
<< "returned false.";
const ProblemImpl::ParameterMap& parameter_map = problem_->parameter_map();
// For OpenMP compatibility we need to define these vectors in advance
const int num_parameters = parameters.size();
vector<int> parameter_sizes;
vector<int> cum_parameter_size;
parameter_sizes.reserve(num_parameters);
cum_parameter_size.resize(num_parameters + 1);
cum_parameter_size[0] = 0;
for (int i = 0; i < num_parameters; ++i) {
ParameterBlock* block =
FindOrDie(parameter_map, const_cast<double*>(parameters[i]));
if (lift_covariance_to_ambient_space) {
parameter_sizes.push_back(block->Size());
} else {
parameter_sizes.push_back(block->LocalSize());
}
}
std::partial_sum(parameter_sizes.begin(), parameter_sizes.end(),
cum_parameter_size.begin() + 1);
const int max_covariance_block_size =
*std::max_element(parameter_sizes.begin(), parameter_sizes.end());
const int covariance_size = cum_parameter_size.back();
// Assemble the blocks in the covariance matrix.
MatrixRef covariance(covariance_matrix, covariance_size, covariance_size);
const int num_threads = options_.num_threads;
scoped_array<double> workspace(
new double[num_threads * max_covariance_block_size *
max_covariance_block_size]);
bool success = true;
// The collapse() directive is only supported in OpenMP 3.0 and higher. OpenMP
// 3.0 was released in May 2008 (hence the version number).
#if _OPENMP >= 200805
# pragma omp parallel for num_threads(num_threads) schedule(dynamic) collapse(2)
#else
# pragma omp parallel for num_threads(num_threads) schedule(dynamic)
#endif
for (int i = 0; i < num_parameters; ++i) {
for (int j = 0; j < num_parameters; ++j) {
// The second loop can't start from j = i for compatibility with OpenMP
// collapse command. The conditional serves as a workaround
if (j >= i) {
int covariance_row_idx = cum_parameter_size[i];
int covariance_col_idx = cum_parameter_size[j];
int size_i = parameter_sizes[i];
int size_j = parameter_sizes[j];
#ifdef CERES_USE_OPENMP
int thread_id = omp_get_thread_num();
#else
int thread_id = 0;
#endif
double* covariance_block =
workspace.get() +
thread_id * max_covariance_block_size * max_covariance_block_size;
if (!GetCovarianceBlockInTangentOrAmbientSpace(
parameters[i], parameters[j], lift_covariance_to_ambient_space,
covariance_block)) {
success = false;
}
covariance.block(covariance_row_idx, covariance_col_idx,
size_i, size_j) =
MatrixRef(covariance_block, size_i, size_j);
if (i != j) {
covariance.block(covariance_col_idx, covariance_row_idx,
size_j, size_i) =
MatrixRef(covariance_block, size_i, size_j).transpose();
}
}
}
}
return success;
}
// Determine the sparsity pattern of the covariance matrix based on
// the block pairs requested by the user.
bool CovarianceImpl::ComputeCovarianceSparsity(
@@ -397,28 +252,18 @@ bool CovarianceImpl::ComputeCovarianceSparsity(
vector<double*> all_parameter_blocks;
problem->GetParameterBlocks(&all_parameter_blocks);
const ProblemImpl::ParameterMap& parameter_map = problem->parameter_map();
HashSet<ParameterBlock*> parameter_blocks_in_use;
vector<ResidualBlock*> residual_blocks;
problem->GetResidualBlocks(&residual_blocks);
for (int i = 0; i < residual_blocks.size(); ++i) {
ResidualBlock* residual_block = residual_blocks[i];
parameter_blocks_in_use.insert(residual_block->parameter_blocks(),
residual_block->parameter_blocks() +
residual_block->NumParameterBlocks());
}
constant_parameter_blocks_.clear();
vector<double*>& active_parameter_blocks =
evaluate_options_.parameter_blocks;
active_parameter_blocks.clear();
for (int i = 0; i < all_parameter_blocks.size(); ++i) {
double* parameter_block = all_parameter_blocks[i];
ParameterBlock* block = FindOrDie(parameter_map, parameter_block);
if (!block->IsConstant() && (parameter_blocks_in_use.count(block) > 0)) {
active_parameter_blocks.push_back(parameter_block);
} else {
if (block->IsConstant()) {
constant_parameter_blocks_.insert(parameter_block);
} else {
active_parameter_blocks.push_back(parameter_block);
}
}
@@ -541,8 +386,8 @@ bool CovarianceImpl::ComputeCovarianceValues() {
switch (options_.algorithm_type) {
case DENSE_SVD:
return ComputeCovarianceValuesUsingDenseSVD();
case SUITE_SPARSE_QR:
#ifndef CERES_NO_SUITESPARSE
case SUITE_SPARSE_QR:
return ComputeCovarianceValuesUsingSuiteSparseQR();
#else
LOG(ERROR) << "SuiteSparse is required to use the "
@@ -779,10 +624,7 @@ bool CovarianceImpl::ComputeCovarianceValuesUsingDenseSVD() {
if (automatic_truncation) {
break;
} else {
LOG(ERROR) << "Error: Covariance matrix is near rank deficient "
<< "and the user did not specify a non-zero"
<< "Covariance::Options::null_space_rank "
<< "to enable the computation of a Pseudo-Inverse. "
LOG(ERROR) << "Cholesky factorization of J'J is not reliable. "
<< "Reciprocal condition number: "
<< singular_value_ratio * singular_value_ratio << " "
<< "min_reciprocal_condition_number: "

View File

@@ -55,21 +55,12 @@ class CovarianceImpl {
const double*> >& covariance_blocks,
ProblemImpl* problem);
bool Compute(
const std::vector<const double*>& parameter_blocks,
ProblemImpl* problem);
bool GetCovarianceBlockInTangentOrAmbientSpace(
const double* parameter_block1,
const double* parameter_block2,
bool lift_covariance_to_ambient_space,
double* covariance_block) const;
bool GetCovarianceMatrixInTangentOrAmbientSpace(
const std::vector<const double*>& parameters,
bool lift_covariance_to_ambient_space,
double *covariance_matrix) const;
bool ComputeCovarianceSparsity(
const std::vector<std::pair<const double*,
const double*> >& covariance_blocks,

View File

@@ -1,276 +0,0 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2016 Google Inc. All rights reserved.
// http://ceres-solver.org/
//
// 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 Google Inc. 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.
//
// Authors: wjr@google.com (William Rucklidge),
// keir@google.com (Keir Mierle),
// dgossow@google.com (David Gossow)
#include "ceres/gradient_checker.h"
#include <algorithm>
#include <cmath>
#include <numeric>
#include <string>
#include <vector>
#include "ceres/is_close.h"
#include "ceres/stringprintf.h"
#include "ceres/types.h"
namespace ceres {
using internal::IsClose;
using internal::StringAppendF;
using internal::StringPrintf;
using std::string;
using std::vector;
namespace {
// Evaluate the cost function and transform the returned Jacobians to
// the local space of the respective local parameterizations.
bool EvaluateCostFunction(
const ceres::CostFunction* function,
double const* const * parameters,
const std::vector<const ceres::LocalParameterization*>&
local_parameterizations,
Vector* residuals,
std::vector<Matrix>* jacobians,
std::vector<Matrix>* local_jacobians) {
CHECK_NOTNULL(residuals);
CHECK_NOTNULL(jacobians);
CHECK_NOTNULL(local_jacobians);
const vector<int32>& block_sizes = function->parameter_block_sizes();
const int num_parameter_blocks = block_sizes.size();
// Allocate Jacobian matrices in local space.
local_jacobians->resize(num_parameter_blocks);
vector<double*> local_jacobian_data(num_parameter_blocks);
for (int i = 0; i < num_parameter_blocks; ++i) {
int block_size = block_sizes.at(i);
if (local_parameterizations.at(i) != NULL) {
block_size = local_parameterizations.at(i)->LocalSize();
}
local_jacobians->at(i).resize(function->num_residuals(), block_size);
local_jacobians->at(i).setZero();
local_jacobian_data.at(i) = local_jacobians->at(i).data();
}
// Allocate Jacobian matrices in global space.
jacobians->resize(num_parameter_blocks);
vector<double*> jacobian_data(num_parameter_blocks);
for (int i = 0; i < num_parameter_blocks; ++i) {
jacobians->at(i).resize(function->num_residuals(), block_sizes.at(i));
jacobians->at(i).setZero();
jacobian_data.at(i) = jacobians->at(i).data();
}
// Compute residuals & jacobians.
CHECK_NE(0, function->num_residuals());
residuals->resize(function->num_residuals());
residuals->setZero();
if (!function->Evaluate(parameters, residuals->data(),
jacobian_data.data())) {
return false;
}
// Convert Jacobians from global to local space.
for (size_t i = 0; i < local_jacobians->size(); ++i) {
if (local_parameterizations.at(i) == NULL) {
local_jacobians->at(i) = jacobians->at(i);
} else {
int global_size = local_parameterizations.at(i)->GlobalSize();
int local_size = local_parameterizations.at(i)->LocalSize();
CHECK_EQ(jacobians->at(i).cols(), global_size);
Matrix global_J_local(global_size, local_size);
local_parameterizations.at(i)->ComputeJacobian(
parameters[i], global_J_local.data());
local_jacobians->at(i) = jacobians->at(i) * global_J_local;
}
}
return true;
}
} // namespace
GradientChecker::GradientChecker(
const CostFunction* function,
const vector<const LocalParameterization*>* local_parameterizations,
const NumericDiffOptions& options) :
function_(function) {
CHECK_NOTNULL(function);
if (local_parameterizations != NULL) {
local_parameterizations_ = *local_parameterizations;
} else {
local_parameterizations_.resize(function->parameter_block_sizes().size(),
NULL);
}
DynamicNumericDiffCostFunction<CostFunction, CENTRAL>*
finite_diff_cost_function =
new DynamicNumericDiffCostFunction<CostFunction, CENTRAL>(
function, DO_NOT_TAKE_OWNERSHIP, options);
finite_diff_cost_function_.reset(finite_diff_cost_function);
const vector<int32>& parameter_block_sizes =
function->parameter_block_sizes();
const int num_parameter_blocks = parameter_block_sizes.size();
for (int i = 0; i < num_parameter_blocks; ++i) {
finite_diff_cost_function->AddParameterBlock(parameter_block_sizes[i]);
}
finite_diff_cost_function->SetNumResiduals(function->num_residuals());
}
bool GradientChecker::Probe(double const* const * parameters,
double relative_precision,
ProbeResults* results_param) const {
int num_residuals = function_->num_residuals();
// Make sure that we have a place to store results, no matter if the user has
// provided an output argument.
ProbeResults* results;
ProbeResults results_local;
if (results_param != NULL) {
results = results_param;
results->residuals.resize(0);
results->jacobians.clear();
results->numeric_jacobians.clear();
results->local_jacobians.clear();
results->local_numeric_jacobians.clear();
results->error_log.clear();
} else {
results = &results_local;
}
results->maximum_relative_error = 0.0;
results->return_value = true;
// Evaluate the derivative using the user supplied code.
vector<Matrix>& jacobians = results->jacobians;
vector<Matrix>& local_jacobians = results->local_jacobians;
if (!EvaluateCostFunction(function_, parameters, local_parameterizations_,
&results->residuals, &jacobians, &local_jacobians)) {
results->error_log = "Function evaluation with Jacobians failed.";
results->return_value = false;
}
// Evaluate the derivative using numeric derivatives.
vector<Matrix>& numeric_jacobians = results->numeric_jacobians;
vector<Matrix>& local_numeric_jacobians = results->local_numeric_jacobians;
Vector finite_diff_residuals;
if (!EvaluateCostFunction(finite_diff_cost_function_.get(), parameters,
local_parameterizations_, &finite_diff_residuals,
&numeric_jacobians, &local_numeric_jacobians)) {
results->error_log += "\nFunction evaluation with numerical "
"differentiation failed.";
results->return_value = false;
}
if (!results->return_value) {
return false;
}
for (int i = 0; i < num_residuals; ++i) {
if (!IsClose(
results->residuals[i],
finite_diff_residuals[i],
relative_precision,
NULL,
NULL)) {
results->error_log = "Function evaluation with and without Jacobians "
"resulted in different residuals.";
LOG(INFO) << results->residuals.transpose();
LOG(INFO) << finite_diff_residuals.transpose();
return false;
}
}
// See if any elements have relative error larger than the threshold.
int num_bad_jacobian_components = 0;
double& worst_relative_error = results->maximum_relative_error;
worst_relative_error = 0;
// Accumulate the error message for all the jacobians, since it won't get
// output if there are no bad jacobian components.
string error_log;
for (int k = 0; k < function_->parameter_block_sizes().size(); k++) {
StringAppendF(&error_log,
"========== "
"Jacobian for " "block %d: (%ld by %ld)) "
"==========\n",
k,
static_cast<long>(local_jacobians[k].rows()),
static_cast<long>(local_jacobians[k].cols()));
// The funny spacing creates appropriately aligned column headers.
error_log +=
" block row col user dx/dy num diff dx/dy "
"abs error relative error parameter residual\n";
for (int i = 0; i < local_jacobians[k].rows(); i++) {
for (int j = 0; j < local_jacobians[k].cols(); j++) {
double term_jacobian = local_jacobians[k](i, j);
double finite_jacobian = local_numeric_jacobians[k](i, j);
double relative_error, absolute_error;
bool bad_jacobian_entry =
!IsClose(term_jacobian,
finite_jacobian,
relative_precision,
&relative_error,
&absolute_error);
worst_relative_error = std::max(worst_relative_error, relative_error);
StringAppendF(&error_log,
"%6d %4d %4d %17g %17g %17g %17g %17g %17g",
k, i, j,
term_jacobian, finite_jacobian,
absolute_error, relative_error,
parameters[k][j],
results->residuals[i]);
if (bad_jacobian_entry) {
num_bad_jacobian_components++;
StringAppendF(
&error_log,
" ------ (%d,%d,%d) Relative error worse than %g",
k, i, j, relative_precision);
}
error_log += "\n";
}
}
}
// Since there were some bad errors, dump comprehensive debug info.
if (num_bad_jacobian_components) {
string header = StringPrintf("\nDetected %d bad Jacobian component(s). "
"Worst relative error was %g.\n",
num_bad_jacobian_components,
worst_relative_error);
results->error_log = header + "\n" + error_log;
return false;
}
return true;
}
} // namespace ceres

View File

@@ -26,8 +26,7 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Authors: keir@google.com (Keir Mierle),
// dgossow@google.com (David Gossow)
// Author: keir@google.com (Keir Mierle)
#include "ceres/gradient_checking_cost_function.h"
@@ -37,7 +36,7 @@
#include <string>
#include <vector>
#include "ceres/gradient_checker.h"
#include "ceres/cost_function.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/parameter_block.h"
@@ -60,25 +59,55 @@ using std::vector;
namespace {
// True if x and y have an absolute relative difference less than
// relative_precision and false otherwise. Stores the relative and absolute
// difference in relative/absolute_error if non-NULL.
bool IsClose(double x, double y, double relative_precision,
double *relative_error,
double *absolute_error) {
double local_absolute_error;
double local_relative_error;
if (!absolute_error) {
absolute_error = &local_absolute_error;
}
if (!relative_error) {
relative_error = &local_relative_error;
}
*absolute_error = abs(x - y);
*relative_error = *absolute_error / max(abs(x), abs(y));
if (x == 0 || y == 0) {
// If x or y is exactly zero, then relative difference doesn't have any
// meaning. Take the absolute difference instead.
*relative_error = *absolute_error;
}
return abs(*relative_error) < abs(relative_precision);
}
class GradientCheckingCostFunction : public CostFunction {
public:
GradientCheckingCostFunction(
const CostFunction* function,
const std::vector<const LocalParameterization*>* local_parameterizations,
const NumericDiffOptions& options,
double relative_precision,
const string& extra_info,
GradientCheckingIterationCallback* callback)
GradientCheckingCostFunction(const CostFunction* function,
const NumericDiffOptions& options,
double relative_precision,
const string& extra_info)
: function_(function),
gradient_checker_(function, local_parameterizations, options),
relative_precision_(relative_precision),
extra_info_(extra_info),
callback_(callback) {
CHECK_NOTNULL(callback_);
extra_info_(extra_info) {
DynamicNumericDiffCostFunction<CostFunction, CENTRAL>*
finite_diff_cost_function =
new DynamicNumericDiffCostFunction<CostFunction, CENTRAL>(
function,
DO_NOT_TAKE_OWNERSHIP,
options);
const vector<int32>& parameter_block_sizes =
function->parameter_block_sizes();
for (int i = 0; i < parameter_block_sizes.size(); ++i) {
finite_diff_cost_function->AddParameterBlock(parameter_block_sizes[i]);
}
*mutable_parameter_block_sizes() = parameter_block_sizes;
set_num_residuals(function->num_residuals());
finite_diff_cost_function->SetNumResiduals(num_residuals());
finite_diff_cost_function_.reset(finite_diff_cost_function);
}
virtual ~GradientCheckingCostFunction() { }
@@ -91,92 +120,133 @@ class GradientCheckingCostFunction : public CostFunction {
return function_->Evaluate(parameters, residuals, NULL);
}
GradientChecker::ProbeResults results;
bool okay = gradient_checker_.Probe(parameters,
relative_precision_,
&results);
int num_residuals = function_->num_residuals();
// If the cost function returned false, there's nothing we can say about
// the gradients.
if (results.return_value == false) {
// Make space for the jacobians of the two methods.
const vector<int32>& block_sizes = function_->parameter_block_sizes();
vector<Matrix> term_jacobians(block_sizes.size());
vector<Matrix> finite_difference_jacobians(block_sizes.size());
vector<double*> term_jacobian_pointers(block_sizes.size());
vector<double*> finite_difference_jacobian_pointers(block_sizes.size());
for (int i = 0; i < block_sizes.size(); i++) {
term_jacobians[i].resize(num_residuals, block_sizes[i]);
term_jacobian_pointers[i] = term_jacobians[i].data();
finite_difference_jacobians[i].resize(num_residuals, block_sizes[i]);
finite_difference_jacobian_pointers[i] =
finite_difference_jacobians[i].data();
}
// Evaluate the derivative using the user supplied code.
if (!function_->Evaluate(parameters,
residuals,
&term_jacobian_pointers[0])) {
LOG(WARNING) << "Function evaluation failed.";
return false;
}
// Copy the residuals.
const int num_residuals = function_->num_residuals();
MatrixRef(residuals, num_residuals, 1) = results.residuals;
// Evaluate the derivative using numeric derivatives.
finite_diff_cost_function_->Evaluate(
parameters,
residuals,
&finite_difference_jacobian_pointers[0]);
// Copy the original jacobian blocks into the jacobians array.
const vector<int32>& block_sizes = function_->parameter_block_sizes();
// See if any elements have relative error larger than the threshold.
int num_bad_jacobian_components = 0;
double worst_relative_error = 0;
// Accumulate the error message for all the jacobians, since it won't get
// output if there are no bad jacobian components.
string m;
for (int k = 0; k < block_sizes.size(); k++) {
// Copy the original jacobian blocks into the jacobians array.
if (jacobians[k] != NULL) {
MatrixRef(jacobians[k],
results.jacobians[k].rows(),
results.jacobians[k].cols()) = results.jacobians[k];
term_jacobians[k].rows(),
term_jacobians[k].cols()) = term_jacobians[k];
}
StringAppendF(&m,
"========== "
"Jacobian for " "block %d: (%ld by %ld)) "
"==========\n",
k,
static_cast<long>(term_jacobians[k].rows()),
static_cast<long>(term_jacobians[k].cols()));
// The funny spacing creates appropriately aligned column headers.
m += " block row col user dx/dy num diff dx/dy "
"abs error relative error parameter residual\n";
for (int i = 0; i < term_jacobians[k].rows(); i++) {
for (int j = 0; j < term_jacobians[k].cols(); j++) {
double term_jacobian = term_jacobians[k](i, j);
double finite_jacobian = finite_difference_jacobians[k](i, j);
double relative_error, absolute_error;
bool bad_jacobian_entry =
!IsClose(term_jacobian,
finite_jacobian,
relative_precision_,
&relative_error,
&absolute_error);
worst_relative_error = max(worst_relative_error, relative_error);
StringAppendF(&m, "%6d %4d %4d %17g %17g %17g %17g %17g %17g",
k, i, j,
term_jacobian, finite_jacobian,
absolute_error, relative_error,
parameters[k][j],
residuals[i]);
if (bad_jacobian_entry) {
num_bad_jacobian_components++;
StringAppendF(
&m, " ------ (%d,%d,%d) Relative error worse than %g",
k, i, j, relative_precision_);
}
m += "\n";
}
}
}
if (!okay) {
std::string error_log = "Gradient Error detected!\nExtra info for "
"this residual: " + extra_info_ + "\n" + results.error_log;
callback_->SetGradientErrorDetected(error_log);
// Since there were some bad errors, dump comprehensive debug info.
if (num_bad_jacobian_components) {
string header = StringPrintf("Detected %d bad jacobian component(s). "
"Worst relative error was %g.\n",
num_bad_jacobian_components,
worst_relative_error);
if (!extra_info_.empty()) {
header += "Extra info for this residual: " + extra_info_ + "\n";
}
LOG(WARNING) << "\n" << header << m;
}
return true;
}
private:
const CostFunction* function_;
GradientChecker gradient_checker_;
internal::scoped_ptr<CostFunction> finite_diff_cost_function_;
double relative_precision_;
string extra_info_;
GradientCheckingIterationCallback* callback_;
};
} // namespace
GradientCheckingIterationCallback::GradientCheckingIterationCallback()
: gradient_error_detected_(false) {
}
CallbackReturnType GradientCheckingIterationCallback::operator()(
const IterationSummary& summary) {
if (gradient_error_detected_) {
LOG(ERROR)<< "Gradient error detected. Terminating solver.";
return SOLVER_ABORT;
}
return SOLVER_CONTINUE;
}
void GradientCheckingIterationCallback::SetGradientErrorDetected(
std::string& error_log) {
mutex_.Lock();
gradient_error_detected_ = true;
error_log_ += "\n" + error_log;
mutex_.Unlock();
}
CostFunction* CreateGradientCheckingCostFunction(
const CostFunction* cost_function,
const std::vector<const LocalParameterization*>* local_parameterizations,
CostFunction *CreateGradientCheckingCostFunction(
const CostFunction *cost_function,
double relative_step_size,
double relative_precision,
const std::string& extra_info,
GradientCheckingIterationCallback* callback) {
const string& extra_info) {
NumericDiffOptions numeric_diff_options;
numeric_diff_options.relative_step_size = relative_step_size;
return new GradientCheckingCostFunction(cost_function,
local_parameterizations,
numeric_diff_options,
relative_precision, extra_info,
callback);
relative_precision,
extra_info);
}
ProblemImpl* CreateGradientCheckingProblemImpl(
ProblemImpl* problem_impl,
double relative_step_size,
double relative_precision,
GradientCheckingIterationCallback* callback) {
CHECK_NOTNULL(callback);
ProblemImpl* CreateGradientCheckingProblemImpl(ProblemImpl* problem_impl,
double relative_step_size,
double relative_precision) {
// We create new CostFunctions by wrapping the original CostFunction
// in a gradient checking CostFunction. So its okay for the
// ProblemImpl to take ownership of it and destroy it. The
@@ -190,9 +260,6 @@ ProblemImpl* CreateGradientCheckingProblemImpl(
gradient_checking_problem_options.local_parameterization_ownership =
DO_NOT_TAKE_OWNERSHIP;
NumericDiffOptions numeric_diff_options;
numeric_diff_options.relative_step_size = relative_step_size;
ProblemImpl* gradient_checking_problem_impl = new ProblemImpl(
gradient_checking_problem_options);
@@ -227,26 +294,19 @@ ProblemImpl* CreateGradientCheckingProblemImpl(
string extra_info = StringPrintf(
"Residual block id %d; depends on parameters [", i);
vector<double*> parameter_blocks;
vector<const LocalParameterization*> local_parameterizations;
parameter_blocks.reserve(residual_block->NumParameterBlocks());
local_parameterizations.reserve(residual_block->NumParameterBlocks());
for (int j = 0; j < residual_block->NumParameterBlocks(); ++j) {
ParameterBlock* parameter_block = residual_block->parameter_blocks()[j];
parameter_blocks.push_back(parameter_block->mutable_user_state());
StringAppendF(&extra_info, "%p", parameter_block->mutable_user_state());
extra_info += (j < residual_block->NumParameterBlocks() - 1) ? ", " : "]";
local_parameterizations.push_back(problem_impl->GetParameterization(
parameter_block->mutable_user_state()));
}
// Wrap the original CostFunction in a GradientCheckingCostFunction.
CostFunction* gradient_checking_cost_function =
new GradientCheckingCostFunction(residual_block->cost_function(),
&local_parameterizations,
numeric_diff_options,
relative_precision,
extra_info,
callback);
CreateGradientCheckingCostFunction(residual_block->cost_function(),
relative_step_size,
relative_precision,
extra_info);
// The const_cast is necessary because
// ProblemImpl::AddResidualBlock can potentially take ownership of

View File

@@ -26,8 +26,7 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Authors: keir@google.com (Keir Mierle),
// dgossow@google.com (David Gossow)
// Author: keir@google.com (Keir Mierle)
#ifndef CERES_INTERNAL_GRADIENT_CHECKING_COST_FUNCTION_H_
#define CERES_INTERNAL_GRADIENT_CHECKING_COST_FUNCTION_H_
@@ -35,76 +34,50 @@
#include <string>
#include "ceres/cost_function.h"
#include "ceres/iteration_callback.h"
#include "ceres/local_parameterization.h"
#include "ceres/mutex.h"
namespace ceres {
namespace internal {
class ProblemImpl;
// Callback that collects information about gradient checking errors, and
// will abort the solve as soon as an error occurs.
class GradientCheckingIterationCallback : public IterationCallback {
public:
GradientCheckingIterationCallback();
// Will return SOLVER_CONTINUE until a gradient error has been detected,
// then return SOLVER_ABORT.
virtual CallbackReturnType operator()(const IterationSummary& summary);
// Notify this that a gradient error has occurred (thread safe).
void SetGradientErrorDetected(std::string& error_log);
// Retrieve error status (not thread safe).
bool gradient_error_detected() const { return gradient_error_detected_; }
const std::string& error_log() const { return error_log_; }
private:
bool gradient_error_detected_;
std::string error_log_;
// Mutex protecting member variables.
ceres::internal::Mutex mutex_;
};
// Creates a CostFunction that checks the Jacobians that cost_function computes
// with finite differences. This API is only intended for unit tests that intend
// to check the functionality of the GradientCheckingCostFunction
// implementation directly.
CostFunction* CreateGradientCheckingCostFunction(
const CostFunction* cost_function,
const std::vector<const LocalParameterization*>* local_parameterizations,
double relative_step_size,
double relative_precision,
const std::string& extra_info,
GradientCheckingIterationCallback* callback);
// Create a new ProblemImpl object from the input problem_impl, where all
// cost functions are wrapped so that each time their Evaluate method is called,
// an additional check is performed that compares the Jacobians computed by
// the original cost function with alternative Jacobians computed using
// numerical differentiation. If local parameterizations are given for any
// parameters, the Jacobians will be compared in the local space instead of the
// ambient space. For details on the gradient checking procedure, see the
// documentation of the GradientChecker class. If an error is detected in any
// iteration, the respective cost function will notify the
// GradientCheckingIterationCallback.
// Creates a CostFunction that checks the jacobians that cost_function computes
// with finite differences. Bad results are logged; required precision is
// controlled by relative_precision and the numeric differentiation step size is
// controlled with relative_step_size. See solver.h for a better explanation of
// relative_step_size. Caller owns result.
//
// The caller owns the returned ProblemImpl object.
// The condition enforced is that
//
// (J_actual(i, j) - J_numeric(i, j))
// ------------------------------------ < relative_precision
// max(J_actual(i, j), J_numeric(i, j))
//
// where J_actual(i, j) is the jacobian as computed by the supplied cost
// function (by the user) and J_numeric is the jacobian as computed by finite
// differences.
//
// Note: This is quite inefficient and is intended only for debugging.
CostFunction* CreateGradientCheckingCostFunction(
const CostFunction* cost_function,
double relative_step_size,
double relative_precision,
const std::string& extra_info);
// Create a new ProblemImpl object from the input problem_impl, where
// each CostFunctions in problem_impl are wrapped inside a
// GradientCheckingCostFunctions. This gives us a ProblemImpl object
// which checks its derivatives against estimates from numeric
// differentiation everytime a ResidualBlock is evaluated.
//
// relative_step_size and relative_precision are parameters to control
// the numeric differentiation and the relative tolerance between the
// jacobian computed by the CostFunctions in problem_impl and
// jacobians obtained by numerically differentiating them. See the
// documentation of 'numeric_derivative_relative_step_size' in solver.h for a
// better explanation.
ProblemImpl* CreateGradientCheckingProblemImpl(
ProblemImpl* problem_impl,
double relative_step_size,
double relative_precision,
GradientCheckingIterationCallback* callback);
// jacobians obtained by numerically differentiating them. For more
// details see the documentation for
// CreateGradientCheckingCostFunction above.
ProblemImpl* CreateGradientCheckingProblemImpl(ProblemImpl* problem_impl,
double relative_step_size,
double relative_precision);
} // namespace internal
} // namespace ceres

View File

@@ -84,12 +84,6 @@ Solver::Options GradientProblemSolverOptionsToSolverOptions(
} // namespace
bool GradientProblemSolver::Options::IsValid(std::string* error) const {
const Solver::Options solver_options =
GradientProblemSolverOptionsToSolverOptions(*this);
return solver_options.IsValid(error);
}
GradientProblemSolver::~GradientProblemSolver() {
}
@@ -105,6 +99,8 @@ void GradientProblemSolver::Solve(const GradientProblemSolver::Options& options,
using internal::SetSummaryFinalCost;
double start_time = WallTimeInSeconds();
Solver::Options solver_options =
GradientProblemSolverOptionsToSolverOptions(options);
*CHECK_NOTNULL(summary) = Summary();
summary->num_parameters = problem.NumParameters();
@@ -116,16 +112,14 @@ void GradientProblemSolver::Solve(const GradientProblemSolver::Options& options,
summary->nonlinear_conjugate_gradient_type = options.nonlinear_conjugate_gradient_type; // NOLINT
// Check validity
if (!options.IsValid(&summary->message)) {
if (!solver_options.IsValid(&summary->message)) {
LOG(ERROR) << "Terminating: " << summary->message;
return;
}
// TODO(sameeragarwal): This is a bit convoluted, we should be able
// to convert to minimizer options directly, but this will do for
// now.
Minimizer::Options minimizer_options =
Minimizer::Options(GradientProblemSolverOptionsToSolverOptions(options));
// Assuming that the parameter blocks in the program have been
Minimizer::Options minimizer_options;
minimizer_options = Minimizer::Options(solver_options);
minimizer_options.evaluator.reset(new GradientProblemEvaluator(problem));
scoped_ptr<IterationCallback> logging_callback;

View File

@@ -1,59 +0,0 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2016 Google Inc. All rights reserved.
// http://ceres-solver.org/
//
// 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 Google Inc. 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.
//
// Authors: keir@google.com (Keir Mierle), dgossow@google.com (David Gossow)
#include "ceres/is_close.h"
#include <algorithm>
#include <cmath>
namespace ceres {
namespace internal {
bool IsClose(double x, double y, double relative_precision,
double *relative_error,
double *absolute_error) {
double local_absolute_error;
double local_relative_error;
if (!absolute_error) {
absolute_error = &local_absolute_error;
}
if (!relative_error) {
relative_error = &local_relative_error;
}
*absolute_error = std::fabs(x - y);
*relative_error = *absolute_error / std::max(std::fabs(x), std::fabs(y));
if (x == 0 || y == 0) {
// If x or y is exactly zero, then relative difference doesn't have any
// meaning. Take the absolute difference instead.
*relative_error = *absolute_error;
}
return *relative_error < std::fabs(relative_precision);
}
} // namespace internal
} // namespace ceres

View File

@@ -1,51 +0,0 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2016 Google Inc. All rights reserved.
// http://ceres-solver.org/
//
// 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 Google Inc. 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.
//
// Authors: keir@google.com (Keir Mierle), dgossow@google.com (David Gossow)
//
// Utility routine for comparing two values.
#ifndef CERES_INTERNAL_IS_CLOSE_H_
#define CERES_INTERNAL_IS_CLOSE_H_
namespace ceres {
namespace internal {
// Returns true if x and y have a relative (unsigned) difference less than
// relative_precision and false otherwise. Stores the relative and absolute
// difference in relative/absolute_error if non-NULL. If one of the two values
// is exactly zero, the absolute difference will be compared, and relative_error
// will be set to the absolute difference.
bool IsClose(double x,
double y,
double relative_precision,
double *relative_error,
double *absolute_error);
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_IS_CLOSE_H_

View File

@@ -191,7 +191,6 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
options.line_search_sufficient_curvature_decrease;
line_search_options.max_step_expansion =
options.max_line_search_step_expansion;
line_search_options.is_silent = options.is_silent;
line_search_options.function = &line_search_function;
scoped_ptr<LineSearch>
@@ -342,12 +341,10 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
"as the step was valid when it was selected by the line search.";
LOG_IF(WARNING, is_not_silent) << "Terminating: " << summary->message;
break;
}
if (!Evaluate(evaluator,
x_plus_delta,
&current_state,
&summary->message)) {
} else if (!Evaluate(evaluator,
x_plus_delta,
&current_state,
&summary->message)) {
summary->termination_type = FAILURE;
summary->message =
"Step failed to evaluate. This should not happen as the step was "
@@ -355,17 +352,15 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
summary->message;
LOG_IF(WARNING, is_not_silent) << "Terminating: " << summary->message;
break;
} else {
x = x_plus_delta;
}
// Compute the norm of the step in the ambient space.
iteration_summary.step_norm = (x_plus_delta - x).norm();
x = x_plus_delta;
iteration_summary.gradient_max_norm = current_state.gradient_max_norm;
iteration_summary.gradient_norm = sqrt(current_state.gradient_squared_norm);
iteration_summary.cost_change = previous_state.cost - current_state.cost;
iteration_summary.cost = current_state.cost + summary->fixed_cost;
iteration_summary.step_norm = delta.norm();
iteration_summary.step_is_valid = true;
iteration_summary.step_is_successful = true;
iteration_summary.step_size = current_state.step_size;
@@ -381,13 +376,6 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
WallTimeInSeconds() - start_time
+ summary->preprocessor_time_in_seconds;
// Iterations inside the line search algorithm are considered
// 'steps' in the broader context, to distinguish these inner
// iterations from from the outer iterations of the line search
// minimizer. The number of line search steps is the total number
// of inner line search iterations (or steps) across the entire
// minimization.
summary->num_line_search_steps += line_search_summary.num_iterations;
summary->line_search_cost_evaluation_time_in_seconds +=
line_search_summary.cost_evaluation_time_in_seconds;
summary->line_search_gradient_evaluation_time_in_seconds +=

View File

@@ -30,8 +30,6 @@
#include "ceres/local_parameterization.h"
#include <algorithm>
#include "Eigen/Geometry"
#include "ceres/householder_vector.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/fixed_array.h"
@@ -89,17 +87,28 @@ bool IdentityParameterization::MultiplyByJacobian(const double* x,
}
SubsetParameterization::SubsetParameterization(
int size, const vector<int>& constant_parameters)
: local_size_(size - constant_parameters.size()), constancy_mask_(size, 0) {
int size,
const vector<int>& constant_parameters)
: local_size_(size - constant_parameters.size()),
constancy_mask_(size, 0) {
CHECK_GT(constant_parameters.size(), 0)
<< "The set of constant parameters should contain at least "
<< "one element. If you do not wish to hold any parameters "
<< "constant, then do not use a SubsetParameterization";
vector<int> constant = constant_parameters;
std::sort(constant.begin(), constant.end());
CHECK_GE(constant.front(), 0)
<< "Indices indicating constant parameter must be greater than zero.";
CHECK_LT(constant.back(), size)
<< "Indices indicating constant parameter must be less than the size "
<< "of the parameter block.";
CHECK(std::adjacent_find(constant.begin(), constant.end()) == constant.end())
sort(constant.begin(), constant.end());
CHECK(unique(constant.begin(), constant.end()) == constant.end())
<< "The set of constant parameters cannot contain duplicates";
CHECK_LT(constant_parameters.size(), size)
<< "Number of parameters held constant should be less "
<< "than the size of the parameter block. If you wish "
<< "to hold the entire parameter block constant, then a "
<< "efficient way is to directly mark it as constant "
<< "instead of using a LocalParameterization to do so.";
CHECK_GE(*min_element(constant.begin(), constant.end()), 0);
CHECK_LT(*max_element(constant.begin(), constant.end()), size);
for (int i = 0; i < constant_parameters.size(); ++i) {
constancy_mask_[constant_parameters[i]] = 1;
}
@@ -120,10 +129,6 @@ bool SubsetParameterization::Plus(const double* x,
bool SubsetParameterization::ComputeJacobian(const double* x,
double* jacobian) const {
if (local_size_ == 0) {
return true;
}
MatrixRef m(jacobian, constancy_mask_.size(), local_size_);
m.setZero();
for (int i = 0, j = 0; i < constancy_mask_.size(); ++i) {
@@ -138,10 +143,6 @@ bool SubsetParameterization::MultiplyByJacobian(const double* x,
const int num_rows,
const double* global_matrix,
double* local_matrix) const {
if (local_size_ == 0) {
return true;
}
for (int row = 0; row < num_rows; ++row) {
for (int col = 0, j = 0; col < constancy_mask_.size(); ++col) {
if (!constancy_mask_[col]) {
@@ -183,39 +184,6 @@ bool QuaternionParameterization::ComputeJacobian(const double* x,
return true;
}
bool EigenQuaternionParameterization::Plus(const double* x_ptr,
const double* delta,
double* x_plus_delta_ptr) const {
Eigen::Map<Eigen::Quaterniond> x_plus_delta(x_plus_delta_ptr);
Eigen::Map<const Eigen::Quaterniond> x(x_ptr);
const double norm_delta =
sqrt(delta[0] * delta[0] + delta[1] * delta[1] + delta[2] * delta[2]);
if (norm_delta > 0.0) {
const double sin_delta_by_delta = sin(norm_delta) / norm_delta;
// Note, in the constructor w is first.
Eigen::Quaterniond delta_q(cos(norm_delta),
sin_delta_by_delta * delta[0],
sin_delta_by_delta * delta[1],
sin_delta_by_delta * delta[2]);
x_plus_delta = delta_q * x;
} else {
x_plus_delta = x;
}
return true;
}
bool EigenQuaternionParameterization::ComputeJacobian(const double* x,
double* jacobian) const {
jacobian[0] = x[3]; jacobian[1] = x[2]; jacobian[2] = -x[1]; // NOLINT
jacobian[3] = -x[2]; jacobian[4] = x[3]; jacobian[5] = x[0]; // NOLINT
jacobian[6] = x[1]; jacobian[7] = -x[0]; jacobian[8] = x[3]; // NOLINT
jacobian[9] = -x[0]; jacobian[10] = -x[1]; jacobian[11] = -x[2]; // NOLINT
return true;
}
HomogeneousVectorParameterization::HomogeneousVectorParameterization(int size)
: size_(size) {
CHECK_GT(size_, 1) << "The size of the homogeneous vector needs to be "
@@ -364,9 +332,9 @@ bool ProductParameterization::ComputeJacobian(const double* x,
if (!param->ComputeJacobian(x + x_cursor, buffer.get())) {
return false;
}
jacobian.block(x_cursor, delta_cursor, global_size, local_size)
= MatrixRef(buffer.get(), global_size, local_size);
delta_cursor += local_size;
x_cursor += global_size;
}

View File

@@ -67,7 +67,7 @@ FindOrDie(const Collection& collection,
// If the key is present in the map then the value associated with that
// key is returned, otherwise the value passed as a default is returned.
template <class Collection>
const typename Collection::value_type::second_type
const typename Collection::value_type::second_type&
FindWithDefault(const Collection& collection,
const typename Collection::value_type::first_type& key,
const typename Collection::value_type::second_type& value) {

View File

@@ -161,34 +161,25 @@ class ParameterBlock {
// does not take ownership of the parameterization.
void SetParameterization(LocalParameterization* new_parameterization) {
CHECK(new_parameterization != NULL) << "NULL parameterization invalid.";
// Nothing to do if the new parameterization is the same as the
// old parameterization.
if (new_parameterization == local_parameterization_) {
return;
}
CHECK(local_parameterization_ == NULL)
<< "Can't re-set the local parameterization; it leads to "
<< "ambiguous ownership. Current local parameterization is: "
<< local_parameterization_;
CHECK(new_parameterization->GlobalSize() == size_)
<< "Invalid parameterization for parameter block. The parameter block "
<< "has size " << size_ << " while the parameterization has a global "
<< "size of " << new_parameterization->GlobalSize() << ". Did you "
<< "accidentally use the wrong parameter block or parameterization?";
CHECK_GT(new_parameterization->LocalSize(), 0)
<< "Invalid parameterization. Parameterizations must have a positive "
<< "dimensional tangent space.";
local_parameterization_ = new_parameterization;
local_parameterization_jacobian_.reset(
new double[local_parameterization_->GlobalSize() *
local_parameterization_->LocalSize()]);
CHECK(UpdateLocalParameterizationJacobian())
<< "Local parameterization Jacobian computation failed for x: "
<< ConstVectorRef(state_, Size()).transpose();
if (new_parameterization != local_parameterization_) {
CHECK(local_parameterization_ == NULL)
<< "Can't re-set the local parameterization; it leads to "
<< "ambiguous ownership.";
local_parameterization_ = new_parameterization;
local_parameterization_jacobian_.reset(
new double[local_parameterization_->GlobalSize() *
local_parameterization_->LocalSize()]);
CHECK(UpdateLocalParameterizationJacobian())
<< "Local parameterization Jacobian computation failed for x: "
<< ConstVectorRef(state_, Size()).transpose();
} else {
// Ignore the case that the parameterizations match.
}
}
void SetUpperBound(int index, double upper_bound) {

View File

@@ -174,10 +174,6 @@ void Problem::SetParameterBlockVariable(double* values) {
problem_impl_->SetParameterBlockVariable(values);
}
bool Problem::IsParameterBlockConstant(double* values) const {
return problem_impl_->IsParameterBlockConstant(values);
}
void Problem::SetParameterization(
double* values,
LocalParameterization* local_parameterization) {

View File

@@ -249,11 +249,10 @@ ResidualBlock* ProblemImpl::AddResidualBlock(
// Check for duplicate parameter blocks.
vector<double*> sorted_parameter_blocks(parameter_blocks);
sort(sorted_parameter_blocks.begin(), sorted_parameter_blocks.end());
const bool has_duplicate_items =
(std::adjacent_find(sorted_parameter_blocks.begin(),
sorted_parameter_blocks.end())
!= sorted_parameter_blocks.end());
if (has_duplicate_items) {
vector<double*>::const_iterator duplicate_items =
unique(sorted_parameter_blocks.begin(),
sorted_parameter_blocks.end());
if (duplicate_items != sorted_parameter_blocks.end()) {
string blocks;
for (int i = 0; i < parameter_blocks.size(); ++i) {
blocks += StringPrintf(" %p ", parameter_blocks[i]);
@@ -573,16 +572,6 @@ void ProblemImpl::SetParameterBlockConstant(double* values) {
parameter_block->SetConstant();
}
bool ProblemImpl::IsParameterBlockConstant(double* values) const {
const ParameterBlock* parameter_block =
FindWithDefault(parameter_block_map_, values, NULL);
CHECK(parameter_block != NULL)
<< "Parameter block not found: " << values << ". You must add the "
<< "parameter block to the problem before it can be queried.";
return parameter_block->IsConstant();
}
void ProblemImpl::SetParameterBlockVariable(double* values) {
ParameterBlock* parameter_block =
FindWithDefault(parameter_block_map_, values, NULL);

View File

@@ -128,8 +128,6 @@ class ProblemImpl {
void SetParameterBlockConstant(double* values);
void SetParameterBlockVariable(double* values);
bool IsParameterBlockConstant(double* values) const;
void SetParameterization(double* values,
LocalParameterization* local_parameterization);
const LocalParameterization* GetParameterization(double* values) const;

View File

@@ -142,11 +142,6 @@ void OrderingForSparseNormalCholeskyUsingSuiteSparse(
ordering);
}
VLOG(2) << "Block ordering stats: "
<< " flops: " << ss.mutable_cc()->fl
<< " lnz : " << ss.mutable_cc()->lnz
<< " anz : " << ss.mutable_cc()->anz;
ss.Free(block_jacobian_transpose);
#endif // CERES_NO_SUITESPARSE
}

View File

@@ -127,7 +127,7 @@ class ResidualBlock {
int index() const { return index_; }
void set_index(int index) { index_ = index; }
std::string ToString() const {
std::string ToString() {
return StringPrintf("{residual block; index=%d}", index_);
}

View File

@@ -33,7 +33,6 @@
#include <algorithm>
#include <ctime>
#include <set>
#include <sstream>
#include <vector>
#include "ceres/block_random_access_dense_matrix.h"
@@ -564,12 +563,6 @@ SparseSchurComplementSolver::SolveReducedLinearSystemUsingEigen(
// worse than the one computed using the block version of the
// algorithm.
simplicial_ldlt_->analyzePattern(eigen_lhs);
if (VLOG_IS_ON(2)) {
std::stringstream ss;
simplicial_ldlt_->dumpMemory(ss);
VLOG(2) << "Symbolic Analysis\n"
<< ss.str();
}
event_logger.AddEvent("Analysis");
if (simplicial_ldlt_->info() != Eigen::Success) {
summary.termination_type = LINEAR_SOLVER_FATAL_ERROR;

View File

@@ -94,7 +94,7 @@ bool CommonOptionsAreValid(const Solver::Options& options, string* error) {
OPTION_GT(num_linear_solver_threads, 0);
if (options.check_gradients) {
OPTION_GT(gradient_check_relative_precision, 0.0);
OPTION_GT(gradient_check_numeric_derivative_relative_step_size, 0.0);
OPTION_GT(numeric_derivative_relative_step_size, 0.0);
}
return true;
}
@@ -351,7 +351,6 @@ void PreSolveSummarize(const Solver::Options& options,
summary->dense_linear_algebra_library_type = options.dense_linear_algebra_library_type; // NOLINT
summary->dogleg_type = options.dogleg_type;
summary->inner_iteration_time_in_seconds = 0.0;
summary->num_line_search_steps = 0;
summary->line_search_cost_evaluation_time_in_seconds = 0.0;
summary->line_search_gradient_evaluation_time_in_seconds = 0.0;
summary->line_search_polynomial_minimization_time_in_seconds = 0.0;
@@ -496,28 +495,21 @@ void Solver::Solve(const Solver::Options& options,
// values provided by the user.
program->SetParameterBlockStatePtrsToUserStatePtrs();
// If gradient_checking is enabled, wrap all cost functions in a
// gradient checker and install a callback that terminates if any gradient
// error is detected.
scoped_ptr<internal::ProblemImpl> gradient_checking_problem;
internal::GradientCheckingIterationCallback gradient_checking_callback;
Solver::Options modified_options = options;
if (options.check_gradients) {
modified_options.callbacks.push_back(&gradient_checking_callback);
gradient_checking_problem.reset(
CreateGradientCheckingProblemImpl(
problem_impl,
options.gradient_check_numeric_derivative_relative_step_size,
options.gradient_check_relative_precision,
&gradient_checking_callback));
options.numeric_derivative_relative_step_size,
options.gradient_check_relative_precision));
problem_impl = gradient_checking_problem.get();
program = problem_impl->mutable_program();
}
scoped_ptr<Preprocessor> preprocessor(
Preprocessor::Create(modified_options.minimizer_type));
Preprocessor::Create(options.minimizer_type));
PreprocessedProblem pp;
const bool status = preprocessor->Preprocess(modified_options, problem_impl, &pp);
const bool status = preprocessor->Preprocess(options, problem_impl, &pp);
summary->fixed_cost = pp.fixed_cost;
summary->preprocessor_time_in_seconds = WallTimeInSeconds() - start_time;
@@ -542,13 +534,6 @@ void Solver::Solve(const Solver::Options& options,
summary->postprocessor_time_in_seconds =
WallTimeInSeconds() - postprocessor_start_time;
// If the gradient checker reported an error, we want to report FAILURE
// instead of USER_FAILURE and provide the error log.
if (gradient_checking_callback.gradient_error_detected()) {
summary->termination_type = FAILURE;
summary->message = gradient_checking_callback.error_log();
}
summary->total_time_in_seconds = WallTimeInSeconds() - start_time;
}
@@ -571,7 +556,6 @@ Solver::Summary::Summary()
num_successful_steps(-1),
num_unsuccessful_steps(-1),
num_inner_iteration_steps(-1),
num_line_search_steps(-1),
preprocessor_time_in_seconds(-1.0),
minimizer_time_in_seconds(-1.0),
postprocessor_time_in_seconds(-1.0),
@@ -712,14 +696,16 @@ string Solver::Summary::FullReport() const {
num_linear_solver_threads_given,
num_linear_solver_threads_used);
string given;
StringifyOrdering(linear_solver_ordering_given, &given);
string used;
StringifyOrdering(linear_solver_ordering_used, &used);
StringAppendF(&report,
"Linear solver ordering %22s %24s\n",
given.c_str(),
used.c_str());
if (IsSchurType(linear_solver_type_used)) {
string given;
StringifyOrdering(linear_solver_ordering_given, &given);
string used;
StringifyOrdering(linear_solver_ordering_used, &used);
StringAppendF(&report,
"Linear solver ordering %22s %24s\n",
given.c_str(),
used.c_str());
}
if (inner_iterations_given) {
StringAppendF(&report,
@@ -798,14 +784,9 @@ string Solver::Summary::FullReport() const {
num_inner_iteration_steps);
}
const bool line_search_used =
(minimizer_type == LINE_SEARCH ||
(minimizer_type == TRUST_REGION && is_constrained));
if (line_search_used) {
StringAppendF(&report, "Line search steps % 14d\n",
num_line_search_steps);
}
const bool print_line_search_timing_information =
minimizer_type == LINE_SEARCH ||
(minimizer_type == TRUST_REGION && is_constrained);
StringAppendF(&report, "\nTime (in seconds):\n");
StringAppendF(&report, "Preprocessor %25.4f\n",
@@ -813,13 +794,13 @@ string Solver::Summary::FullReport() const {
StringAppendF(&report, "\n Residual evaluation %23.4f\n",
residual_evaluation_time_in_seconds);
if (line_search_used) {
if (print_line_search_timing_information) {
StringAppendF(&report, " Line search cost evaluation %10.4f\n",
line_search_cost_evaluation_time_in_seconds);
}
StringAppendF(&report, " Jacobian evaluation %23.4f\n",
jacobian_evaluation_time_in_seconds);
if (line_search_used) {
if (print_line_search_timing_information) {
StringAppendF(&report, " Line search gradient evaluation %6.4f\n",
line_search_gradient_evaluation_time_in_seconds);
}
@@ -834,7 +815,7 @@ string Solver::Summary::FullReport() const {
inner_iteration_time_in_seconds);
}
if (line_search_used) {
if (print_line_search_timing_information) {
StringAppendF(&report, " Line search polynomial minimization %.4f\n",
line_search_polynomial_minimization_time_in_seconds);
}

View File

@@ -33,7 +33,6 @@
#include <algorithm>
#include <cstring>
#include <ctime>
#include <sstream>
#include "ceres/compressed_row_sparse_matrix.h"
#include "ceres/cxsparse.h"
@@ -72,12 +71,6 @@ LinearSolver::Summary SimplicialLDLTSolve(
if (do_symbolic_analysis) {
solver->analyzePattern(lhs);
if (VLOG_IS_ON(2)) {
std::stringstream ss;
solver->dumpMemory(ss);
VLOG(2) << "Symbolic Analysis\n"
<< ss.str();
}
event_logger->AddEvent("Analyze");
if (solver->info() != Eigen::Success) {
summary.termination_type = LINEAR_SOLVER_FATAL_ERROR;

View File

@@ -43,27 +43,14 @@ namespace internal {
using std::string;
// va_copy() was defined in the C99 standard. However, it did not appear in the
// C++ standard until C++11. This means that if Ceres is being compiled with a
// strict pre-C++11 standard (e.g. -std=c++03), va_copy() will NOT be defined,
// as we are using the C++ compiler (it would however be defined if we were
// using the C compiler). Note however that both GCC & Clang will in fact
// define va_copy() when compiling for C++ if the C++ standard is not explicitly
// specified (i.e. no -std=c++<XX> arg), even though it should not strictly be
// defined unless -std=c++11 (or greater) was passed.
#if !defined(va_copy)
#if defined (__GNUC__)
// On GCC/Clang, if va_copy() is not defined (C++ standard < C++11 explicitly
// specified), use the internal __va_copy() version, which should be present
// in even very old GCC versions.
#define va_copy(d, s) __va_copy(d, s)
#else
// Some older versions of MSVC do not have va_copy(), in which case define it.
// Although this is required for older MSVC versions, it should also work for
// other non-GCC/Clang compilers which also do not defined va_copy().
#ifdef _MSC_VER
enum { IS_COMPILER_MSVC = 1 };
#if _MSC_VER < 1800
#define va_copy(d, s) ((d) = (s))
#endif // defined (__GNUC__)
#endif // !defined(va_copy)
#endif
#else
enum { IS_COMPILER_MSVC = 0 };
#endif
void StringAppendV(string* dst, const char* format, va_list ap) {
// First try with a small fixed size buffer
@@ -84,13 +71,13 @@ void StringAppendV(string* dst, const char* format, va_list ap) {
return;
}
#if defined (_MSC_VER)
// Error or MSVC running out of space. MSVC 8.0 and higher
// can be asked about space needed with the special idiom below:
va_copy(backup_ap, ap);
result = vsnprintf(NULL, 0, format, backup_ap);
va_end(backup_ap);
#endif
if (IS_COMPILER_MSVC) {
// Error or MSVC running out of space. MSVC 8.0 and higher
// can be asked about space needed with the special idiom below:
va_copy(backup_ap, ap);
result = vsnprintf(NULL, 0, format, backup_ap);
va_end(backup_ap);
}
if (result < 0) {
// Just an error.

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2016 Google Inc. All rights reserved.
// Copyright 2015 Google Inc. All rights reserved.
// http://ceres-solver.org/
//
// Redistribution and use in source and binary forms, with or without
@@ -31,136 +31,35 @@
#ifndef CERES_INTERNAL_TRUST_REGION_MINIMIZER_H_
#define CERES_INTERNAL_TRUST_REGION_MINIMIZER_H_
#include "ceres/internal/eigen.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/minimizer.h"
#include "ceres/solver.h"
#include "ceres/sparse_matrix.h"
#include "ceres/trust_region_step_evaluator.h"
#include "ceres/trust_region_strategy.h"
#include "ceres/types.h"
namespace ceres {
namespace internal {
// Generic trust region minimization algorithm.
// Generic trust region minimization algorithm. The heavy lifting is
// done by a TrustRegionStrategy object passed in as part of options.
//
// For example usage, see SolverImpl::Minimize.
class TrustRegionMinimizer : public Minimizer {
public:
~TrustRegionMinimizer();
// This method is not thread safe.
~TrustRegionMinimizer() {}
virtual void Minimize(const Minimizer::Options& options,
double* parameters,
Solver::Summary* solver_summary);
Solver::Summary* summary);
private:
void Init(const Minimizer::Options& options,
double* parameters,
Solver::Summary* solver_summary);
bool IterationZero();
bool FinalizeIterationAndCheckIfMinimizerCanContinue();
bool ComputeTrustRegionStep();
bool EvaluateGradientAndJacobian();
void ComputeCandidatePointAndEvaluateCost();
void DoLineSearch(const Vector& x,
const Vector& gradient,
const double cost,
Vector* delta);
void DoInnerIterationsIfNeeded();
bool ParameterToleranceReached();
bool FunctionToleranceReached();
bool GradientToleranceReached();
bool MaxSolverTimeReached();
bool MaxSolverIterationsReached();
bool MinTrustRegionRadiusReached();
bool IsStepSuccessful();
void HandleUnsuccessfulStep();
bool HandleSuccessfulStep();
bool HandleInvalidStep();
void Init(const Minimizer::Options& options);
void EstimateScale(const SparseMatrix& jacobian, double* scale) const;
bool MaybeDumpLinearLeastSquaresProblem(const int iteration,
const SparseMatrix* jacobian,
const double* residuals,
const double* step) const;
Minimizer::Options options_;
// These pointers are shortcuts to objects passed to the
// TrustRegionMinimizer. The TrustRegionMinimizer does not own them.
double* parameters_;
Solver::Summary* solver_summary_;
Evaluator* evaluator_;
SparseMatrix* jacobian_;
TrustRegionStrategy* strategy_;
scoped_ptr<TrustRegionStepEvaluator> step_evaluator_;
bool is_not_silent_;
bool inner_iterations_are_enabled_;
bool inner_iterations_were_useful_;
// Summary of the current iteration.
IterationSummary iteration_summary_;
// Dimensionality of the problem in the ambient space.
int num_parameters_;
// Dimensionality of the problem in the tangent space. This is the
// number of columns in the Jacobian.
int num_effective_parameters_;
// Length of the residual vector, also the number of rows in the Jacobian.
int num_residuals_;
// Current point.
Vector x_;
// Residuals at x_;
Vector residuals_;
// Gradient at x_.
Vector gradient_;
// Solution computed by the inner iterations.
Vector inner_iteration_x_;
// model_residuals = J * trust_region_step
Vector model_residuals_;
Vector negative_gradient_;
// projected_gradient_step = Plus(x, -gradient), an intermediate
// quantity used to compute the projected gradient norm.
Vector projected_gradient_step_;
// The step computed by the trust region strategy. If Jacobi scaling
// is enabled, this is a vector in the scaled space.
Vector trust_region_step_;
// The current proposal for how far the trust region algorithm
// thinks we should move. In the most basic case, it is just the
// trust_region_step_ with the Jacobi scaling undone. If bounds
// constraints are present, then it is the result of the projected
// line search.
Vector delta_;
// candidate_x = Plus(x, delta)
Vector candidate_x_;
// Scaling vector to scale the columns of the Jacobian.
Vector jacobian_scaling_;
// Euclidean norm of x_.
double x_norm_;
// Cost at x_.
double x_cost_;
// Minimum cost encountered up till now.
double minimum_cost_;
// How much did the trust region strategy reduce the cost of the
// linearized Gauss-Newton model.
double model_cost_change_;
// Cost at candidate_x_.
double candidate_cost_;
// Time at which the minimizer was started.
double start_time_in_secs_;
// Time at which the current iteration was started.
double iteration_start_time_in_secs_;
// Number of consecutive steps where the minimizer loop computed a
// numerically invalid step.
int num_consecutive_invalid_steps_;
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_TRUST_REGION_MINIMIZER_H_

View File

@@ -1,107 +0,0 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2016 Google Inc. All rights reserved.
// http://ceres-solver.org/
//
// 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 Google Inc. 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.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
#include <algorithm>
#include "ceres/trust_region_step_evaluator.h"
#include "glog/logging.h"
namespace ceres {
namespace internal {
TrustRegionStepEvaluator::TrustRegionStepEvaluator(
const double initial_cost,
const int max_consecutive_nonmonotonic_steps)
: max_consecutive_nonmonotonic_steps_(max_consecutive_nonmonotonic_steps),
minimum_cost_(initial_cost),
current_cost_(initial_cost),
reference_cost_(initial_cost),
candidate_cost_(initial_cost),
accumulated_reference_model_cost_change_(0.0),
accumulated_candidate_model_cost_change_(0.0),
num_consecutive_nonmonotonic_steps_(0){
}
double TrustRegionStepEvaluator::StepQuality(
const double cost,
const double model_cost_change) const {
const double relative_decrease = (current_cost_ - cost) / model_cost_change;
const double historical_relative_decrease =
(reference_cost_ - cost) /
(accumulated_reference_model_cost_change_ + model_cost_change);
return std::max(relative_decrease, historical_relative_decrease);
}
void TrustRegionStepEvaluator::StepAccepted(
const double cost,
const double model_cost_change) {
// Algorithm 10.1.2 from Trust Region Methods by Conn, Gould &
// Toint.
//
// Step 3a
current_cost_ = cost;
accumulated_candidate_model_cost_change_ += model_cost_change;
accumulated_reference_model_cost_change_ += model_cost_change;
// Step 3b.
if (current_cost_ < minimum_cost_) {
minimum_cost_ = current_cost_;
num_consecutive_nonmonotonic_steps_ = 0;
candidate_cost_ = current_cost_;
accumulated_candidate_model_cost_change_ = 0.0;
} else {
// Step 3c.
++num_consecutive_nonmonotonic_steps_;
if (current_cost_ > candidate_cost_) {
candidate_cost_ = current_cost_;
accumulated_candidate_model_cost_change_ = 0.0;
}
}
// Step 3d.
//
// At this point we have made too many non-monotonic steps and
// we are going to reset the value of the reference iterate so
// as to force the algorithm to descend.
//
// Note: In the original algorithm by Toint, this step was only
// executed if the step was non-monotonic, but that would not handle
// the case of max_consecutive_nonmonotonic_steps = 0. The small
// modification of doing this always handles that corner case
// correctly.
if (num_consecutive_nonmonotonic_steps_ ==
max_consecutive_nonmonotonic_steps_) {
reference_cost_ = candidate_cost_;
accumulated_reference_model_cost_change_ =
accumulated_candidate_model_cost_change_;
}
}
} // namespace internal
} // namespace ceres

View File

@@ -1,122 +0,0 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2016 Google Inc. All rights reserved.
// http://ceres-solver.org/
//
// 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 Google Inc. 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.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
#ifndef CERES_INTERNAL_TRUST_REGION_STEP_EVALUATOR_H_
#define CERES_INTERNAL_TRUST_REGION_STEP_EVALUATOR_H_
namespace ceres {
namespace internal {
// The job of the TrustRegionStepEvaluator is to evaluate the quality
// of a step, i.e., how the cost of a step compares with the reduction
// in the objective of the trust region problem.
//
// Classic trust region methods are descent methods, in that they only
// accept a point if it strictly reduces the value of the objective
// function. They do this by measuring the quality of a step as
//
// cost_change / model_cost_change.
//
// Relaxing the monotonic descent requirement allows the algorithm to
// be more efficient in the long term at the cost of some local
// increase in the value of the objective function.
//
// This is because allowing for non-decreasing objective function
// values in a principled manner allows the algorithm to "jump over
// boulders" as the method is not restricted to move into narrow
// valleys while preserving its convergence properties.
//
// The parameter max_consecutive_nonmonotonic_steps controls the
// window size used by the step selection algorithm to accept
// non-monotonic steps. Setting this parameter to zero, recovers the
// classic montonic descent algorithm.
//
// Based on algorithm 10.1.2 (page 357) of "Trust Region
// Methods" by Conn Gould & Toint, or equations 33-40 of
// "Non-monotone trust-region algorithms for nonlinear
// optimization subject to convex constraints" by Phil Toint,
// Mathematical Programming, 77, 1997.
//
// Example usage:
//
// TrustRegionStepEvaluator* step_evaluator = ...
//
// cost = ... // Compute the non-linear objective function value.
// model_cost_change = ... // Change in the value of the trust region objective.
// if (step_evaluator->StepQuality(cost, model_cost_change) > threshold) {
// x = x + delta;
// step_evaluator->StepAccepted(cost, model_cost_change);
// }
class TrustRegionStepEvaluator {
public:
// initial_cost is as the name implies the cost of the starting
// state of the trust region minimizer.
//
// max_consecutive_nonmonotonic_steps controls the window size used
// by the step selection algorithm to accept non-monotonic
// steps. Setting this parameter to zero, recovers the classic
// montonic descent algorithm.
TrustRegionStepEvaluator(double initial_cost,
int max_consecutive_nonmonotonic_steps);
// Return the quality of the step given its cost and the decrease in
// the cost of the model. model_cost_change has to be positive.
double StepQuality(double cost, double model_cost_change) const;
// Inform the step evaluator that a step with the given cost and
// model_cost_change has been accepted by the trust region
// minimizer.
void StepAccepted(double cost, double model_cost_change);
private:
const int max_consecutive_nonmonotonic_steps_;
// The minimum cost encountered up till now.
double minimum_cost_;
// The current cost of the trust region minimizer as informed by the
// last call to StepAccepted.
double current_cost_;
double reference_cost_;
double candidate_cost_;
// Accumulated model cost since the last time the reference model
// cost was updated, i.e., when a step with cost less than the
// current known minimum cost is accepted.
double accumulated_reference_model_cost_change_;
// Accumulated model cost since the last time the candidate model
// cost was updated, i.e., a non-monotonic step was taken with a
// cost that was greater than the current candidate cost.
double accumulated_candidate_model_cost_change_;
// Number of steps taken since the last time minimum_cost was updated.
int num_consecutive_nonmonotonic_steps_;
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_TRUST_REGION_STEP_EVALUATOR_H_

View File

@@ -86,20 +86,20 @@ class TrustRegionStrategy {
struct PerSolveOptions {
PerSolveOptions()
: eta(0),
dump_filename_base(""),
dump_format_type(TEXTFILE) {
}
// Forcing sequence for inexact solves.
double eta;
DumpFormatType dump_format_type;
// If non-empty and dump_format_type is not CONSOLE, the trust
// regions strategy will write the linear system to file(s) with
// name starting with dump_filename_base. If dump_format_type is
// CONSOLE then dump_filename_base will be ignored and the linear
// system will be written to the standard error.
std::string dump_filename_base;
DumpFormatType dump_format_type;
};
struct Summary {

View File

@@ -1,5 +1,5 @@
Project: OpenCL Wrangler
URL: https://github.com/OpenCLWrangler/clew
License: Apache 2.0
Upstream version: 309a653
Upstream version: 277db43
Local modifications: None

View File

@@ -369,8 +369,7 @@ typedef unsigned int cl_GLenum;
#endif
/* Define basic vector types */
/* WOrkaround for ppc64el platform: conflicts with bool from C++. */
#if defined( __VEC__ ) && !(defined(__PPC64__) && defined(__LITTLE_ENDIAN__))
#if defined( __VEC__ )
#include <altivec.h> /* may be omitted depending on compiler. AltiVec spec provides no way to detect whether the header is required. */
typedef vector unsigned char __cl_uchar16;
typedef vector signed char __cl_char16;

View File

@@ -137,17 +137,6 @@ PFNCLCREATEFROMGLTEXTURE3D __clewCreateFromGLTexture3D = NULL;
#endif
PFNCLGETGLCONTEXTINFOKHR __clewGetGLContextInfoKHR = NULL;
static CLEW_DYNLIB_HANDLE dynamic_library_open_find(const char **paths) {
int i = 0;
while (paths[i] != NULL) {
CLEW_DYNLIB_HANDLE lib = CLEW_DYNLIB_OPEN(paths[i]);
if (lib != NULL) {
return lib;
}
++i;
}
return NULL;
}
static void clewExit(void)
{
@@ -162,15 +151,11 @@ static void clewExit(void)
int clewInit()
{
#ifdef _WIN32
const char *paths[] = {"OpenCL.dll", NULL};
const char *path = "OpenCL.dll";
#elif defined(__APPLE__)
const char *paths[] = {"/Library/Frameworks/OpenCL.framework/OpenCL", NULL};
const char *path = "/Library/Frameworks/OpenCL.framework/OpenCL";
#else
const char *paths[] = {"libOpenCL.so",
"libOpenCL.so.0",
"libOpenCL.so.1",
"libOpenCL.so.2",
NULL};
const char *path = "libOpenCL.so";
#endif
int error = 0;
@@ -182,7 +167,7 @@ int clewInit()
}
// Load library
module = dynamic_library_open_find(paths);
module = CLEW_DYNLIB_OPEN(path);
// Check for errors
if (module == NULL)

2
extern/cuew/README vendored
View File

@@ -4,7 +4,7 @@ for determining which CUDA functions and extensions extensions are supported
on the target platform.
CUDA core and extension functionality is exposed in a single header file.
CUEW has been tested on a variety of operating systems, including Windows,
GUEW has been tested on a variety of operating systems, including Windows,
Linux, Mac OS X.
LICENSE

View File

@@ -1,5 +1,5 @@
Project: Cuda Wrangler
URL: https://github.com/CudaWrangler/cuew
License: Apache 2.0
Upstream version: 63d2a0f
Upstream version: e2e0315
Local modifications: None

View File

@@ -137,7 +137,7 @@ int curve_fit_cubic_to_points_refit_db(
const double error_threshold,
const unsigned int calc_flag,
const unsigned int *corners,
const unsigned int corners_len,
unsigned int corners_len,
const double corner_angle,
double **r_cubic_array, unsigned int *r_cubic_array_len,

View File

@@ -255,7 +255,7 @@ static void cubic_list_clear(CubicList *clist)
/** \name Cubic Evaluation
* \{ */
static void cubic_calc_point(
static void cubic_evaluate(
const Cubic *cubic, const double t, const uint dims,
double r_v[])
{
@@ -271,6 +271,18 @@ static void cubic_calc_point(
}
}
static void cubic_calc_point(
const Cubic *cubic, const double t, const uint dims,
double r_v[])
{
CUBIC_VARS_CONST(cubic, dims, p0, p1, p2, p3);
const double s = 1.0 - t;
for (uint j = 0; j < dims; j++) {
r_v[j] = p0[j] * s * s * s +
3.0 * t * s * (s * p1[j] + t * p2[j]) + t * t * t * p3[j];
}
}
static void cubic_calc_speed(
const Cubic *cubic, const double t, const uint dims,
double r_v[])
@@ -320,7 +332,7 @@ static double cubic_calc_error(
#endif
for (uint i = 1; i < points_offset_len - 1; i++, pt_real += dims) {
cubic_calc_point(cubic, u[i], dims, pt_eval);
cubic_evaluate(cubic, u[i], dims, pt_eval);
const double err_sq = len_squared_vnvn(pt_real, pt_eval, dims);
if (err_sq >= error_max_sq) {
@@ -356,7 +368,7 @@ static double cubic_calc_error_simple(
#endif
for (uint i = 1; i < points_offset_len - 1; i++, pt_real += dims) {
cubic_calc_point(cubic, u[i], dims, pt_eval);
cubic_evaluate(cubic, u[i], dims, pt_eval);
const double err_sq = len_squared_vnvn(pt_real, pt_eval, dims);
if (err_sq >= error_threshold_sq) {
@@ -489,7 +501,7 @@ static double points_calc_circle_tangent_factor(
return (1.0 / 3.0) * 0.75;
}
else if (tan_dot < -1.0 + eps) {
/* parallel tangents (half-circle) */
/* parallele tangents (half-circle) */
return (1.0 / 2.0);
}
else {
@@ -611,8 +623,8 @@ static void cubic_from_points_offset_fallback(
}
}
double alpha_l = (dists[0] / 0.75) / fabs(dot_vnvn(tan_l, a[0], dims));
double alpha_r = (dists[1] / 0.75) / fabs(dot_vnvn(tan_r, a[1], dims));
double alpha_l = (dists[0] / 0.75) / dot_vnvn(tan_l, a[0], dims);
double alpha_r = (dists[1] / 0.75) / -dot_vnvn(tan_r, a[1], dims);
if (!(alpha_l > 0.0)) {
alpha_l = dir_dist / 3.0;
@@ -665,11 +677,13 @@ static void cubic_from_points(
double alpha_l, alpha_r;
#ifdef USE_VLA
double a[2][dims];
double tmp[dims];
#else
double *a[2] = {
alloca(sizeof(double) * dims),
alloca(sizeof(double) * dims),
};
double *tmp = alloca(sizeof(double) * dims);
#endif
{
@@ -680,22 +694,22 @@ static void cubic_from_points(
mul_vnvn_fl(a[0], tan_l, B1(u_prime[i]), dims);
mul_vnvn_fl(a[1], tan_r, B2(u_prime[i]), dims);
const double b0_plus_b1 = B0plusB1(u_prime[i]);
const double b2_plus_b3 = B2plusB3(u_prime[i]);
/* inline dot product */
for (uint j = 0; j < dims; j++) {
const double tmp = (pt[j] - (p0[j] * b0_plus_b1)) + (p3[j] * b2_plus_b3);
x[0] += a[0][j] * tmp;
x[1] += a[1][j] * tmp;
c[0][0] += a[0][j] * a[0][j];
c[0][1] += a[0][j] * a[1][j];
c[1][1] += a[1][j] * a[1][j];
}
c[0][0] += dot_vnvn(a[0], a[0], dims);
c[0][1] += dot_vnvn(a[0], a[1], dims);
c[1][1] += dot_vnvn(a[1], a[1], dims);
c[1][0] = c[0][1];
{
const double b0_plus_b1 = B0plusB1(u_prime[i]);
const double b2_plus_b3 = B2plusB3(u_prime[i]);
for (uint j = 0; j < dims; j++) {
tmp[j] = (pt[j] - (p0[j] * b0_plus_b1)) + (p3[j] * b2_plus_b3);
}
x[0] += dot_vnvn(a[0], tmp, dims);
x[1] += dot_vnvn(a[1], tmp, dims);
}
}
double det_C0_C1 = c[0][0] * c[1][1] - c[0][1] * c[1][0];

View File

@@ -463,7 +463,7 @@ static uint curve_incremental_simplify(
rstate_pool_create(&epool, 0);
#endif
Heap *heap = HEAP_new(knots_len_remaining);
Heap *heap = HEAP_new(knots_len);
struct KnotRemove_Params params = {
.pd = pd,
@@ -698,7 +698,7 @@ static uint curve_incremental_simplify_refit(
refit_pool_create(&epool, 0);
#endif
Heap *heap = HEAP_new(knots_len_remaining);
Heap *heap = HEAP_new(knots_len);
struct KnotRefit_Params params = {
.pd = pd,
@@ -890,7 +890,7 @@ static void knot_corner_error_recalculate(
static uint curve_incremental_simplify_corners(
const struct PointData *pd,
struct Knot *knots, const uint knots_len, uint knots_len_remaining,
const double error_sq_max, const double error_sq_collapse_max,
const double error_sq_max, const double error_sq_2x_max,
const double corner_angle,
const uint dims,
uint *r_corner_index_len)
@@ -954,12 +954,12 @@ static uint curve_incremental_simplify_corners(
project_vn_vnvn_normalized(k_proj_ref, co_prev, k_prev->tan[1], dims);
project_vn_vnvn_normalized(k_proj_split, co_split, k_prev->tan[1], dims);
if (len_squared_vnvn(k_proj_ref, k_proj_split, dims) < error_sq_collapse_max) {
if (len_squared_vnvn(k_proj_ref, k_proj_split, dims) < error_sq_2x_max) {
project_vn_vnvn_normalized(k_proj_ref, co_next, k_next->tan[0], dims);
project_vn_vnvn_normalized(k_proj_split, co_split, k_next->tan[0], dims);
if (len_squared_vnvn(k_proj_ref, k_proj_split, dims) < error_sq_collapse_max) {
if (len_squared_vnvn(k_proj_ref, k_proj_split, dims) < error_sq_2x_max) {
struct Knot *k_split = &knots[split_index];
@@ -1048,6 +1048,7 @@ int curve_fit_cubic_to_points_refit_db(
{
const uint knots_len = points_len;
struct Knot *knots = malloc(sizeof(Knot) * knots_len);
knots[0].next = NULL;
#ifndef USE_CORNER_DETECT
(void)r_corner_index_array;
@@ -1084,6 +1085,7 @@ int curve_fit_cubic_to_points_refit_db(
knots[i].heap_node = NULL;
knots[i].index = i;
knots[i].index = i;
knots[i].can_remove = true;
knots[i].is_removed = false;
knots[i].is_corner = false;
@@ -1153,8 +1155,8 @@ int curve_fit_cubic_to_points_refit_db(
add_vn_vnvn(k->tan[0], tan_prev, tan_next, dims);
normalize_vn(k->tan[0], dims);
copy_vnvn(k->tan[1], k->tan[0], dims);
k->handles[0] = len_prev / 3;
k->handles[1] = len_next / -3;
k->handles[0] = len_prev / 3;
k->handles[1] = len_next / 3;
}
#else
if (knots_len < 2) {
@@ -1183,8 +1185,8 @@ int curve_fit_cubic_to_points_refit_db(
add_vn_vnvn(k->tan[0], tan_prev, tan_next, dims);
normalize_vn(k->tan[0], dims);
copy_vnvn(k->tan[1], k->tan[0], dims);
k->handles[0] = len_prev / 3;
k->handles[1] = len_next / -3;
k->handles[0] = len_prev / 3;
k->handles[1] = len_next / 3;
copy_vnvn(tan_prev, tan_next, dims);
len_prev = len_next;
@@ -1199,8 +1201,8 @@ int curve_fit_cubic_to_points_refit_db(
tan_prev, &points[0 * dims], &points[1 * dims], dims);
copy_vnvn(knots[0].tan[0], tan_prev, dims);
copy_vnvn(knots[0].tan[1], tan_prev, dims);
knots[0].handles[0] = len_prev / 3;
knots[0].handles[1] = len_prev / -3;
knots[0].handles[0] = len_prev / 3;
knots[0].handles[1] = len_prev / 3;
for (uint i_curr = 1, i_next = 2; i_next < knots_len; i_curr = i_next++) {
struct Knot *k = &knots[i_curr];
@@ -1213,8 +1215,8 @@ int curve_fit_cubic_to_points_refit_db(
add_vn_vnvn(k->tan[0], tan_prev, tan_next, dims);
normalize_vn(k->tan[0], dims);
copy_vnvn(k->tan[1], k->tan[0], dims);
k->handles[0] = len_prev / 3;
k->handles[1] = len_next / -3;
k->handles[0] = len_prev / 3;
k->handles[1] = len_next / 3;
copy_vnvn(tan_prev, tan_next, dims);
len_prev = len_next;
@@ -1222,8 +1224,8 @@ int curve_fit_cubic_to_points_refit_db(
copy_vnvn(knots[knots_len - 1].tan[0], tan_next, dims);
copy_vnvn(knots[knots_len - 1].tan[1], tan_next, dims);
knots[knots_len - 1].handles[0] = len_next / 3;
knots[knots_len - 1].handles[1] = len_next / -3;
knots[knots_len - 1].handles[0] = len_next / 3;
knots[knots_len - 1].handles[1] = len_next / 3;
}
#endif
}
@@ -1260,12 +1262,9 @@ int curve_fit_cubic_to_points_refit_db(
#ifdef USE_CORNER_DETECT
if (use_corner) {
#ifdef DEBUG
for (uint i = 0; i < knots_len; i++) {
assert(knots[i].heap_node == NULL);
}
#endif
knots_len_remaining = curve_incremental_simplify_corners(
&pd, knots, knots_len, knots_len_remaining,

View File

@@ -18,8 +18,6 @@ Local modifications:
- Applied some modifications from fork https://github.com/Nazg-Gul/gflags.git
(see https://github.com/gflags/gflags/pull/129)
- Avoid attempt of acquiring mutex lock in FlagRegistry::GlobalRegistry when
- Avoid attemot of acquiring mutex lock in FlagRegistry::GlobalRegistry when
doing static flags initialization. See d81dd2d in Blender repository.
- Made `google::{anonymous}::FlagValue::ValueSize() const` inlined, so it does
not trigger strict compiler warning.

View File

@@ -218,7 +218,7 @@ class FlagValue {
bool Equal(const FlagValue& x) const;
FlagValue* New() const; // creates a new one with default value
void CopyFrom(const FlagValue& x);
inline int ValueSize() const;
int ValueSize() const;
// Calls the given validate-fn on value_buffer_, and returns
// whatever it returns. But first casts validate_fn_proto to a
@@ -443,7 +443,7 @@ void FlagValue::CopyFrom(const FlagValue& x) {
}
}
inline int FlagValue::ValueSize() const {
int FlagValue::ValueSize() const {
if (type_ > FV_MAX_INDEX) {
assert(false); // unknown type
return 0;

View File

@@ -59,8 +59,7 @@
# include <unistd.h>
#endif
// Hurd does not have SYS_write.
#if (defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)) && !defined(__GNU__)
#if defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)
# define safe_write(fd, s, len) syscall(SYS_write, fd, s, len)
#else
// Not so safe, but what can you do?

View File

@@ -111,7 +111,7 @@ int GetStackTrace(void** result, int max_depth, int skip_count) {
result[n++] = *(sp+2);
#elif defined(_CALL_SYSV)
result[n++] = *(sp+1);
#elif defined(__APPLE__) || ((defined(__linux) || defined(__linux__)) && defined(__PPC64__))
#elif defined(__APPLE__) || (defined(__linux) && defined(__PPC64__))
// This check is in case the compiler doesn't define _CALL_AIX/etc.
result[n++] = *(sp+2);
#elif defined(__linux)

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