Compare commits

..

164 Commits

Author SHA1 Message Date
40f92e161a Quiet a warning in non-debug build. 2020-08-28 10:44:09 -04:00
b8cc4b9392 Merge branch 'master' into newboolean 2020-08-28 10:27:21 -04:00
8556a10bd9 Moved orientation etc tests into BLI_math_boolean.hh.
These tests are only used by the delaunay, mesh_intersect,
and mesh_boolean files. At the suggestion of Brecht, moving
them into BLI_math_boolean.hh and math_boolean.cc.
2020-08-28 10:21:59 -04:00
123955377c Merge branch 'master' into newboolean 2020-08-28 07:43:07 -04:00
baf9ee73d3 Use blo_do_versions_290 to set Fast solver for pre-2.91 files. 2020-08-28 07:18:46 -04:00
665ffa5dca Cleanup: more spelling corrections 2020-08-27 18:53:02 +10:00
cc0a0d3291 Expand on solver descriptions 2020-08-27 18:37:59 +10:00
e0cb025870 Cleanup: mostly comments, use doxy syntax & typos
- Use doxy syntax for functions.
- Use `pragma once` for header guard.
2020-08-27 18:18:47 +10:00
94884777b2 Merge branch 'master' into newboolean 2020-08-27 15:49:22 +10:00
0659560a10 Merge branch 'master' into newboolean 2020-08-26 07:21:08 -04:00
77242de80e Refactor to defer building Plane for Faces until later.
This is a precursor to a big speed optimization in the "finding clusters"
code. Right now there is no speedup, maybe even a bit of a slowdown,
but following commits should lead to nice speed increases.
2020-08-26 06:59:58 -04:00
4909e599e8 Some small speedups from parallelizing more parts.
Parallelized bounding box finding and degenerate triangle testing.
2020-08-23 10:12:55 -04:00
f4e337a7da Some tweaks to multithreading parameters based on tests to minimize time. 2020-08-22 15:53:22 -04:00
99d4d94762 Merge branch 'master' into newboolean 2020-08-22 09:44:33 -04:00
7cc85d8b9c A couple more cleanups inspire by reviewer comments. 2020-08-22 09:33:00 -04:00
2231c4bd89 Fix clang-tidy warnings. 2020-08-22 08:19:10 -04:00
7e06208f6a Fixed an error and warning on Linux from previous commit. 2020-08-22 08:02:33 -04:00
9810cfa1e8 Addressed comments of reviewers on D8623.
Almost all changes asked for by Campbell and Jacques have been
addressed. The clang-tidy fixes will happen in the next commit.
2020-08-22 07:30:13 -04:00
0a6ef69509 Cleanup: move break statements into case body, or remove if follwing a return. 2020-08-21 10:16:37 -04:00
4b13eb2788 Rename some classes at the suggestion of reviewers.
Mesh -> IMesh; MArena -> IMeshArena
Remove type abbreviations Vertp and Facep.
2020-08-21 10:02:58 -04:00
481927d4d6 Use an enum type for solver in boolean modifier.
This matches what was done in a previous commit for the tool.
It makes it easier to associate a tooltip with each choice.
For this branch, I have the default solver be the Exact one;
when we merge to master, we will have to decide the best default.
Make format caught a coouple other files, sorr for not doing those
earlier.
2020-08-21 08:23:18 -04:00
de294bb3e2 Use custom layout for intersect tools, with expanded choices.
Makes "Exact" vs "Fast" a choice with tooltips for each.
Hides merge threshold when in Exact mode.
2020-08-20 21:23:21 -04:00
6903b3414a Renamed boolean to meah_boolean in BLI file names. 2020-08-20 19:46:57 -04:00
3b36e2b781 Merge branch 'master' into newboolean 2020-08-20 17:03:51 -04:00
57c3718447 Revert "Use std::abs instead of fabs in C++ code."
This reverts commit eac84bf527.

Using std::abs causes ambiguity problems when compiling on a Mac.
2020-08-19 20:29:09 -04:00
eac84bf527 Use std::abs instead of fabs in C++ code. 2020-08-19 18:20:31 -04:00
fa9a630b29 Use std::lower_bound instead of custom binary search. 2020-08-19 17:48:28 -04:00
f5c7a6d3b6 Fix memory leak in delaunay C interface code. 2020-08-19 17:29:04 -04:00
db292912f4 Fix crash in Debug build for some cases of no intersects. 2020-08-19 07:35:57 -04:00
b1a53cc85b Merge branch 'master' into newboolean 2020-08-19 16:43:30 +10:00
108e6d4ef2 Better performance when there are clusters of coplanar triangles. 2020-08-18 21:51:35 -04:00
5cd49e46f4 Added a sphere/grid test to mesh intersect performance tests. 2020-08-18 06:12:47 -04:00
f65a50d794 Tweaked the performance debugging gathering. 2020-08-16 19:01:52 -04:00
cce4bafc53 Add support for non-closed-volume arguments.
Use a "generalized winding number" calculation to get an inside/outside
test that works reasonably well when meshes aren't closed.
This change allows one to use a plane as the cutter in a difference
operator and get the expected results.
2020-08-16 11:05:58 -04:00
06696ab0bd Let Boolean be seen in edit mode, if enabled.
Since the beginning of time, Boolean has not supported this.
While it might be too slow for some uses, it seems that the user
should be able to decide whether to use it or not.
2020-08-15 13:21:36 -04:00
eba77a95fc Fixed a bug in dissolving triangulation edges.
If an original face was divided into triangles with different
orientations, the program would crash. Fixed now.
2020-08-15 13:03:13 -04:00
abd7b1c20e Merge branch 'master' into newboolean 2020-08-15 08:24:19 -04:00
4d9d12a48f Added more debugging help. 2020-08-15 07:22:25 -04:00
d75c86429f Checking for PWN.
The current code is only supposed to work if the input meshes
are "piecewise constant winding number" (PWN). Added a check
to see if this is true about the inputs.
2020-08-12 07:35:48 -04:00
2b6bd6f76d Fix the nearest point containing cell when nearest is inside a tri. 2020-08-09 16:16:07 -04:00
7f5a4053f5 Remove degenerate triangles before intersecting. 2020-08-09 13:38:37 -04:00
18c6d7b066 Use #pragma in newboolean branch. 2020-08-09 07:32:33 -04:00
e66c59129c Merge branch 'master' into newboolean 2020-08-09 07:24:50 -04:00
56b547aa9d Cleanup: stop some warnings. 2020-08-09 07:14:09 -04:00
8da4842fd5 Fixed bug in understanding of nesting of connected components. 2020-08-08 17:23:11 -04:00
81410044bc Add debugging to face merge. 2020-08-07 09:25:36 -04:00
c581c4ae44 Fix crash when point finding encounters a coplanar stack. 2020-08-05 19:19:48 -04:00
843aead88e Disable the boolean and modifier python tests.
These tests rely on the behavoir of the old boolean, down the the
exact values of coordinates and ordering of the output vertices.
Because I want the default behavior of boolean to be new boolean
in this branch, this is inconvenient. I will make these tests work
again if/when we merge with master. Probably by adding the flag
that invokes the old behavior to the tests.
New bevel is mostly tested by unit tests now, so disabling the
regression test for it is not a big deal.
2020-08-05 15:52:48 -04:00
0023d30590 Merge branch 'master' into newboolean 2020-08-05 15:13:57 -04:00
4539f345e8 Fixed bug where normals were sometimes wrong after a difference op.
Needed to check for correct orientation of a face before reusing an
original face.
Also added another test case.
2020-08-05 15:02:21 -04:00
ca109986a6 Add some more boolean unit tests. 2020-08-05 10:03:06 -04:00
10109fd1b2 Fix union of two disjoint meshes.
Also added unit test for that.
2020-08-05 09:25:25 -04:00
37d326a052 Merge branch 'master' into newboolean 2020-08-04 15:35:50 -04:00
1ae25d48dd Resetting some stuff that got messed up with previous commit. 2020-08-04 15:20:50 -04:00
f2bee8e5e6 Fixed several filtering bugs.
Several bugs with the acceleration filters cauased crashes and
incorrect results. Redid the error analysis and found some mistakes.
There was also a bug in the code for checking non-trivial intersections.
Now you can boolean a standard cube and cylinder and scale the cylinder
without crashing.
Also rewrote the tri-tri intersection code to make it more understandable
and also prepare the way for more floating filters.
2020-08-04 13:48:30 -04:00
3e30fd75ab Fix bugs re triangle sorting.
Several somewhat self-compensating bugs in the routine that sorts
triangles around an edge let to a bug visible with a unit cube
subtracting a unit cylinder with 4 sides. Fixed.
2020-08-02 17:13:54 -04:00
e65ddfa5fd Fix building WITH_GMP in case of boolean modifier.
Left out a define.
Also, added more debugging in boolean.cc.
2020-08-02 10:30:35 -04:00
b9845566b4 Merge branch 'master' into newboolean.
Also, make it possible to build when WITH_GMP is disabled.
2020-08-02 09:35:20 -04:00
771da552bb Warning removal: Remove unused argument; make a private function static. 2020-08-02 06:44:42 -04:00
eb0231f20f Handle cases of nested meshes.
This fixes some "implement me" crashes and also case where one
moves a cutter completely inside the cut mesh.
Also fixed a bug in the implementation of mpq3::distance_squared.
2020-08-01 18:24:16 -04:00
04ba7e05e8 Merge branch 'master' into newboolean 2020-07-31 08:49:42 -04:00
9f23dbe75c Merge branch 'master' into newboolean 2020-07-30 19:47:41 -04:00
a85a52f064 Fix wrong use of initializer in C++. Fix unused parameter. 2020-07-30 19:13:53 -04:00
7755a2ed78 Fix a coplanar case - two cubes forming steps.
Needed careful logic about what to do with zero volume cells.
It worked before on some cases by accident, but now it should
work on any depth stack of coincident faces.
2020-07-30 17:58:36 -04:00
64d8f6b191 Use floating point filtering to make the degenerate triangle detection faster. 2020-07-26 13:23:49 -04:00
7781c49c22 Set up to try either spinlock or mutex for boolean parallelism.
On my 48 core Linux machine, mutex's seem to lead to faster execution.
2020-07-26 13:09:29 -04:00
4c25824f19 Use multithreading to calculate subdivided triangles. 2020-07-26 12:43:37 -04:00
a2dbeb458c Merge branch 'master' into newboolean 2020-07-26 06:47:46 -04:00
accadbc2aa Used wrong #if to isolate debugging code for Windows. 2020-07-26 06:38:02 -04:00
d6e3ba3416 Fix the knife boolean modes.
Had to track the intersect edges through from mesh_intersect
through to the bmesh boolean.
2020-07-25 21:19:39 -04:00
04ea79dc0b Turn off debug file writing in boolean etc unit tests.
Also, for Windows, do something other than /tmp when file writing
is turned on. This file writing is only intended for debugging.
2020-07-24 16:20:33 -04:00
e18cf6f998 Interpolate face loop data from example faces.
This makes for a reasonable first pass at getting OK UV maps.
2020-07-24 09:58:34 -04:00
50b7025ebf Use original edges as examples when possible.
These means that, for example, an original edge that has a bevel
weight and only survives partly after the boolean will still
have that bevel weight.
2020-07-24 09:27:26 -04:00
3edc33123c BMesh construction now better at preserving attributes of mesh elements.
Uses existing BMVerts, BMEdges, and BMFaces if possible.
Uses good examples for BMFaces for intersected faces.
Still todo: good examples for BMEdges when partially reusing an edge,
and UV interpolation for new faces.
2020-07-23 07:46:53 -04:00
7c36c72b25 Merge branch 'master' into newboolean 2020-07-21 18:31:40 -04:00
77c83d3be1 Fixed the regression after making binary ops not do self-intersection.
Now the new Boolean code is only about 3 to 4 times slower than the
current BMesh one.
2020-07-20 11:58:37 -04:00
3b77c59bf7 Merge branch 'master' into newboolean 2020-07-20 08:15:06 -04:00
37ee7f20e7 Update integer type usage 2020-07-20 13:35:58 +02:00
44f58e0d96 Merge branch 'master' into newboolean 2020-07-20 13:34:29 +02:00
833514b2ce Work in progress to treat nary boolean differently.
This will make it faster. There's one bug in it still,
but committing progress.
2020-07-20 05:28:42 -04:00
62dc64bdee Better estimate of number of output faces.
Avoids need to resize some arena vectors in many cases.
2020-07-19 16:00:48 -04:00
383b4c0727 Added floating filters to the initial plane-side tests in tri-tri intersect.
Needed an "abs" function for double3, so added it to all of the
float/double/mpq 2/3 types.
2020-07-19 14:16:39 -04:00
41722bfaa6 Fix a strange merge problem, and fix a couple of warnings. 2020-07-18 19:58:41 -04:00
64e462f688 Merge branch 'master' into newboolean 2020-07-18 06:58:43 -04:00
49a15ac05a Merge master
commit aa8279648e
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 17 21:19:48 2020 +0200

    Simulation: extract node tree parsing code to separate file

commit 25582aef61
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 17 20:51:52 2020 +0200

    Simulation: separate code from node tree parsing and solver

commit 69d14c0ddb
Author: Hans Goudey <h.goudey@me.com>
Date:   Fri Jul 17 15:18:54 2020 -0400

    Fix T78959: Show current frame indicator when interface is locked

    When the playhead drawing moved to an overlay, a check was added to keep
    it from drawing with a locked interface. This is necessary for some overlays,
    but not this one, so this removes the check, making it the responsibility of
    the editor.

    A context function is added to make that check easier in the future.

    Differential Revision: https://developer.blender.org/D8313

commit 8b0df381d9
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Fri Jul 17 14:33:40 2020 -0300

    Transform: use GHASH_ITER when restoring customdata

commit d8a6eec1a3
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 17 16:00:08 2020 +0200

    Cleanup: Removed incorrect `// namespace DEG` comment

    No functional changes.

commit 893eb30730
Author: Sebastián Barschkis <sebbas@sebbas.org>
Date:   Fri Jul 17 16:11:21 2020 +0200

    Fluid: Numpy support for Mantaflow build system

    Adjusted the fluid build system so that plugins that depend on numpy can be compiled as well.

    Note that in this commit numpy support is still disabled. It can be enabled by re-running the Mantaflow update script with USE_NUMPY=1 and enabling WITH_MANTA_NUMPY in extern/mantaflow/CMakeLists.txt. This will happen in a future commit.

commit 0cdc75ccd2
Author: Sebastián Barschkis <sebbas@sebbas.org>
Date:   Fri Jul 17 15:58:13 2020 +0200

    Fluid: Cleanup build system for extern mantaflow

    No longer including unused dependencies. Should numpy IO be needed at some point, the Manta source update script can be configured so that the required dependencies are included again.

commit e3f8768d8a
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 17 14:23:57 2020 +0200

    Refactor: move ParticleFunction to separate file

commit 2679236047
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 17 14:15:06 2020 +0200

    Cleanup: avoid static initialization order issues when accessing CPPTypes

    Instead of depending on static initialization order of globals use
    static variables within functions. Those are initialized on first use.
    This is every so slighly less efficient, but avoids a full class of problems.

commit 3ef59121a4
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 17 13:47:57 2020 +0200

    Simulation: move initial simulation code from bf_blenkernel to bf_simulation

    I removed bf_blenkernel from `nodes/CMakeLists.txt` again (added it yesterday),
    because now this was causing me unresolved symbol errors... Without it, cmake
    seems to link the libraries bf_simulation, bf_blenkernel and bf_nodes in the right
    order. Not sure if that is just luck or if it is guaranteed.

    It was possible to fix the issue by using cmakes `LINK_INTERFACE_MULTIPLICITY`,
    but that is probably bad style.

commit 9582797d4b
Author: Jeroen Bakker <jbakker>
Date:   Fri Jul 17 13:47:10 2020 +0200

    Fix T77867: Link Duplicate Object crashes during batch creation

    When using link duplicated objects it could happen that one object is
    calculating the GPUBuffers and the second object is marking these
    buffers invalid. This introduces threading issues.

    This patch fixes this by combining the surface and surface per material
    batches. Most likely the surface per material batches are used and when
    requested you will most likely need the surface batch for the depth
    tests and overlays.

    During tests it slightly improves performance as batches aren't thrown
    away without using it.

    After this patch we can add a quick path for meshes with one material
    and two materials.

    Alternative approaches that have been checked:
    - sync extraction per object: reduced performance to much (-15%)
      ({D8292})
    - post checks: reduced the threading issues, but didn't solve it.
    - separating preparation and execution of the extraction ({D8312})

    Reviewed By: Clément Foucault

    Differential Revision: https://developer.blender.org/D8329

commit bf2bb6db26
Author: Ankit Meel <ankitjmeel@gmail.com>
Date:   Fri Jul 17 12:50:08 2020 +0530

    Cleanup: silence unused variable warning

    Reviewed By: fclem

    Differential Revision: https://developer.blender.org/D8328

commit 0e3d34e48f
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 17 12:38:15 2020 +0200

    BLI: add StringRefNull.c_str() method

    This should be used whenever you rely on the fact, that the
    returned pointer points to the beginning of a null-terminated array.

commit 0fcd23a388
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 17 12:28:09 2020 +0200

    Simulation: use better api for adding and removing simulation states

commit c5f61fbf48
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 17 11:29:46 2020 +0200

    Cleanup: avoid warning about redundant access specifier

    No functional changes.

commit 5910dbdbf7
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 17 11:36:59 2020 +0200

    Nodes: move some code from blenkernel directory to nodes

    This also introduces the `blender::nodes` namespace. Eventually,
    we want to move most/all of the node implementation files into
    this namespace.

    The reason for this file-move is that the code fits much better
    into the `nodes` directory than in the `blenkernel` directory.

commit 0a40c671b0
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 17 17:11:32 2020 +1000

    Cleanup: consistent ordering for scene argument to UV functions

commit 83e204702d
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Thu Jul 16 23:50:33 2020 +1000

    Cleanup: remove f-string use in favor of percentage for formatting

commit 618f31312c
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 17 17:35:46 2020 +1000

    Fix vertex selection error from recent refactor

    Temporary fix for regression in 8084b7e6e2.

commit 89a7a1c156
Author: Jeroen Bakker <jeroen@blender.org>
Date:   Fri Jul 17 08:31:03 2020 +0200

    Cleanup: extract draw cache sanity checks to own function

commit 608d9b5aa1
Author: Hans Goudey <h.goudey@me.com>
Date:   Thu Jul 16 14:07:47 2020 -0400

    UI: Add shortcuts for constraint panels

    Only the delete shortcut applies here, although the move up and down
    operators can optionally be assigned in the keymap.

    See rB1fa40c9f8a81 for more details and rB5d2005cbb54b for the
    grease pencil modifier panel implementation, which is the same.
    Some refactoring of the constraint delete operator was necessary,
    including adding an invoke function.

    Differential Revision: https://developer.blender.org/D8238

commit b13bbb22e4
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 16 19:52:28 2020 +0200

    Fix link error in bf_nodes

    I got undefined reference errors on the `NodeMFNetworkBuilder::get_default_fn`
    function under some circumstances. This symbol is definitely defined in bf_blenkernel.
    The error seemed a bit undeterministic and was probably caused by some incorrect
    link order. I don't get the error with this change.

commit 02a3720000
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 16 18:49:26 2020 +0200

    Simulation: rename bf_physics to bf_simulation

    Also see {rB9363c4de0635394548fa2eb8d205581313029775}.

commit 93f21ebb13
Author: Sebastián Barschkis <sebbas@sebbas.org>
Date:   Thu Jul 16 18:01:08 2020 +0200

    Fluid: Update Mantaflow source files

    Includes cleanup that resolves a -Wunused-but-set-variable warning.

commit e7c1a32a78
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Thu Jul 16 17:22:58 2020 +0200

    Tests: disable ASAN when discovering tests

    CMake, when it's configuring the project, runs the `blender_test` test
    runner (if it exists from a previous build) to discover which tests it
    contains. At this time none of the tests themselves are run, so it's not
    that useful to run ASAN and have it break things when there are memory
    leaks.

    This commit disables ASAN by injecting `ASAN_OPTIONS="detect_leaks=0"` in
    the environment variables.

    It is not enough to use `set(ENV{ASAN_OPTIONS} "detect_leaks=0")` in
    `tests/gtests/runner/CMakeLists.txt`, as it wouldn't be passed to the child
    process.

commit a138bf57c9
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Thu Jul 16 16:10:53 2020 +0200

    Tests: move tests from USD test directory into `io/common` and `io/usd`

    This commit is a followup of {D7649}, and ports the USD tests to the new
    testing approach. It moves test code from `tests/gtests/usd` into
    `source/blender/io/common` and `source/blender/io/usd`, and adjusts the
    use of namespaces to be consistent with the other tests.

    I decided to put one test into `io/usd/tests`, instead of
    `io/usd/intern`. The reason is that this test does not correspond with a
    single file in that directory; instead, it tests Blender's integration
    with the USD library itself.

    There are two new CLI arguments for the Big Test Runner:

    - `--test-assets-dir`, which points to the `lib/tests` directory in the
      SVN repository. This allows unit tests to find test assets.
    - `--test-release-dir`, which points to `bin/{BLENDER_VERSION}` in the
      build directory. At the moment this is only used by the USD test.

    The CLI arguments are automatically passed to the Big Test Runner when
    using `ctest`. When manually running the tests, the arguments are only
    required when there is a test run that needs them.

    For more info about splitting some code into 'common', see
    rB084c5d6c7e2cf8.

    No functional changes to the tests themselves, only to the way they are
    built & run.

    Differential Revision: https://developer.blender.org/D8314

    Reviewed by: brecht, mont29

commit 09a483a3aa
Author: Francesco Siddi <fsiddi>
Date:   Thu Jul 16 17:10:15 2020 +0200

    macOS: improve design of .dmg background

    Differential Revision: https://developer.blender.org/D8300

commit 671c6d8afd
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Thu Jul 16 04:32:09 2020 +0200

    Cleanup: Gizmo: Remove non matched glDisable

    We use the polyline shader for drawing the rotation gizmo now.
    This shader supports clipping without hardware clip planes.

commit 07d70a76df
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Thu Jul 16 04:31:29 2020 +0200

    Cleanup: WM: Use GPUTexture API instead of raw ogl calls

commit 5099cbeec9
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Thu Jul 16 04:16:10 2020 +0200

    Cleanup: GPU: Move depth/color masks functions to GPU_state

commit 436d38bb54
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Thu Jul 16 03:31:25 2020 +0200

    Cleanup: GPU: Move XOR logic op to gpu_state.c

commit 3481f6eaf2
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Thu Jul 16 03:12:21 2020 +0200

    Cleanup: GPU: Remove GL_DITHER usage

commit 71ac137662
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Thu Jul 16 03:01:07 2020 +0200

    Cleanup: GPU: Move quad buffer stereo check to GPU module

commit 8084b7e6e2
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Thu Jul 16 02:50:55 2020 +0200

    Cleanup: GPU: Replace all glReadPixels by GPU equivalent

commit ab19abe223
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Thu Jul 16 02:06:25 2020 +0200

    Cleanup: Port glClear calls to GPU module functions

commit bc85081156
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Thu Jul 16 01:20:25 2020 +0200

    Cleanup: DRW: remove uneeded double bind

    Now that binds are permanent there is no need to setup the same
    texture for each subgroups.

commit 56b8adb9e2
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 16 16:41:36 2020 +0200

    Particles: avoid crash when connected unimplemented node

commit 1494ad20b9
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 16 16:33:20 2020 +0200

    Particles: add implicit covnersions between Vector and Color

    Not sure if these conversions are a good idea. However, we have them
    in Cycles, so they be available in the simulation node tree for consistency
    reasons.

commit 76bf050853
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 16 16:29:05 2020 +0200

    Particles: simplify adding new implicit conversions between sockets

commit aa547ce88b
Author: Sebastián Barschkis <sebbas@sebbas.org>
Date:   Thu Jul 16 16:39:14 2020 +0200

    Fluid: Update Mantaflow source files

    Refactored various functions after noticing new warnings when compiling on Apple DTK devices - there should now be fewer warnings when building.

commit f64710a518
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 16 16:09:09 2020 +0200

    Particles: change initial velocity of particles

    This is only temporary, but makes testing the system a bit easier.

commit 4249d6f58e
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 16 16:08:18 2020 +0200

    Particles: support Separate/Combine RGB nodes

commit ada173ebfd
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 16 15:54:18 2020 +0200

    Particles: simplify Combine XYZ node

commit 72df7c23c4
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 16 15:49:56 2020 +0200

    Particles: support Color Ramp node

commit c7aa0f9d74
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Thu Jul 16 14:54:45 2020 +0200

    Fix T78537: too much memory usage rendering animation with persistent images

    For still images, always return 0 for the current frame number. This ensures
    Cycles can detects that the image did not change.

    Based on patch by Vincent Blankfield.

    Differential Revision: https://developer.blender.org/D8242

commit 279cc34343
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Thu Jul 16 23:44:38 2020 +1000

    Keymap: disable 'Alt' click for tools prompt by default

    Based on feedback from artists in the Blender Studio this is too
    easy to access by accident.

    This is still accessible as a preference.

commit 83955d6769
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 16 13:25:57 2020 +0200

    Particles: support Map Range node

    Only linear interpolation mode is supported for now.

commit 99fda4d31e
Author: Ray Molenkamp <github@lazydodo.com>
Date:   Thu Jul 16 07:22:52 2020 -0600

    deps builder: Fix typo in windows harvesting

commit 9b6088cb9d
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 16 14:37:21 2020 +0200

    Simulation: Change BPH prefix to SIM

    In a previous commit the `physics` folder has been renamed to `simulation`.
    This commit updates the function/file prefix accordingly.

commit 9363c4de06
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 16 14:27:47 2020 +0200

    Simulation: Rename `physics` directory to `simulation`

    Function names will be updated in a separate commit.

    This will be the place for the new particle system and other
    code related to the Simulation data block. We don't want
    to have all that code in blenkernel.

    Approved by brecht.

commit 66b48ad8fb
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Thu Jul 16 12:47:28 2020 +0200

    Fix git tag warning when running make update after recent changes

commit f3ea6a5b28
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 16 14:15:12 2020 +0200

    Particles: implement more vector math operations

commit 3d8f8085fb
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Thu Jul 16 18:53:41 2020 +1000

    UI: show connected icon for proportional editing in the image space

commit b882f89fe3
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 16 13:41:47 2020 +0200

    Particles: support for most math node operations

commit 2ddb3dc617
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 16 13:38:23 2020 +0200

    Nodes: support default function for partially implemented nodes

commit 56aa5b0d8c
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Thu Jul 16 12:58:49 2020 +0200

    T73268: Link C/C++ unit tests into single executable

    This commit introduces a new way to build unit tests. It is now possible
    for each module to generate its own test library. The tests in these
    libraries are then bundled into a single executable.

    The test executable can be run with `ctest`. Even though the tests
    reside in a single executable, they are still exposed as individual
    tests to `ctest`, and thus can be selected via its `-R` argument.

    Not yet ported tests still build & run as before.

    The following rules apply:

    - Test code should reside in the same directory as the code under test.
    - Tests that target functionality in `somefile.{c,cc}` should reside in
      `somefile_test.cc`.
    - The namespace for tests is the `tests` sub-namespace of the code under
      test. For example, tests for `blender::bke` should be in
      `blender::bke:tests`.
    - The test files should be listed in the module's `CMakeLists.txt` in a
      `blender_add_test_lib()` call. See the `blenkernel` module for an
      example.

    Reviewed By: brecht

    Differential Revision: https://developer.blender.org/D7649

commit 065a00ee3e
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Tue Jul 14 16:31:54 2020 +0200

    Fix T78920: missing depsgraph relation when using sound strips in VSE

    Having a sound strip in the VSE caused a missing relation error to be
    logged on the console. This was caused by the AUDIO depsgraph component
    not having an entry node. This commits adds that node, and sets up
    relations correctly.

    Differential Revision: https://developer.blender.org/D8290

    Reviewed By: Sergey

commit d4ce777aed
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 16 11:33:35 2020 +0200

    BLI: move inline include to the bottom to avoid redeclaration warning

commit d897228682
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 16 11:28:31 2020 +0200

    BLI: move safe math functions to separate header

commit f6f93b5b12
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 16 11:05:13 2020 +0200

    BLI: add safe_divide, safe_modf and safe_logf

    Those are defined exactly as their corresponding functions in Cycles.

commit 7e0bf7a0f1
Author: Bastien Montagne <bastien@blender.org>
Date:   Thu Jul 16 11:03:11 2020 +0200

    LibOverride: Fix getting proper RNA path and ID from embedded ones.

    Master collections and root node trees should now be working as expected
    in that regard.

commit 35bfe1702c
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 16 10:46:18 2020 +0200

    BLI: add safe_powf function

    The same function is also used by cycles.

commit 4a9d903e2b
Author: Yevgeny Makarov <jenkm>
Date:   Thu Jul 16 18:06:51 2020 +1000

    Fix View3D "Mirror" menu, both "Global" and "Local" items are GLOBAL

commit 9715ad5aca
Author: Stefan Werner <stewreo@gmail.com>
Date:   Thu Jul 16 09:25:55 2020 +0200

    macOS: Support arm64 architecture.

    Enabling all `make deps` dependencies with the exception of Embree and OIDN.
    After that, Blender can be compiled on an Apple Silicon Mac just like on any
    Intel based Mac. There are still compiler warnings that need to be
    investigated and there are probably a couple of bug still to be discovered
    and to be fixed.

    Most patches to the dependencies are simple and are about disabling SSE and
    setting the proper architecture to compiile for. Notable exception is Python,
    where I back ported a yet to be accepted PR for upstream Python:
    https://github.com/python/cpython/pull/21249

    Cross compiling or buliding a Universal Binary is not supported yet.
    The minimum macOS target version for x86_64 remains at 10.13, the target
    for arm64 is 11.00.

    Differential Revision: https://developer.blender.org/D8236

commit ad4928a171
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Thu Jul 16 17:00:16 2020 +1000

    UI: avoid aligning labels for ui_item_with_label

    Key-map display was doing thousands of redundant alignment operations.
    Set the spacing instead as align was only set to use zero spacing.

    This would have prevented the crash reported by T78636.

commit 75520894c7
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Thu Jul 16 16:32:55 2020 +1000

    Fix T78636: Crash displaying many aligned buttons

    Displaying user preferences search crashed on macOS when the search
    contained a common character such as 'E'.
    This caused alignment to 'alloca' too much memory.

    Replace with a heap allocation fallback.

commit 2811de6e5c
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Thu Jul 16 13:48:01 2020 +1000

    Cleanup: fix building without USE_UIBUT_SPATIAL_ALIGN defined

commit 5b099a25d7
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Thu Jul 16 13:27:50 2020 +1000

    Fix T78966: Center cursor doesn't refresh the UI

commit 123e29c274
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Thu Jul 16 13:17:31 2020 +1000

    Cleanup: missing CMake headers from source lists

commit 54abab53bf
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Thu Jul 16 11:07:36 2020 +1000

    Cleanup: undeclared function warning, unused argument

commit a3d90337b8
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Thu Jul 16 10:58:33 2020 +1000

    Cleanup: spelling

commit d11a2dfe71
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Thu Jul 16 10:44:37 2020 +1000

    Cleanup: minor change to grease pencil material access

    Rename for clarity and avoid passing in the prefix length.

commit 75a09ba2ed
Author: Richard Antalik <richardantalik@gmail.com>
Date:   Thu Jul 16 02:24:37 2020 +0200

    Fix T78837: Prefetching can corrupt .blend files

    This happened because of typo in seq_dupli() when duplicating effect data.
    Instead of duplicating data to new sequence, it was duplicated into original.

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8295

commit 974e36d7d0
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Wed Jul 15 21:05:50 2020 +0200

    Fix T78647 UVEdit: Crash when entering edit mode with UV Editor open

    Only affects MacOS.

commit 058514aa0a
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Wed Jul 15 20:10:45 2020 +0200

    PointCloud: Initial rendering support for Workbench

    Also includes outline overlays. Removes the temp overlay drawing

    We make the geometry follow camera like billboards this uses less
    geometry. Currently we use half octahedron for now. Goal would be
    to use icospheres.

    This patch also optimize the case when pointcloud has uniform radius.
    However we should premultiply the radius prop by the default radius
    beforehand to avoid a multiplication on CPU.

    Using geometry instead of pseudo raytraced spheres is more scalable as
    we can render as low as 1 or 2 triangle to a full half sphere and can
    integrate easily in the render pipeline using a low amount of code.

    Reviewed By: brecht

    Differential Revision: https://developer.blender.org/D8301

commit d4d810f817
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Mon Jul 6 21:15:36 2020 +0200

    Cleanup: EEVEE: Remove concentric samples.

commit 37a8c6d809
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Mon Jul 6 21:06:16 2020 +0200

    Cleanup: EEVEE: Remove unused IRRADIANCE_CUBEMAP

commit 47885abbe6
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Wed Jul 15 16:41:30 2020 +0200

    Workbench: Replace viewvecs caculation by DRWView

commit cd8f3c9ee7
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Wed Jul 15 16:38:44 2020 +0200

    DRW: Add glsl math libraries

    Copied from eevee bsdf_common_lib.glsl

commit 2c1edcf3ef
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Wed Jul 15 15:01:59 2020 +0200

    EEVEE: Fix undefined behavior in world output

commit 24c846b2b4
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Wed Jul 15 14:59:52 2020 +0200

    GPU: Shader: Move IN_OUT define to shader GPU_shader_create_ex

    This adds the opportunity to use it in multiple places.

commit 987d14a3b2
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Wed Jul 15 14:40:28 2020 +0200

    DRW: Shader: Fix const correctness and print better debug output

commit 8e16873086
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Wed Jul 15 14:39:29 2020 +0200

    DRW: Shader: Add DRW_shader_create(_fullscreen)_with_shaderlib

    Some convenience function for using DRWShaderLibrary.

commit 5dcf60e053
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Wed Jul 15 14:35:57 2020 +0200

    DRW: View: Add ViewVecs calculation

    This will remove some code duplication between draw engines.

commit f1104c2828
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Wed Jul 15 18:52:01 2020 +0200

    Fix T78369: Sculpt Vertex Colors not rendering in EEVEE

    The vertex colors node was using the M_COL attribute type but Sculpt
    Vertex Colors use CD_PROP_COLOR
    Now the Vertex Color node also fallbacks to legacy vertex colors if
    Scultp Vertex Colors are not enabled as experimental.

    Reviewed By: brecht

    Maniphest Tasks: T78369

    Differential Revision: https://developer.blender.org/D8185

commit eb54624a9a
Author: Bastien Montagne <bastien@blender.org>
Date:   Wed Jul 15 18:10:55 2020 +0200

    LibOverride: make outliner's 'override hierarchy' use same logic as 3DView operator.

    So now one can create a 'full', 'complete' override of a character from
    the outliner as well.

commit 5057b28a2f
Author: Bastien Montagne <bastien@blender.org>
Date:   Wed Jul 15 18:09:30 2020 +0200

    LibOverride: move most of 'complete override creation' from ED_object to BKE_lib_override.

    This code is fairly complex and can be used in more places, better not
    duplicate that logic and just have it in BKE area.

commit ba100c883c
Author: Bastien Montagne <bastien@blender.org>
Date:   Wed Jul 15 18:07:56 2020 +0200

    BKE collection: add util to add a collection using another collection as 'template'.

    Similar to what we already had using an object as 'template'.

commit a082e49671
Author: Bastien Montagne <bastien@blender.org>
Date:   Wed Jul 15 15:51:13 2020 +0200

    Cleanup: remove debug prints.

commit cda6da4957
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 15 18:14:03 2020 +0200

    Fix error in recent commit

    Obviously a copy paste error of mine...

commit ae4098e234
Author: Antonio Vazquez <blendergit@gmail.com>
Date:   Wed Jul 15 17:25:07 2020 +0200

    GPencil: Fix unreported error baking mesh animation

    When the mesh is linked, the materials can not be available or be the same assigned to mesh. Now, if the mesh is linked, a simple two materials conversion is used.

    To get the full list of materials, the mesh must not be linked.

    Also checked some indexes to be sure never get a wrong value and that materials are not created again and again.

commit 36e836d0e9
Author: Sebastián Barschkis <sebbas@sebbas.org>
Date:   Wed Jul 15 17:03:51 2020 +0200

    Fluid: Adjusted Mantaflow version number

    Version number was increased after recent OpenVDB IO changes.

commit 19d17b217a
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 15 16:48:30 2020 +0200

    Particles: use CD_PROP_FLOAT3 instead of CD_LOCATION

    `CD_LOCATION` was only used temporarily due to the lack
    of a better alternative. This also removes the name from
    `CD_LOCATION` again, because at most one layer of this
    type should exist.

commit 57ec1f37e9
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 15 16:42:17 2020 +0200

    CustomData: add float2 and float3 data types

    This adds `CD_PROP_FLOAT2` and `CD_PROP_FLOAT3`.

    Reviewers: brecht

    Differential Revision: https://developer.blender.org/D8251

commit e06a346458
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Wed Jul 15 16:24:03 2020 +0200

    Fix T78747: Fix mesh boundary detection and automasking

    This issue was produced by a hack in the sculpt mode code from 2.80
     when the sculpt API for connectivity info was not available.
    The smooth brush was the only brush that needed connectivity info,
    so there were 3 different smooth functions with the connectivity
    queries implemented for dyntopo, meshes and grids. The mesh version
    of smoothing was checking the number of connected faces to a vertex
    to mask the mesh boundaries, which was not covering all cases and
    was hardcoded in the smooth function itself.

    This patch removes all those legacy functions and unifies all
    smooth functions into a single one using the new API and the
    automasking system. In order to achieve this, there were needed
    some extra changes:

    - The smooth brush now does not automasks the boundaries by default,
    so its default preset needs to be updated to enable automasking

    - The mesh boundary info is extracted once and cached in a
    bitmap, similar to the disconnected elements IDs. This makes
    boundary detection work as expected in all cases, solving a lot
    of known issues with the smooth brush. In multires, this info is
    extracted and cached only at the base mesh level, so it is much
    more memory efficient than the previous automasking system.

    - In order to keep the brushes responsive as they were before,
    the automasking system can now skip creating the cache when it
    is not needed for the requested options. This means that for
    high poly meshes and simple automasking options the brushes
    won't lag on start.

    Reviewed By: sergey

    Maniphest Tasks: T78747

    Differential Revision: https://developer.blender.org/D8260

commit 10cacbbb15
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Tue Jul 14 23:15:13 2020 +0200

    Fix T77417: Topology Automasking not working with individual vertices

    The flood fill operation was setting the mask using to_v, so in the first
    iteration when the floodfill callback was using the active vertex as
    from_v and any other neighbor as to_v, the mask for the active vertex
    was never set.

    Now the mask is set using from_v and it checks if it should continue
    propagating to the next neighbor using to_v.

    Reviewed By: sergey

    Maniphest Tasks: T77417

    Differential Revision: https://developer.blender.org/D8294

commit 613d314251
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Wed Jul 15 17:35:57 2020 +1000

    UV: support region fill for path select

    This matches edit-mesh region selection (Ctrl-Shift-Select).

commit b3c34011c0
Author: Hans Goudey <h.goudey@me.com>
Date:   Wed Jul 15 09:11:01 2020 -0400

    Cleanup: Replace 0 with False for boolean argument

commit efc6f6e1ae
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 15 14:23:51 2020 +0200

    Clang-Tidy: ignore some newer checks

    Those checks have been added to clang tidy within the last year.
    They fail when I use a clang tidy version I built from source.

    Reviewers: sergey

    Differential Revision: https://developer.blender.org/D8302

commit 5a11c8ba24
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Wed Jul 15 21:48:28 2020 +1000

    Fix T68845: Follow Active Quads, divide by zero error

commit 87f8949f0e
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Wed Jul 15 13:37:13 2020 +0200

    Fix T78930: Cycles OpenCL error on graphics cards that don't support half float

commit 44bb73e765
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Wed Jul 15 08:10:41 2020 -0300

    Revert "Cleanup: simplify Weld Modifier logic"

    This reverts commit 98b1a716d6.

    That commit broke a few modifiers.py tests
    (Screw+Weld and a weld merge threshold).

    And some pairs may be lost in the first loop.

commit ff2fa59689
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 15 12:45:40 2020 +0200

    Fix T76690: Incorrect liquid particle count displayed

    Reviewers: sergey, sebbas

    Differential Revision: https://developer.blender.org/D7852

commit 4e8fc14120
Author: Antonio Vazquez <blendergit@gmail.com>
Date:   Wed Jul 15 12:47:45 2020 +0200

    GPencil: Fix name typo error

commit 7e2ffbfb25
Author: Sebastian Parborg <darkdefende@gmail.com>
Date:   Wed Jul 15 12:36:48 2020 +0200

    Add missing NULL assignment to D8293

    Missed reseting "next_td" in that patch.
    Shouldn't have caused any issues in practice, but it is nice to be
    extra clear and safe in the code.

commit 50c6448781
Author: Sebastian Parborg <darkdefende@gmail.com>
Date:   Wed Jul 15 12:28:32 2020 +0200

    Fix T78909: Curve-edit proportional connected-only broken

    Now it calculates the actual distance when traveling along the curve.

    I addition to this, it also now supports cyclic curves.

    Reviewed By: Campbell

    Differential Revision: http://developer.blender.org/D8293

commit e8b26a0501
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 15 11:06:37 2020 +0200

    Fix signed/unsigned comparison

commit 680a81fc49
Author: Bastien Montagne <bastien@blender.org>
Date:   Wed Jul 15 10:58:54 2020 +0200

    LibOverride: rework 'make override' 3DView operator.

    Removed the 'select main object to override' menu when overriding an
    instanced collection, this was no more used anyway.

    Added new behavior allowing to select which directly linked collection
    to override when trying to override an inderctly linked object. This
    allows to link collections without instancing them with an empty object,
    select one of their objects, and call override operator.

commit eb87b1c8f6
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Wed Jul 15 15:37:03 2020 +1000

    Cleanup: remove assignment from a NULL struct

    Quiet ASAN 'member access within null pointer' warning.

    While this doesn't crash, access to 'shading'
    without checking if the 'v3d' would have.

commit 920b138f83
Author: Liam Scaife <Voltist>
Date:   Wed Jul 15 15:19:21 2020 +1000

    UI: Add manifold extrude to extrude menu

commit e062def3b4
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Wed Jul 15 13:11:22 2020 +1000

    Cleanup: spelling

commit 061d76f55c
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Wed Jul 15 13:09:06 2020 +1000

    Revert "Cleanup: remove public unused function."

    This reverts commit 03c8b048a1.

    This commit re-introduced T76837.

    While there is a comment explaining why this function is needed,
    the naming of the poll function does make this confusing.
    The API could be changed to avoid confusion here.

commit d493fc43bd
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Tue Jul 14 17:45:31 2020 -0300

    Fix T78875: Numerical display of delta of translation is not updating in 3d view

commit 7f67e3200a
Author: Sebastián Barschkis <sebbas@sebbas.org>
Date:   Tue Jul 14 22:16:43 2020 +0200

    Fluid: Fix liquid mesh scaling

    Fixes issue with .bobj.gz and .obj mesh files not always being scaled correctly in the viewport.

commit 7e0289b618
Author: Sebastián Barschkis <sebbas@sebbas.org>
Date:   Tue Jul 14 22:15:00 2020 +0200

    Fluid: Updated Mantaflow source files

    New files include fixes for obj mesh import and minor cleanups.

commit 98b1a716d6
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Tue Jul 14 15:18:03 2020 -0300

    Cleanup: simplify Weld Modifier logic

    The original code to rearrange the weld vertices map was confusing.

    It traverses the overlap result multiple times within a loop.

    This part of the code has therefore been rethought, simplified and commented.

    This also results in a slight improvement in the performance of the modifier.

commit dbcc74f801
Author: Sebastián Barschkis <sebbas@sebbas.org>
Date:   Tue Jul 14 18:11:28 2020 +0200

    Fix T77263: Mantaflow: Cache gets deleted at changing upres factor under Particles section.

    Moved fluid simulation reset to separate functions based on type.

commit 0b100e21fb
Author: Jeroen Bakker <j.bakker@atmind.nl>
Date:   Mon Jul 13 14:19:13 2020 +0200

    Fix T78704: RenderPass normals disapear when view isn't updated

    When the view isn't updated the renderpass thought that it was rendering
    the next sample, skipping the conversion from encoded to blender
    normals.

    This patch resets the current sample when only rendering single sample
    layers.

    Reviewed By: Clément Foucault

    Differential Revision: https://developer.blender.org/D8280

commit 6cc88e330b
Author: Jeroen Bakker <j.bakker@atmind.nl>
Date:   Mon Jul 6 08:41:28 2020 +0200

    Fix T78431: Update mesh_cd_layers_type_ to support 8 bytes.

    Sculpt vertex colors changed the `DRW_MeshCDMask` from 4 bytes to 8 bytes, but
    the functions assumed it still was 4 bytes. This patch updates the functions and
    adds a compile time check.

    Reviewed By: Clément Foucault

    Differential Revision: https://developer.blender.org/D8215

commit 2ba1cf4b40
Author: Sebastian Parborg <darkdefende@gmail.com>
Date:   Tue Jul 14 17:26:13 2020 +0200

    Fix T78880: UV Editor - Match prop edit connected behavior with mesh editing and fix Rip Region double proportional checkbox

    This fixes the double prop edit checkbox in the redo menu.

    This also makes it so that proportional edit in connected mode now
    matches how it behaves in mesh edit mode.

    Without this change, ripping in UV edit mode with proportional edit on
    would be useless as the UV verts you ripped will still be stuck together
    even if they were not connected anymore.

    Reviewed By: Campbell

    Differential Revision: http://developer.blender.org/D8289

commit 797027be6b
Author: Sebastián Barschkis <sebbas@sebbas.org>
Date:   Tue Jul 14 16:30:01 2020 +0200

    Fluid: Fix missing flag update for cache

    These flags need to be set correctly in order to distinguish between data that comes from cache files and raw data that comes directly from pointers to the data in Mantaflow.

commit 14eaa9ed63
Author: Bastien Montagne <bastien@blender.org>
Date:   Tue Jul 14 16:03:12 2020 +0200

    LibOverride: fix for removing `use_override_library` in rB3d587efef2872.

    Thanks to @JacquesLucke for the heads up.

commit 8e9dd5492a
Author: Antonio Vazquez <blendergit@gmail.com>
Date:   Tue Jul 14 15:59:40 2020 +0200

    Gpencil: Simplify modifier sample mode minimal vert count fix.

    For this mode is possible use strokes of 2 points.

    Differential revision: https://developer.blender.org/D8138

commit c8a62e4f50
Author: Bastien Montagne <bastien@blender.org>
Date:   Tue Jul 14 15:27:41 2020 +0200

    Cleanup: function name not following its module conventions.

commit 6068f49c33
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 14 15:20:44 2020 +0200

    BLI: remove static assert noexcept move constructors

    The move constructor of `mpq_class` from GMP currently
    allocates when it is moved. So, it cannot be noexcept.
    Since we want to use this type, this static assert cannot
    stay there.

commit 2e8a78f4d1
Author: Kévin Dietrich <kevin.dietrich@mailoo.org>
Date:   Mon Jul 13 18:26:48 2020 +0200

    Fluid bake: fix memory leak when path validation fails

    Reviewed By: sebbas

    Differential Revision: https://developer.blender.org/D8284

commit 78148e20fa
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Tue Jul 14 22:47:18 2020 +1000

    Cleanup: remove tab indention

commit fa7ace2215
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Tue Jul 14 22:45:33 2020 +1000

    PyAPI: support element multiplication for vector, matrix, quaternions

    This was disabled during 2.8x for smooth porting of 2.7x scripts,

    Now '@' is used for matrix multiplication,
    support '*' to multiple vector elements.

    See T56276.

commit e3fd60b182
Author: Bastien Montagne <bastien@blender.org>
Date:   Tue Jul 14 14:49:59 2020 +0200

    LibOverride: Outliner: Add an operation to override the selected ID and its parents.

    This will override all linked data-blocks in the tree branch leading to
    the selected one.

commit 140b26909e
Author: Bastien Montagne <bastien@blender.org>
Date:   Tue Jul 14 11:38:25 2020 +0200

    LibOverride: Move code tagging reauired dependencies of an override into BKE.

    This is fairly generic code that can be re-used in other places.

commit 1e5ce39156
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Tue Jul 14 09:30:54 2020 -0300

    Fix T78900: Single vertex sliding crashes

    As we can see in `initVertSlide_ex`, `sld` can be `NULL`.
    `sld` is dereferenced, but can still be `NULL`.

commit 01ec76842f
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 14 13:47:32 2020 +0200

    Fix T77766: support animated global gravity toggle

    Reviewers: sebbas

    Differential Revision: https://developer.blender.org/D8281

commit 4096330b81
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 14 13:01:46 2020 +0200

    Cleanup: typo

commit 25fc84bf2e
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Tue Jul 14 10:42:35 2020 +0200

    Fix wrong vector size functions used in knife tool

    Should not use copy_v3_v3 on a 2 element vectors.

commit 26793d619c
Author: Antonio Vazquez <blendergit@gmail.com>
Date:   Tue Jul 14 10:26:19 2020 +0200

    GPencil: Cleanup Build modifier and fix potential div by zero errors

commit 0fb08b7cc4
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Tue Jul 14 16:04:18 2020 +1000

    Cleanup: sort header, cmake paths

commit 93e14e5935
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Tue Jul 14 15:53:56 2020 +1000

    Fix T78883: New bezier curve points to uninitialized memory

commit 5338b36fcc
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Tue Jul 14 15:19:52 2020 +1000

    Cleanup: spelling

commit b818f6b55f
Author: Hans Goudey <h.goudey@me.com>
Date:   Mon Jul 13 20:10:49 2020 -0400

    Fix T78902: Only check main modifier panel for expansion property

    Internally the "show_expanded" property stores the expansion for every
    subpanel, but for RNA we should only check the first bit of the flag that
    corresponds to the main panel.

commit 0b24930541
Author: Hans Goudey <h.goudey@me.com>
Date:   Mon Jul 13 17:16:01 2020 -0400

    UI: Add missing row in curve profile template

commit 37fb586a0b
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Mon Jul 13 16:10:45 2020 -0300

    Cleanup: remove unnecessary member

    `Kfv-> sco` was being treated as a local variable, and can be
    confusing since this value is not updated when navigating the viewport.

commit 70992ae270
Author: Ray Molenkamp <github@lazydodo.com>
Date:   Mon Jul 13 12:29:53 2020 -0600

    Fix: Fix build error with MSVC in BLI_span_test

    span.size() returns an uint, causing a signed/unsigned comparison
    using 3u sidesteps the issue

commit 6e74a8b69f
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Mon Jul 13 16:45:15 2020 +0200

    Fix T78881: Cycles OpenImageDenoise not using albedo and normal correctly

    Properly normalize buffers now. Also expose option to not use albedo and normal
    just like OptiX.

commit 2b5e21fe00
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Sat Jul 11 00:19:45 2020 +0200

    Sculpt: Add extra deform types to Smear

    The smear brush was using the stroke direction to slide colors across
    the mesh surface (this is called drag in other sculpt tools). Similarly,
    other deformations can be included. The most common ones in image
    editing are pinch and expand, which can be used to sharpen transitions
    between colors.

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8270

commit 1076952209
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Fri Jul 10 23:00:21 2020 +0200

    Fix wrong variable name in Sculpt Vertex Colors experimental check

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8269

commit eb3f74a0fe
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Fri Jul 10 19:43:01 2020 +0200

    Sculpt: Enable color palettes for sculpt vertex colors

    Enables the color palette subpanel for brushes that have color
    capabilities (only the paint brush for now)

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8268

commit 8dd2386a68
Author: Bastien Montagne <bastien@blender.org>
Date:   Mon Jul 13 17:43:22 2020 +0200

    IDTemplate: Minor tweak to 'make local/override' code.

    Only update pointer of the template if we actually changed it...

commit fcc91faf3f
Author: Bastien Montagne <bastien@blender.org>
Date:   Mon Jul 13 17:02:58 2020 +0200

    Fix (unreported) bad handling of undo for some IDTemplates operations.

commit 91e67c7bda
Author: Jacques Lucke <jacques@blender.org>
Date:   Mon Jul 13 16:55:39 2020 +0200

    Cleanup: remove some incorrectly placed consts

    Clang-tidy reported that those parameters could be const,
    but that is not true on windows.

commit 3d587efef2
Author: Bastien Montagne <bastien@blender.org>
Date:   Mon Jul 13 16:44:41 2020 +0200

    LibOverride: Cleanup: Remove option to disable library overrides.

    Code is mature enough now to not need this anymore, people who do not
    want to use liboverrides can just not create them.

commit 5c8dd2a703
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Mon Jul 13 11:40:14 2020 -0300

    Cleanup: silence warnings

commit 3dcc7c73e2
Author: Ray Molenkamp <github@lazydodo.com>
Date:   Mon Jul 13 08:38:31 2020 -0600

    MSVC: Fix build error with the 8.1 SDK

    shobjidl_core.h only exists in the windows 10 SDK in the 8.1
    SDK ShObjIdl.h will have the definitions we need, which still
    exists in the 10 SDK and implicitly includes shobjidl_core.h.

    so ShObjIdl.h will work on both SDK versions.

commit 29da019cb3
Author: Szymon Ulatowski <szulat>
Date:   Mon Jul 13 17:02:19 2020 +0200

    EEVEE: Fix sky zenith bug

    Careless use of acos() in spherical coordinates transformation was
    deteriorating the precision near zenith (and nadir) and producing
    glitchy pixels (best seen in longer focal lengths).

    Reviewed By: fclem

    Differential Revision: https://developer.blender.org/D8266

commit 16989c4d1d
Author: Bastien Montagne <bastien@blender.org>
Date:   Mon Jul 13 16:15:52 2020 +0200

    Fix T78037: fresh install of blender 2.83.0 not able to save user startup file.

    Simply remove that check ob userdef's themes, we are never read any
    userdef from startup file anymore, so this check makes no more sense.

    To be backported to 2.83.

commit 952279a366
Author: Sebastián Barschkis <sebbas@sebbas.org>
Date:   Mon Jul 13 16:09:24 2020 +0200

    Fix T76687: [Mantaflow] low domain transformation performance

    Implemented G.moving suggestion from comments.

commit 5ecefc6a07
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Mon Jul 13 15:42:47 2020 +0200

    Build: make update support for git tags

    Previously it only picked the appropriate version with the
    blender-vX.XX-release branches.

commit 2be7a11e43
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Mon Jul 13 15:26:00 2020 +0200

    Python API: new RNA property `Screen.is_scrubbing`

    This commit adds a new read-only boolean property `Screen.is_scrubbing`.

    The related property `Screen.is_animation_playing` is set to `True` in
    two situations:

    - Animation is actually playing (for example via the Play button in the
      timeline)
    - The user is scrubbing through time (in the timeline, dopesheet, graph
      editor, etc.)

    To distinguish between these two cases, the property
    `Screen.is_scrubbing` has been added.

    Concept approved by @brecht.

commit b9f565881e
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Mon Jul 13 15:02:25 2020 +0200

    VSE: Python API, allow creation of VSE Movie strips with missing file

    It was already possible to create Sound and Image strips that reference
    non-existing files. Now it's also possible to create Movie strips
    referencing missing files via the Python API call
    `Sequences.new_movie()`. In this case, the duration of the strip will be
    set to 1 frame.

    Note that this commit does not change anything in the user interface.

    The Python API of the `MovieStrip` class is extended with a function
    `reload_if_needed()`. This function only performs disk I/O if the movie
    strip cannot produce frames, that is either when its filepath points to
    a non-existing file, or when the video sequence editor has not been
    shown yet (for example because it is in an inactive workspace).

    This allows for the following:

    ```
    import bpy

    scene = bpy.context.scene
    vse = scene.sequence_editor_create()

    filepath = bpy.path.abspath('//demo.mkv')
    strip = vse.sequences.new_movie("movie", filepath,
        channel=2,
        frame_start=47,
        file_must_exist=False)
    strip.frame_final_end = 327
    ```

    This will create a new movie strip, even when `demo.mkv` does not exist.

    Once `demo.mkv` has appeared at the expected location, either
    `strip.reload_if_needed()` or `strip.filepath = strip.filepath` will
    load it.

    Differential Revision: https://developer.blender.org/D8257

    Reviewed By: Sergey, ISS

commit 9db0c36af1
Author: Bastien Montagne <bastien@blender.org>
Date:   Mon Jul 13 14:29:04 2020 +0200

    LibOverride: add more polling checks to operators not supposed to work on overrides.

    This is long work, we are still likely missing a lot of cases...

commit 03c8b048a1
Author: Bastien Montagne <bastien@blender.org>
Date:   Mon Jul 13 14:15:57 2020 +0200

    Cleanup: remove public unused function.

commit 9c9eb03d78
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Sun Jul 12 21:47:50 2020 -0300

    Fix T78855: Knife tool crashes when the geometry has no face

    I don't see the need for a BVH Tree to have root but not have leafs.
    But apparently this case is possible.

commit f019164f1f
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Sun Jul 12 21:13:05 2020 -0300

    Optimization: Use dedicated function to restore customdata

    Called when canceling a transform operation.

commit 8074a18964
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Sun Jul 12 21:01:54 2020 -0300

    Cleanup: move unchanged condition out of loop

commit 7b558a20a9
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Sun Jul 12 20:53:22 2020 -0300

    Fix Extrude Manifold losing original UV

commit 976a0ff691
Author: Bastien Montagne <bastien@blender.org>
Date:   Mon Jul 13 12:48:56 2020 +0200

    RNA code cleanup: Fix wrong usages of `rna_idproperty_check()`.

    This function is more expansive than the simpler `rna_ensure_property()`
    one, and should only be used when IDProperty data is actually needed.

    If one only needs to ensure it has a valid PropertyRNA pointer,
    `rna_ensure_property()` is much more efficient.

    Also add compiler warnings when results of those functions are unused,
    this should never be the case.

commit f8afbb7657
Author: Bastien Montagne <bastien@blender.org>
Date:   Mon Jul 13 12:47:49 2020 +0200

    RNA property management: tweak to 'is set' information.

    Only consider a full IDProperty as set if it actually exists in given
    PointerRNA data.

commit 0158571b34
Author: Bastien Montagne <bastien@blender.org>
Date:   Mon Jul 13 12:46:29 2020 +0200

    I18n utils: fix broken case when 'settings' argument is default NULL one.

commit 7453ff73ad
Author: Jacques Lucke <jacques@blender.org>
Date:   Mon Jul 13 12:48:46 2020 +0200

    Cleanup: quiet warnings by adding const in some places

    The warnings were introduced in rB725973485a909c2b732c5.

commit 725973485a
Author: Jacques Lucke <jacques@blender.org>
Date:   Mon Jul 13 11:27:09 2020 +0200

    Clang Tidy: enable readability-non-const-parameter warning

    Clang Tidy reported a couple of false positives. I disabled
    those `NOLINTNEXTLINE`.

    Differential Revision: https://developer.blender.org/D8199

commit a19584a471
Author: Jacques Lucke <jacques@blender.org>
Date:   Mon Jul 13 10:51:46 2020 +0200

    BLI: fix constructor regression for Vector and Array

    This was introduced in rB403384998a6bb5f428e15ced5.

commit 644a915b1b
Author: Jacques Lucke <jacques@blender.org>
Date:   Mon Jul 13 10:49:59 2020 +0200

    BLI: don't allow mutable span of initializer list

commit 0718c6fae0
Author: Jacques Lucke <jacques@blender.org>
Date:   Mon Jul 13 10:40:05 2020 +0200

    Cleanup: fix clang tidy warning

    The code was actually correct, but clang tidy complaint about
    using the Vector after it was moved from.

commit 91c763af3e
Author: Jacques Lucke <jacques@blender.org>
Date:   Mon Jul 13 10:34:44 2020 +0200

    Cleanup: typo

commit 6dabfacb38
Author: Lukas Stockner <lukas.stockner@freenet.de>
Date:   Mon Jul 13 01:53:54 2020 +0200

    Sky: Code style and formatting fixes

    Differential Revision: https://developer.blender.org/D8091

commit 6a3c91f7ad
Author: Lukas Stockner <lukas.stockner@freenet.de>
Date:   Mon Jul 13 01:53:02 2020 +0200

    Cycles: Clamp Sky Texture altitude to avoid numerical issues

    Differential Revision: https://developer.blender.org/D8091

commit 7aacf2e119
Author: Lukas Stockner <lukas.stockner@freenet.de>
Date:   Mon Jul 13 01:52:07 2020 +0200

    Cycles: Account for Sky Texture mapping in the sun sampling code

    Differential Revision: https://developer.blender.org/D8091

commit 192bd2605f
Author: Lukas Stockner <lukas.stockner@freenet.de>
Date:   Mon Jul 13 01:51:13 2020 +0200

    Cycles: Change precomputed Sky Texture mapping to prioritize the horizon

    Differential Revision: https://developer.blender.org/D8091

commit 41e6f9bd43
Author: Lukas Stockner <lukas.stockner@freenet.de>
Date:   Mon Jul 13 01:49:25 2020 +0200

    Cycles: Add control for sun intensity in Sky Texture and change altitude to km

    Differential Revision: https://developer.blender.org/D8091

commit e2736afdbe
Author: Lukas Stockner <lukas.stockner@freenet.de>
Date:   Mon Jul 13 01:44:24 2020 +0200

    Cycles: Add versioning code for the new Sky Texture model

    Differential Revision: https://developer.blender.org/D8091

commit 77cd8182f8
Author: Lukas Stockner <lukas.stockner@freenet.de>
Date:   Mon Jul 13 01:40:47 2020 +0200

    Cycles: Remove Vector input on Sky texture when using the included sun

    When using the sun, we need to sun sampling logic to avoid excessive
    sampling map resolution, but that logic assumes that the Vector input
    comes from the view direction.
    That is the case in the vast majority of cases anyways, so the easiest
    solution is to just remove the input for that case.

    Differential Revision: https://developer.blender.org/D8091

commit 474dcbcf12
Author: Lukas Stockner <lukas.stockner@freenet.de>
Date:   Mon Jul 13 01:39:11 2020 +0200

    Cycles: Remove limits on the Sky texture's sun rotation

    For animation/driver purposes, being able to go outside of the 0-360
    range makes things easier.

    Differential Revision: https://developer.blender.org/D8091

commit f319eec881
Author: Jacques Lucke <jacques@blender.org>
Date:   Sun Jul 12 11:05:43 2020 +0200

    Cleanup: disable debug code

commit 30ed51d60a
Author: Jacques Lucke <jacques@blender.org>
Date:   Sun Jul 12 12:50:19 2020 +0200

    Cleanup: unused debug variable

commit 21b20ae5ec
Author: Jacques Lucke <jacques@blender.org>
Date:   Sun Jul 12 12:38:57 2020 +0200

    Particles: initial support for forces in simulation node trees

    The force node can now be used to control the behavior of particles.
    Forces can access particles attributes. Currently, there are three attributes:
    `Position` (vector), `Velocity` (vector) and `ID` (integer).

    Supported nodes are: Math, Vector Math, Separate Vector, Combine Vector and Value.

    Next, I'll have to split `simulation.cc` into multiple files and move
    some stuff out of blenkernel into another folder.

commit ebf9082e1c
Author: Jacques Lucke <jacques@blender.org>
Date:   Sun Jul 12 12:38:30 2020 +0200

    Nodes: support more implicit conversions in simulation node tree

commit 838b1742fb
Author: Jacques Lucke <jacques@blender.org>
Date:   Sun Jul 12 12:38:03 2020 +0200

    Functions: minor improvements

commit 404486e66c
Author: Jacques Lucke <jacques@blender.org>
Date:   Sun Jul 12 10:01:37 2020 +0200

    Functions: minor api improvements

commit ee5c2f6ead
Author: Antonio Vazquez <blendergit@gmail.com>
Date:   Sat Jul 11 20:41:21 2020 +0200

    GPencil: Replace "ShaderFX" with "Shader Effects" in RNA prop text

commit c7eada103c
Author: Jacques Lucke <jacques@blender.org>
Date:   Sat Jul 11 18:02:06 2020 +0200

    Nodes: support implicit conversions and incorrectly linked sockets

commit 06401157a6
Author: Jacques Lucke <jacques@blender.org>
Date:   Sat Jul 11 17:59:43 2020 +0200

    Fix: incorrect attribute type in network

commit 46b79b3d4a
Author: Jacques Lucke <jacques@blender.org>
Date:   Sat Jul 11 16:55:57 2020 +0200

    Nodes: support vector math node in simulation node tree

commit b920875893
Author: Jacques Lucke <jacques@blender.org>
Date:   Sat Jul 11 16:47:53 2020 +0200

    Nodes: support math node in simulation node tree

commit 8fae58ce0b
Author: Jacques Lucke <jacques@blender.org>
Date:   Sat Jul 11 16:39:17 2020 +0200

    Nodes: support Value node in simulation node tree

commit 16d4373158
Author: Jacques Lucke <jacques@blender.org>
Date:   Sat Jul 11 16:24:53 2020 +0200

    Nodes: move Math, Vector Math and Value shader nodes to c++ files

    This required a little bit of refactoring, because we were using c-only
    syntax for the gpu shader names. All tests are still passing.

commit 415d3ee05b
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Sat Jul 11 22:03:27 2020 +1000

    UV: add path select operator that uses the selection

    Instead of using the mouse cursor position,
    this selects between existing selected elements.

    Access this since picking a selection path doesn't
    work from the menu.

commit 6e698653df
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Sat Jul 11 20:34:17 2020 +1000

    Cleanup: remove unused function

commit 651db1b26f
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Sat Jul 11 15:10:05 2020 +1000

    Cleanup: spelling

commit 020e0f11ff
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Sat Jul 11 14:50:47 2020 +1000

    Docs: remove reference to PYTHONHOME

    This is no longer used by default, when '--python-use-system-env' is set
    there are many Python environment variables, don't list them in
    Blender's help message.

commit d2b910fafe
Author: Aaron Carlisle <carlisle.b3d@gmail.com>
Date:   Fri Jul 10 16:07:31 2020 -0400

    UI: UV: Add Select Shortest Path to menu

    This matches the 3D Viewport

commit 3dc0178390
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Fri Jul 10 20:00:20 2020 +0200

    Fix T78662: Cycles baking fails if denoising is enabled, after recent changes

    This is not supported yet.

commit 6fbacd6048
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Fri Jul 10 19:56:53 2020 +0200

    Fix build error building without OpenImageDenoise

commit 48f10319c6
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Fri Jul 10 18:40:35 2020 +0200

    Fix T78801: Eevee missing setting to enable/disable freestyle per view layer

    This was only visible when Cycles was enabled.

commit 4e8fc15586
Author: Hans Goudey <h.goudey@me.com>
Date:   Fri Jul 10 12:21:32 2020 -0400

    UI: Improve transform constraint layout

      - Remove the "mapping" subpanel and moves the source axis
        selection ot the destination subpanel.
      - Rename "Source" and "Destination" to "Map From" and "Map To" to
        make the action more clear
      - Gray out source axes when their data isn't selected.

      These changes were discussed in D8041.

commit 3e4f49fe71
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Fri Jul 10 18:02:51 2020 +0200

    Revert "Fix T78296: Performance - Use Binary Search for MDeformWeight"

    This reverts commit 39b525e0f0 and
    3121015dce as tests are failing.

commit d5208c45fa
Author: Antonio Vazquez <blendergit@gmail.com>
Date:   Fri Jul 10 17:56:05 2020 +0200

    GPencil: Fix unreported Use Falloff curve for active frame not working

    For the active frame it was using always a value of 1.0 and it was not using the curve.

commit 6eeb32706a
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Thu Jul 9 12:20:07 2020 +0200

    Cycles: support OpenImageDenoise in final renders

    Performance is not great currently due to the API not seeming to support
    efficient denoising of multiple tiles at the same time. So in many cases
    only one or a few threads will actually be denoising at the same time.

    In renders with many samples this is not a big problem, but for faster
    renders it's a signficant overhead.

    We should try to optimize this still, possibly by batching denoising of
    a bigger neighborhood of multiple tiles at once.

commit 93791381fe
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Thu Jul 9 20:01:22 2020 +0200

    Cleanup: reduce hardcoded numbers in denoising neighbor tiles code

commit e65c78cd43
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Thu Jul 9 18:54:42 2020 +0200

    Cleanup: minor refactoring in Cycles update detection code

commit ad45b8d6a4
Author: Milan Jaros <jar091>
Date:   Fri Jul 10 11:49:52 2020 +0200

    Cycles: optimize camera inside volume tests

    Only run when there are volumes in the scene, and compute in parallel.

    Ref T56939

    Differential Revision: https://developer.blender.org/D8261

commit d8e648c352
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Fri Jul 10 17:09:35 2020 +0200

    Fix T78776: Cycles OpenCL error after recent changes for holdouts

commit 9dbe9a753a
Author: Bastien Montagne <bastien@blender.org>
Date:   Fri Jul 10 16:50:26 2020 +0200

    Fix T78766: Blender crashes after deleting vertices with Custom Normals.

    Some core BMesh topology changing functions were not properly tagging
    custom normal runtime caches as dirty...

commit 5372924983
Author: Richard Antalik <richardantalik@gmail.com>
Date:   Fri Jul 10 16:14:10 2020 +0200

    Fix T78579: Proxy produces wrong preview when using Offset or Crop

    Make sure that proxy and original images are scaled to same size before
    applying offset or crop.

    During testing, I discovered, that raw cache will lose information whether
    this image was proxy or not. Because of this, proxy images will not create
    this cache type. It would be fairly easy to implement this functionality for
    cache, but I have decided to not do it now, because I did not want to pass yet
    another mostly hard-coded bool flag to cache system. Since image is proxy, it
    should be fast to read anyway.

    In case of using offset property, code was modified to make sure we scale
    image only once. I also tried to make code more readable and streamlined and
    cleaned up surrounding functions a bit.

    Reviewed By: brecht

    Differential Revision: https://developer.blender.org/D8203

commit 77f823a240
Author: Richard Antalik <richardantalik@gmail.com>
Date:   Fri Jul 10 15:57:28 2020 +0200

    Fix T78573: Crash when removing strips with prefetching

    Stop prefetching before changing content of seqbase.

    Reviewed By: brecht

    Differential Revision: https://developer.blender.org/D8256

commit 47e71f4623
Author: Richard Antalik <richardantalik@gmail.com>
Date:   Fri Jul 10 15:53:57 2020 +0200

    Fix T69440: Memory leak adding strips via python

    seq->strip was overwritten in python API function.

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8204

commit cbfedf2139
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 15:53:36 2020 +0200

    BLI: add C++ random number generator

    This adds `blender::RandomNumberGenerator` in `BLI_rand.hh`.
    Furthermore, `RNG` is now implemented in terms of this new generator.
    No functional changes are expected, the generated random numbers
    are not changed by this commit.

    Reviewers: campbellbarton, brecht

    Differential Revision: https://developer.blender.org/D8259

commit c2304d2f02
Author: Bastien Montagne <bastien@blender.org>
Date:   Fri Jul 10 15:29:03 2020 +0200

    Expose override flags to python RNA properties definition.

    Time will tell whether we need to expose more RNA override flags here.

    Implements/Fix T78534.

    Differential Revision: https://developer.blender.org/D8250

commit 4d1c3c029e
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 08:37:35 2020 +0200

    Cleanup: declaration and implementation function signature did not match

commit f93e0f1a9e
Author: Bastien Montagne <bastien@blender.org>
Date:   Fri Jul 10 15:23:52 2020 +0200

    Refactor override code to properly deal with runtime rna properties too.

    The triplet static RNA / runtime RNA / custom properties is a real pain to
    deal with...

    Using the new `PropertyRNAOrID` struct helps clarifying and properly
    dealing with all three cases.

    Note that this makes override of py-defined RNA properties working
    (support for that will be committed next).

    Differential Revision: https://developer.blender.org/D8249

commit 337e2c9029
Author: Bastien Montagne <bastien@blender.org>
Date:   Fri Jul 10 15:19:40 2020 +0200

    RNA: refactor how we get 'ensured' RNA properties.

    Introduce new PropertyRNAOrID structure, storing most useful data about
    an 'opaque' PropertyRNA in relation with a given PointerRNA struct.

    It deals with all the three cases (pure static RNA, runtime RNA where
    data is actually stored in IDProperties, and pure IDProperties, aka
    custom data.

commit 6c1157201a
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 22:59:12 2020 +1000

    Cleanup: simplify platform define checks

    Platforms besides WIN32 were in a single else clause, use elif instead.

commit 45287f909c
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 22:58:30 2020 +1000

    Fix for building on systems besides apple/windows/linux

commit 26d28ade26
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 14:40:23 2020 +0200

    Cleanup: follow code style

commit c806db6313
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 14:22:35 2020 +0200

    Functions: add utility to find dependencies of input sockets

commit 60133ff98d
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 14:20:39 2020 +0200

    Functions: store derived node tree and network in map for future access

commit 295b3aefb0
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 14:19:45 2020 +0200

    Functions: make constant folding work on unfinished networks

commit 7bae599232
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 14:18:51 2020 +0200

    Nodes: add redundant name check in debug builds to prevent errors

commit 3121015dce
Author: Jeroen Bakker <jeroen@blender.org>
Date:   Fri Jul 10 13:37:12 2020 +0200

    Fix Crash due to recent changes

    {39b525e0f07fa25dcda54226ade789959b642dec} could write in unallocated
    space.

commit 00eb6a56aa
Author: Antonio Vazquez <blendergit@gmail.com>
Date:   Fri Jul 10 13:30:08 2020 +0200

    GPencil: Fix tooltip error

    The tooltip was copied by error from Lattice modifier.

commit 8fd65a2252
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 12:56:57 2020 +0200

    Functions: use new is-equal and hash function of CPPType

commit 3edd2832b2
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 12:54:19 2020 +0200

    Functions: make generic types hashable

commit f62204718b
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 12:53:50 2020 +0200

    BLI: initial hash function for Color4b and float4x4

commit 8f6c0f2242
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 12:41:51 2020 +0200

    Functions: make generic types equality comparable

commit 52636c3059
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 12:36:06 2020 +0200

    Cleanup: various cleanups in for CPPType

commit 39b525e0f0
Author: Jeroen Bakker <jeroen@blender.org>
Date:   Fri Jul 10 12:05:31 2020 +0200

    Fix T78296: Performance - Use Binary Search for MDeformWeight

    Use binary search for querying deform weights.

    Spring 02_020_A.anim.blend on Ryzen 1700X goes from 12.4 to 12.7fps.

    During profiling it was detected that adding new items to the head was faster than adding to the tail.

    Reviewed By: Campbell Barton

    Differential Revision: https://developer.blender.org/D8127

commit 77a646279d
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 12:04:32 2020 +0200

    Cleanup: structure CPPType according to code style guide

commit 9c25731781
Author: Bastien Montagne <bastien@blender.org>
Date:   Fri Jul 10 11:53:11 2020 +0200

    LibOverride: Fix improper tagging of more of the backward pointers in RNA nodetrees.

commit 582a0b7e5a
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 19:02:18 2020 +1000

    Fix T78756: White UV drawing is displayed as Dashed

commit 7a9028cad1
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 18:58:36 2020 +1000

    Fix UV rip failing to disable proportional edit-mode

commit a148c4676b
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 16:04:09 2020 +1000

    Cleanup: spelling

commit 03f5acd445
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 16:03:12 2020 +1000

    Cleanup: clang-format

commit 8b660ea0ec
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 13:36:16 2020 +1000

    Fix UV path redo in vert/edge mode

    Redo was only working in some situations,
    some options were also not being forwarded.

commit 96068324cd
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 13:35:44 2020 +1000

    Fix BM_loop_at_index_find lookup

commit 89cb41faa0
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 12:55:59 2020 +1000

    UV: allow ripping face-regions

    This changes the behavior of rip when entire faces are selected.
    Now face regions are isolated and moved instead of ripping the edge-loop
    extracted from the selection boundary.

    This is a convenient alternative to separate selection & move.
    Resolves T78751.

commit 3fdd092649
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 12:38:28 2020 +1000

    Cleanup: face-center mesh calculation

    Loop over faces and calculate their centers instead of zeroing the
    face center array and accumulating all faces vertex corners.

    Move subsurf face center extraction into it's own loop since it works
    differently.

commit b0378440ce
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 12:18:43 2020 +1000

    Fix missing adjacent UV check for recent UV path select

    Path selection could cross UV islands if the destination element was
    on an island boundary.

commit 8f24ec2e26
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 12:04:29 2020 +1000

    Cleanup: add BLI_linklist_find_last

    This makes adding to the end of a linked list simpler,
    In most cases we avoid this in favor of BLI_linklist_append.

    For one off operations it's OK.

commit 3dd460aa7f
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 11:41:14 2020 +1000

    Cleanup: spelling

commit a0d3b60015
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 11:46:26 2020 +1000

    Cleanup: use FLT_MAX for the maximum path selection cost

    A large number below FLT_MAX was used to avoid overflow,
    however this doesn't cause any problems.

commit 0b77e2f4c4
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 11:31:41 2020 +1000

    Cleanup: variable names, use define for maximum path cost

commit 92bc277950
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 11:40:38 2020 +1000

    Cleanup: undeclared warnings

commit 3623db7784
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 9 19:03:50 2020 +0200

    BLI: add more operator overloads for float2

commit 03a00bda2b
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Thu Jul 9 17:16:24 2020 +0200

    Sculpt: Make Sculpt Vertex Colors features experimental

    This disables all Sculpt Vertex Colors tools, operators, panels and rendering capabilities and puts them under the "Use Sculpt Vertex Colors" experimental option.

    Reviewed By: brecht

    Differential Revision: https://developer.blender.org/D8239

commit 1e3247c078
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 9 18:19:39 2020 +0200

    Fix: add missing extern "C"

commit a90b69d065
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Thu Jul 9 18:04:13 2020 +0200

    Build: add more libc compatibility functions for upcoming libraries update

    These are needed by the x264 library.

commit 6778949e01
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Thu Jul 9 17:56:00 2020 +0200

    Fix repeated Face Sets IDs when joining meshes

    As Face Sets IDs start from 0 and increase by 1 each time a new face set
    is created in a mesh, when joining multiple meshes it could happen that
    the same ID is used by several unrelated areas in multiple objects. This
    checks the Face Sets IDs when joining meshes and ensures that they are
    not repeated between different objects when joining them, so in the
    resulting mesh all previous face sets will have different IDs.

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8224

commit 7b1c406b54
Author: Bastien Montagne <bastien@blender.org>
Date:   Thu Jul 9 15:33:34 2020 +0200

    Implement T77959: Never duplicate linked data during deep-copy.

    Note that this behavior is enforced on user level for now, but on code
    side it is controlled with a flag, which should make it easy to refine
    that behavior if needed.

    Only exception is when we duplicate a linked ID directly (then we assume
    user wants a local deep-copy of that linked data, and we always also
    duplicate linked sub-data-blocks).

    Note that this commit also slightly refactor the handling of actions of
    animdata, by simplifying `BKE_animdata_copy_id_action()` and adding an
    explicit new `BKE_animdata_duplicate_id_action()` to be used during ID
    duplication (deep copy).

    This also allows us to get rid of the special case for liboverrides.

commit 78b629a98f
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Wed Jul 8 18:10:31 2020 +0200

    Sculpt: Skip fully hidden nodes in sculpt tools

    As tools iterators skip not visible vertices, fully hidden nodes can
    also be skipped and considered as masked.

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8244

commit 1fb667da01
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Tue Jul 7 23:01:51 2020 +0200

    Fix wrong upate flag when updating the PBVH visibility

    This function was using the wrong flag to update the visibility state of
    the nodes, so I assume that most of the partially visible optimizations
    were not working.

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8243

commit e5ebaa9fd6
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Wed Jul 8 17:22:11 2020 +0200

    Fix T78664: Implement Mesh and Face Set boundary automasking in Multires

    This implements the SCULPT_vertex_is_boundary and SCULPT_vertex_has_unique_face_set functions for PBVH_GRIDS, which makes features such as automasking now work in multires. It also fixes some other face sets related features in multires, like face set boundary smoothing.

    This uses the BKE_subdiv_ccg_coarse_mesh_adjacency_info_get function to get the vertex indicies in the base mesh from multires. This way the API functions can get topology or face set information directly from it. In the future, these vertex indices can be used to get any other information from the base mesh from multires, like seams, sharp edges, disconnected elements IDs...

    Reviewed By: sergey

    Maniphest Tasks: T78664

    Differential Revision: https://developer.blender.org/D8227

commit bd84b2cbcc
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Sat Jul 4 18:28:40 2020 +0200

    Fix Sculpt Vertex Colors sample color changing brush alpha

    It is not practical to change the alpha of the paint color with the
    color picker as with the current brush design alpha is the main strength
    control for the brush.

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8208

commit 13b1374497
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Thu Jul 9 17:41:04 2020 +0200

    Fix crash when using Mask by Color in Multires

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8207

commit 78d48343ae
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Thu Jul 9 15:59:57 2020 +0200

    Make deps: Fix compilation error on CentOS

    There were two issues.

    First is related on ISPC's CMake configuration forcing C and C++
    compilers to be clang and clang++. This goes against of desired
    behavior when we use our own compiled clang compilers.

    The second issue was related on linker failure: CLang libraries
    are linked statically, and they need some of C++ 11 STL symbols
    which are coming from libstdc++.

    Differential Revision: https://developer.blender.org/D8258

commit 2be0ae7c99
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Thu Jul 9 16:51:48 2020 +0200

    Fix Cycles unnecessary updates to camera in viewport render

    Problem identified by Milan Jaros.

commit 9de09220fc
Author: Szymon Ulatowski <szulat>
Date:   Thu Jul 9 17:19:52 2020 +0200

    EEVEE: Implement the missing Sky texture

    I'm not sure if the Sky was deliberately left out or was just waiting for a
    better moment, but so many I was disappointed that Sky in EEVEE is
    completely white.

    There are already 2 implementations (osl and gpu) so this is the third one.
    Looking at other cases it seems that we are not supposed to share sources
    between cycles and the rest? So the new util_sky_model files are just
    copies of what is already in cycles, except that the data file uses the RGB
    variant of the Hosek/Wilkie model, because we output RGB anyway (but can be
    easily changed to XYZ if desired - the results are nearly identical).
    I am not sure if it is okay to pass 3*9 float values as 3 mat4 uniforms (I
    wanted to use mat3 but it does not work).
    Also, should I cache the sky model data between renders if the parameters
    do not change?

    Reviewed By: fclem, brecht

    Differential Revision: https://developer.blender.org/D7108

commit 42c99ec15b
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 9 16:37:44 2020 +0200

    BLI: rename rand.c to rand.cc

commit 580d50091c
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 9 15:40:27 2020 +0200

    Particles: Create a simulation state for every Particle Simulation node

    Every Particle Simulation node has a name (or a path when it is in a node group).
    This name has to be used in the Simulation modifier on a point cloud to see
    the particles.

    Caching has been disabled for now, because it was holding back development
    a bit. To reset the simulation, go back to frame 1.

    Currently, there is no way to influence the simulation. There are just some
    randomly moving points. Changing that is the next step.

commit 31ad43a3c7
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 9 15:29:25 2020 +0200

    Blenloader: make BLO_read_data_address work in C++

commit 544c435fdd
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Thu Jul 9 12:20:07 2020 +0200

    Fix T78745: Cycles error baking with multiple materials

commit 8ddf7556a5
Author: Bastien Montagne <bastien@blender.org>
Date:   Thu Jul 9 11:44:11 2020 +0200

    Fix T78718: Crash when deleting particle system modifier with the X Shortcut.

    Duplication and deletion code of modifiers was totally wrong for
    particle system, that special weird thing needs its own custom
    management.

    Note that for now I chose not to duplicate the particle settings ID when
    duplicating the modifier...

commit ea5fe7abc1
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Tue Jul 7 17:29:17 2020 +1000

    UV: path selection support

    This adds support for path selection for vertex edge & face selection
    modes, matching mesh editing behavior, useful with the UV rip tool.

    Region select & edge tagging are currently not supported,
    although they could be added eventually.

commit 0b8221683f
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Thu Jul 9 18:23:16 2020 +1000

    BMesh: add utility functions

    - BM_edge_uv_share_vert_check
    - BM_face_uv_calc_center_median_weighted
    - BM_loop_at_index_find

commit 0b3bf69d3c
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Thu Jul 9 13:33:15 2020 +1000

    Cleanup: move BMesh UV queries into their own file

commit 754c5d6a14
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Thu Jul 9 13:29:48 2020 +1000

    Cleanup: clang-format

commit 31bc76ea4e
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 22:29:10 2020 +0200

    Cleanup: remove unnecessary calls to as_span

    This uses the new implicit conversions and constructors
    that have been committed in the previous commit.

    I tested these changes on Linux with gcc and on Windows.

commit 403384998a
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 22:27:25 2020 +0200

    BLI: improve constructors and conversions to span

    This allows us to avoid many calls to `as_span()` methods. I will
    remove those in the next commit. Furthermore, constructors
    of Vector and Array can convert from one type to another now.

    I tested these changes on Linux with gcc and on Windows.

commit 4b85ed819d
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 20:41:00 2020 +0200

    Cleanup: remove unused function

    This is not necessary in C++17 anymore.

commit f7d5d4ee3b
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 20:39:12 2020 +0200

    Cleanup: use c++17 helper variable templates

commit e4926c167b
Author: Bastien Montagne <bastien@blender.org>
Date:   Wed Jul 8 18:08:08 2020 +0200

    Fix T78718: Crash when deleting particle system modifier with the X Shortcut.

    Again those backward pointers not properly flagged in RNA, hence
    generating infinite loops.

commit f4a39cafa1
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 17:05:40 2020 +0200

    Functions: add AttributesRef class

    This is the same as MutableAttributesRef, but the data in it cannot be changed.

commit 439c238bb4
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 17:04:50 2020 +0200

    Cleanup: use different internal socket name

commit 05365d1376
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 17:04:09 2020 +0200

    Functions: support hashing MFDataType and CPPType

commit 2de5de57c5
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Wed Jul 8 15:03:06 2020 +0200

    Build: fix stack linker warning with ffmpeg on macOS

    The ff_cfhd_init_vlcs() function was using a lot of stack space, which
    made linker on macOS unhappy. Using heap allocation allows to silence
    the warning without causing other side-effects.

    Kept the patch enabled for all platforms to avoid difference in behavior
    and performance on different platforms, which could make certain types
    of investigation very tricky.

    Differential Revision: https://developer.blender.org/D8248

commit cb3c4218bf
Author: Bastien Montagne <bastien@blender.org>
Date:   Wed Jul 8 15:43:57 2020 +0200

    Minor cleanup in rna override code.

commit d1f4546a59
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 15:10:24 2020 +0200

    Functions: implement common subnetwork elimination optimization

    This was the last of the three network optimizations I developed in
    the functions branch. Common subnetwork elimination and constant
    folding together can get rid of most unnecessary nodes.

commit e3e42c00cb
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 15:06:32 2020 +0200

    Functions: Support getting MFSocket based on its id

commit 2b9d62b73a
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 15:06:04 2020 +0200

    Functions: Support accessing socket index of MFSocket

commit 34d175f372
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 15:04:28 2020 +0200

    Functions: initial hash/equals implementation for constant multi-functions

commit 840941215d
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 15:02:47 2020 +0200

    Functions: allow multi-functions to override a hash and equals function

commit 36a547af7b
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 15:01:33 2020 +0200

    Cleanup: add correct license header to tests

commit ff133bbd33
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 14:57:31 2020 +0200

    BLI: add disjoint set data structure

    This can be used to find separate islands in meshes efficiently (as is
    done in cycles already). Furthermore, this helps to implement some
    algorithms on node trees more efficiently.

commit a8ff8b64dc
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 14:40:34 2020 +0200

    BLI: add comparison operators and hash functions for float3, etc.

commit ff444da7c4
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Thu Jul 2 12:28:57 2020 +0200

    macOS: upgrade minimum required version to 10.13 High Sierra

    C++17 does not work on 10.12, and Apple extended support ended for 10.12 in
    October 2019.

    Maniphest Tasks: T76783, T76184

    Differential Revision: https://developer.blender.org/D8179

commit 6435acd8f6
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Wed Jul 8 12:57:59 2020 +0200

    Cycles: support shader transparency for holdout objects

    Now transparent areas of the object will render objects behind.

    Fixes T78728.

commit 643196cc37
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Wed Jul 8 11:04:49 2020 +0200

    CMake: Fix spelling of Embree passed to find package

    The spelling and capitalization of package name passed to find_package()
    and find_package_handle_standard_args() needs to match.

    Silences CMake warning about mismatch.

    Differential Revision: https://developer.blender.org/D8247

commit 45004d82e0
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 11:18:43 2020 +0200

    Functions: add dead node removal and constant folding optimization

    Those optimizations work on the multi-function network level.
    Not only will they make the network evaluation faster, but they also
    simplify the network a lot. That makes it easier to understand the
    exported dot graph.

commit 50d7c00d9c
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 10:16:56 2020 +0200

    Cleanup: fix comment

commit 01c8aa12a1
Author: Alexander Gavrilov <angavrilov@gmail.com>
Date:   Wed Jul 1 17:38:07 2020 +0300

    Apply Modifier: support applying as shape key and keeping the modifier.

    This can be useful to save the result of a cloth simulation as a
    shape key without destroying the simulation, so it's possible to
    e.g. re-run it to get other shapes, or simply use the new shape
    key to start the simulation already in a draped state.

    It also makes sense to allow applying as shape key even when the
    mesh is shared, because the operation itself just adds a shape
    key. To support this, split the apply operator into Apply and
    Apply As Shapekey so that they can have different poll callbacks.

    Differential Revision: https://developer.blender.org/D8173

commit 7fcb6bc59c
Author: Lukas Stockner <lukas.stockner@freenet.de>
Date:   Wed Jul 8 02:10:02 2020 +0200

    Fix T78324: Different Sky Texture results between CPU and GPU

    The problem here was numerical precision: The code calculates the angle between
    sun and view direction, and the usual acos(dot(a, b)) approach for that has
    poor numerical performance for almost parallel angles.

    As a result, the generally tiny difference between floating point computation
    between CPU and GPU was enough to make the sun vanish at different radii,
    causing different results.

    The new version fixes the difference by making the computation much more robust
    on both platforms.

commit afcb41a0aa
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 20:32:40 2020 +0200

    BLI: simplify copy constructor of Array

commit eb5fb1741d
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 20:29:35 2020 +0200

    Cleanup: don't end description with a '.'

commit 8713109212
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 20:27:34 2020 +0200

    Cleanup: fix typo

commit 902ee4d13c
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 19:46:10 2020 +0200

    Functions: cleanup loop that traverses the MFNetwork

commit 22158162ef
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 19:34:35 2020 +0200

    Functions: add generic functions that output constants

commit f4633cf46c
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 19:16:31 2020 +0200

    BLI: simplify copy constructor of vector

commit 67042aa6a1
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 18:45:34 2020 +0200

    Functions: extend multi-function network api

commit adfae89f96
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 18:40:42 2020 +0200

    BLI: provide access to underlying node in dot exporter

commit a8627ea66d
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 18:39:24 2020 +0200

    Functions: Add debug print and destruct callback to CPPType

commit 4990e4dd01
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 18:23:33 2020 +0200

    Nodes: Generate multi-function network from node tree

    This adds new callbacks to `bNodeSocketType` and `bNodeType`.
    Those are used to generate a multi-function network from a node
    tree. Later, this network is evaluated on e.g. particle data.

    Reviewers: brecht

    Differential Revision: https://developer.blender.org/D8169

commit ff97545c50
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Tue Jul 7 18:37:35 2020 +0200

    Fix T75943 EEVEE: Cubemaps shows black

    Caused by faulty driver implementation. Force fallback method.

commit 1e2ff4f81b
Author: Hans Goudey <h.goudey@me.com>
Date:   Tue Jul 7 11:10:42 2020 -0400

    Cleanup: Add braces for clang tidy

commit 0edf2fc128
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Tue Jul 7 16:51:03 2020 +0200

    BLI: Correct spin lock definition

    The MSVC atomic function is defined for an unsigned type.

    Not sure why this became an issue after switch to TBB by default,
    maybe some CFLAGS changed to be more strict after that.

commit dad3de89dc
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Tue Jul 7 11:27:09 2020 -0300

    Fix: remove accidental code

    `v1` and `v2` are already set.

commit d352902758
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Tue Jul 7 11:16:31 2020 +0200

    Make deps: Use own nasm for ffmpeg and x264

    Fixes the warning: building for macOS, but linking in object file

    Differential Revision: https://developer.blender.org/D8235

commit 1e3c0b4b03
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Tue Jul 7 10:47:09 2020 +0200

    Make deps: Compile own version of nasm for Apple

    The upstream version of nasm does not put version information to the
    generated object files, which makes linker to show the following
    warning:

      building for macOS, but linking in object file

    Using own patched version of nasm which puts required information to
    the object file, making linker happy.

    The plan is to either streamline the patch and provide it to the
    upstream, or, it that takes too long, get an independent fix from the
    upstream.

commit 202e7ccaae
Author: Jeroen Bakker <j.bakker@atmind.nl>
Date:   Mon Jul 6 14:33:59 2020 +0200

    Fix T77455: Blender Freezes when using the 3d Scale Gizmo

    Issue is reported on Linux ith Intel HD6xx iGPU. Inside
    `gpu_select_sample_query.c` the call to `glGetQueryObjectuiv` froze. After
    bisecting this lead to the polyline shader. When using a 3d color shader
    in stead of the polyline shader during selection seems to fix the issue.

    Other parts of blender might also be effective, but I wasn't able to
    freeze blender in these areas. When it does, we might want to add
    a similar work-around to button2d, cage2d, cage3d & move3d, navigate.

    Backport this patch to 2.83.

    Reviewed By: Clément Foucault

    Differential Revision: https://developer.blender.org/D8217

commit d1dcd2b464
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Tue Jul 7 16:17:36 2020 +0200

    BLI: Fix mistake in SpinLock TBB migration

    Copy-paste mistake.

commit 20558848d3
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Tue Jul 7 09:45:53 2020 -0300

    Optimization: use `BLI_bvhtree_intersect_plane` to detect faces that will be affected by the knife tool

    The knife code currently calls the `BLI_bvhtree_overlap` function that
    tests the overlap between the mesh tree and an AABB that encompasses the
    points projected in the clip_start, clip_end and or clip_planes of the
    view.

    This resulted in many false positives since the AABB is very large.
    Often all the triangles "overlapped".

    The solution was to create a new function that actually tests the
    intersection of AABB with a plane.

    Even not considering the clip_planes of the view, this solution is more
    appropriate than using overlap.

    Differential Revision: https://developer.blender.org/D8229

commit 630c6226e2
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Tue Jul 7 16:26:01 2020 +0200

    Fix T78307 UI: Drawing artifacts in the Blender UI on macOS

    This was due to a bad driver which was not respecting this bit of the
    specification:

    `If the current primitive does not originate from an instanced draw command, the value of gl_InstanceID is zero.`

commit 737bd549b6
Author: Patrick Mours <pmours@nvidia.com>
Date:   Mon Jul 6 12:25:54 2020 +0200

    Cycles: Add support for native OptiX curve primitive

    This patch adds support for the curve primitive from OptiX to Cycles. It's currently hidden
    behind a debug option, since there can be some slight rendering differences still (because no
    backface culling is performed and something seems off with endcaps). The curve primitive
    was added with the OptiX 7.1 SDK and requires a r450 driver or newer, so this also updates
    the codebase to be able to build with the new SDK.

    Reviewed By: brecht

    Differential Revision: https://developer.blender.org/D8223

commit 95f0f31279
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Tue Jul 7 14:45:31 2020 +0200

    Fix T78692: improve UI regarding the effect of the denoiser on denoising passes

    It wasn't obvious that the choice of Cycles denoiser also generates different
    denoising data passes for compositing.

commit a394aac8b4
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Tue Jul 7 14:47:59 2020 +0200

    Fix T78666: Cycles non-uniformly scaled hair renders wrong for static objects

    Don't apply the matrix transform optimization in this case, curve points and
    radius can't represent non-uniform scale the way is possible with triangle
    meshes and vertices.

    This would cause abrupt change if objects had e.g. motion blur in one frame
    and not in the next.

commit 98bee41c8a
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Tue Jul 7 14:30:55 2020 +0200

    IO: Reversed persistent ID order in exports to Alembic and USD

    Each duplicated (a.k.a. instanced) object has a Persistent ID, which
    identifies a dupli within the context of its duplicator. This ID
    consists of several numbers when there are nested duplis (for example a
    mesh instancing empties on its vertices, where each empty instances a
    collection). When exporting to Alembic/USD, these are used to uniquely
    name the duplicated objects in the export.

    This commit reverses the order of the persistent ID numbers, so that the
    first number identifies the first level of recursion. This produces
    trees like this:

        ABC
         `--Triangle
             |--Triangle
             |--Empty-1
             |    `--Pole-1-0
             |        |--Pole
             |        `--Block-1-1
             |            `--Block
             |--Empty
             |    `--Pole-0
             |        |--Pole
             |        `--Block-1
             |            `--Block
             |--Empty-2
             |    `--Pole-2-0
             |        |--Pole
             |        `--Block-2-1
             |            `--Block
             `--Empty-0
                 `--Pole-0-0
                     |--Pole
                     `--Block-0-1
                         `--Block

    It is now clearer that `Pole-2-0` and `Block-2-1` are instanced by
    `Empty-2`. Before this commit, they would have been named `Pole-0-2` and
    `Block-1-2`.

commit 70b1c09d7a
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Tue Jul 7 12:45:30 2020 +0200

    IO: Fix bug exporting dupli parent/child relations

    Exporting a scene to USD or Alembic would fail when there are multiple
    duplicates of parent & child objects, duplicated by the same object. For
    example, this happens when such a hierarchy of objects is contained in a
    collection, and that collection is instanced multiple times by mesh
    vertices. The problem here is that the 'parent' pointer of each
    duplicated object points to the real parent; Blender would not figure
    out properly which duplicated parent should be used.

    This is now resolved by keeping track of the persistent ID of each
    duplicated instance, which makes it possible to reconstruct the
    parent-child relations of duplicated objects. This does use up some
    memory for each dupli, so it could be heavy to export a Spring scene
    (with all the pebbles and leaves), but it's only a small addition on top
    of the USD/Alembic writer objects that have to be created anyway. At
    least with this patch, they're created correctly.

    Code-wise, the following changes are made:

    - The export graph (that maps export parent to its export children) used
      to have as its key (Object, Duplicator). This is insufficient to
      correctly distinguish between multiple duplis of the same object by
      the same duplicator, so this is now extended to (Object, Duplicator,
      Persistent ID). To make this possible, new classes `ObjectIdentifier`
      and `PersistentID` are introduced.
    - Finding the parent of a duplicated object is done via its persistent
      ID. In Python notation, the code first tries to find the parent
      instance where `child_persistent_id[1:] == parent_persistent_id[1:]`.
      If that fails, the dupli with persistent ID `child_persistent_id[1:]`
      is used as parent.

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8233

commit f2175e06a7
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Tue Jul 7 12:43:18 2020 +0200

    Mae deps: Ensure Brotli is disabled for FreeType

    We don't need it and it was optionally enabled, causing Blender to fail
    to link on certain configuration (when Brotli is installed via Homebrew
    for example).

commit 02cd159539
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 12:31:10 2020 +0200

    Cleanup: add comment explaining operator delete

commit cc311e4a52
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Tue Jun 30 15:13:54 2020 +0200

    IO: print export name instead of object name in debug export graph output

    This is just a change in `AbstractHierarchyIterator::debug_print_export_graph()`
    to aid in debugging. It'll make it possible to distinguish between
    different duplicates of the same object.

    No functional changes to Blender itself.

commit 5761cb9ee2
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 11:52:45 2020 +0200

    Guarded Allocator: add missing operator delete

    This resolves warning C4291 on windows.

commit 80fe5e1b15
Author: Johan Walles <walles>
Date:   Tue Jul 7 11:09:31 2020 +0200

    UI: Add units to motion tracking solve errors

    The unit being "pixels".

    Before this change the solve errors were unitless in the UI.

    With this change in place, the UI is now clear on that the unit of the
    reprojection errors is pixels (px).

    Differential Revision: https://developer.blender.org/D8000

commit 6d9a6f12b3
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Tue Jul 7 10:06:14 2020 +0200

    Make deps: Fix compilation error of Python on macOS

    The configuration was confused about gettext installed via Homebrew
    and isysroot passed to Python's compilation but not to test programs.

    After this change `import gettext` still works, but it is unclear how
    to test it further,

    Differential Revision: https://developer.blender.org/D8231

commit 955abbeff2
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 09:01:01 2020 +0200

    Fix sign conversion error

commit e233ee1c1f
Author: Philipp Oeser <info@graphics-engineer.com>
Date:   Thu Jun 25 14:37:22 2020 +0200

    Fix T78186: Dyntopo panel error with tools that dont have a brush

    Maniphest Tasks: T78186

    Differential Revision: https://developer.blender.org/D8120

commit 19d4e265b6
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 10:35:28 2020 +0200

    Cleanup: remove redundant comments

    Searching in these files for "_as" will reveal a comment at the
    top, that explains what these methods are for. There is no need
    to duplicate that knowledge all over the place.

commit 6e609f0eb0
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Tue Jul 7 17:50:33 2020 +1000

    Cleanup: use doxy comments

commit 62774baded
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Tue Jul 7 16:06:05 2020 +1000

    UI: add merge/split menus

    This makes the menus and keymap match the edit-mesh
    (M for merge, Alt-M for split).

commit d212b3dc43
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Mon Jul 6 15:28:19 2020 +0200

    Make deps: Fixes for macOS platform

    Set of fixes which had to be made in order to have dependencies built
    on own laptop:

    - Require bison as a dependent software. It is required by ISPC.

      On macOS it is required to be installed via Homebrew. This is because
      Bison from Xcode toolchain is too old.

    - Made sure Boost is compiled using clang.

      Without this gcc was used, and some unsupported command line argument
      was passed to it.

    - Modify OGG in a way which does in fact pull fixed sized types.
      They are defined in stdint.h.

      Without this fix FFmpeg will not detect presence of OGG because the
      test program fails to compile.

    - Force disable zstd compression and make wepb optional for the TIFF
      library. Without this TIFF might pick up development libraries from
      Homebrew.

    Differential Revision: https://developer.blender.org/D8221

commit b28683b8b5
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Tue Jul 7 16:03:26 2020 +1000

    Cleanup: remove unused arguments

commit 0c58970da7
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Tue Jul 7 12:44:47 2020 +1000

    Cleanup: spelling

commit ad0edc626d
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Tue Jul 7 12:43:45 2020 +1000

    Cleanup: unused World struct members linfac, logfac

commit e20171e59f
Author: Hans Goudey <h.goudey@me.com>
Date:   Mon Jul 6 16:39:28 2020 -0400

    Fix build error with tests for removed functions

    These GHash functions were removed in 12817083ec,
    so the tests should be removed too.

commit d557f05502
Author: Hans Goudey <h.goudey@me.com>
Date:   Mon Jul 6 16:07:54 2020 -0400

    Cleanup: Use bool instead of int

commit 053e0c0af3
Author: Hans Goudey <h.goudey@me.com>
Date:   Mon Jul 6 15:35:21 2020 -0400

    UI: Add shortcuts for shader effect panels

    Only the delete shortcut applies here, although the move up and down
    operators can optionally be assigned in the keymap.

    See rB1fa40c9f8a81 for more details and rB5d2005cbb54b for the
    grease pencil modifier panel implementation, which is the same.

commit 12817083ec
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Mon Jul 6 14:44:30 2020 -0300

    Cleanup: Use the BLI_edgehash API in the sewing simulation of cloths

    Also remove the code in the ghash that is no longer used.

    This change simplifies the existing code.

    Differential Revision: https://developer.blender.org/D8219

commit a856de700b
Author: Hans Goudey <h.goudey@me.com>
Date:   Mon Jul 6 13:17:07 2020 -0400

    Fix T77730: ShaderFx Missing Update Notifier

    This adds a notification type for shaderfx so the properties editor can
    be properly notified to redraw.

    Another possible solution would be to also redraw the shaderfx tab
     with a ND_MODIFIER update, but this solution allows us to avoid
     some unecessary redraws too. There were no existing cases of
    ND_OBJECT | NC_MODIFIER updates, so those cases were
    removed from buttons_area_listener.

    Differential Revision: https://developer.blender.org/D8159

commit f6f4043924
Author: Jacques Lucke <jacques@blender.org>
Date:   Mon Jul 6 17:59:04 2020 +0200

    BLI: add methods to lookup a stored key in a set

commit 1562c9f031
Author: Patrick Mours <pmours@nvidia.com>
Date:   Mon Jul 6 17:32:32 2020 +0200

    Fix OptiX viewport denoising not working when rendering scene (without OptiX) that uses unsupported features

    Denoising devices do not need to load the full feature set of kernels, so only activate the denoising
    feature for them (so that it is possible to use features that are supported by the render devices, but
    not the denoising devices).

commit aabfd2fb9b
Author: Bastien Montagne <bastien@blender.org>
Date:   Mon Jul 6 16:55:00 2020 +0200

    Cleanup: readfile: remove old deprecated OldNewMap for runtime caches.

commit ee3eba902a
Author: Bastien Montagne <bastien@blender.org>
Date:   Mon Jul 6 16:21:41 2020 +0200

    Runtime cache preservation during undo: add support for nodes and embedded IDs.

commit bfc644dcfb
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Mon Jul 6 16:52:28 2020 +0200

    Reduce `DupliObject::persistent_id` from 16 to 8 items

    For historical reasons, `DupliObject::persistent_id` was of size
    `2*MAX_DUPLI_RECUR`. These reasons are now gone, and the persistent ID
    always gets exactly one array element for every dupli-recursion.

    Differential Revision: https://developer.blender.org/D8222

    Reviewed by: brecht

commit 0b07f9b717
Author: Bastien Montagne <bastien@blender.org>
Date:   Mon Jul 6 15:07:12 2020 +0200

    Fix T78608: Memory leak in Material properties: "Data from SCE".

    Caused by recent own refactor of cache presevation handling in readfile,
    EEVEE's lightcache are weird birds that can also be saved in .blend
    files, need a special handling for those 'persistent' caches...

commit 99feb10b8b
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Mon Jul 6 23:01:36 2020 +1000

    Cleanup: warning, spelling

commit 20446f07f6
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Mon Jul 6 22:52:29 2020 +1000

    Docs: reference bl_rna_get_subclass_py instead of bl_rna_get_subclass

    bl_rna_get_subclass only works for Nodes at the moment.

commit ffaf294c3f
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Mon Jul 6 14:53:39 2020 +0200

    Fix alignment/size issue on ARM/RPi architecture

    Addresses 964305 from Debian bug tracker.

commit 924578ce19
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Mon Jul 6 09:49:00 2020 -0300

    Optimization: Don't compute the snap to face on the knife tool twice

    Both `knife_find_closest_vert` and `knife_find_closest_edge` call
    `knife_find_closest_face`. Thus, running the raycast twice and setting
    values like `kcd->curr.bmface` and `kcd->curr.is_space` repeatedly.

    So:
    - separate `knife_find_closest_face` from `knife_find_closest_vert` and `knife_find_closest_edge`.
    - rename `knife_find_closest_vert` to `knife_find_closest_vert_of_face`
    - rename `knife_find_closest_edge `to `knife_find_closest_edge_of_face`.
    - do not set parameters previously set.

    Differential Revision: https://developer.blender.org/D8198

commit 073c426900
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Mon Jul 6 09:03:33 2020 -0300

    Fix faces disappearing when AutoMerge & Split

commit c632cf9ccd
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Mon Jul 6 21:23:35 2020 +1000

    Fix UV select separate not refreshing the display

commit 2c0cab03ca
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Mon Jul 6 21:14:12 2020 +1000

    UV: add rip region to toolbar

commit dbe171fb26
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Mon Jul 6 21:03:45 2020 +1000

    Cleanup: spelling, comments

commit 18b6c49a90
Author: Jacques Lucke <jacques@blender.org>
Date:   Mon Jul 6 12:37:11 2020 +0200

    Cleanup: rename namespace TimeIt to timeit

    According to our style guide, namespaces should have
    lower case names.

commit 572c48cf98
Author: Jacques Lucke <jacques@blender.org>
Date:   Mon Jul 6 09:08:53 2020 +0200

    BLI: improve exception safety of memory utils

    Even if we do not use exception in many places in Blender, our core C++ library
    should become exception safe. Otherwise, we don't even have the option
    to work with exceptions if we decide to do so.

commit 703a73fa84
Author: Jacques Lucke <jacques@blender.org>
Date:   Mon Jul 6 10:56:26 2020 +0200

    BLI: refactor how buffers for small object optimization are stored

    Previously, there was an error when operator-> was returning an
    invalid type. See error C2839.

commit 80393a0eba
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Mon Jul 6 17:41:36 2020 +1000

    UV: add rip tool

    New rip tool matching edit-mesh rip functionality.

    Useful as disconnecting UV's, especially for loops is inconvenient
    without this.

    This uses 'V' to rip, changing stitch to 'Alt-V'.

commit 9353477383
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Mon Jul 6 17:41:17 2020 +1000

    BMesh: add BM_face_calc_uv_cross

commit b51b893df8
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Mon Jul 6 17:40:55 2020 +1000

    BMesh: add BM_loop_other_vert_loop_by_edge

commit 705015e0a4
Author: Jeroen Bakker <j.bakker@atmind.nl>
Date:   Mon Jul 6 10:21:14 2020 +0200

    Fix T78481: Workbench Shadow effects XRay

    When in XRay some effects (shadow, cavity & depth of field) aren't supported.
    This patch makes sure that these effects aren't enabled.

commit 4f3045999d
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Mon Jul 6 17:35:41 2020 +1000

    Cleanup: warnings, spelling

commit 0f617cd67e
Author: Jeroen Bakker <j.bakker@atmind.nl>
Date:   Mon Jul 6 07:45:10 2020 +0200

    GPU: Remove local shaders workaround for Intel/Windows

    It has been tested that local shaders workaround isn't needed for the
    latest Windows/Intel 6xx GPU's.

    Currently the local shaders workaround doesn't work anymore during the
    investigation it was detected that the intel drivers didn't need it
    anymore.

    Local shaders should still be fixed as it is also used for some legacy
    iGPU's. The current work around crashes when doing preview renders in
    EEVEE as the default materials aren't available but for the work around
    they should. (See T77346 for more information)

commit baf124c753
Author: Aaron Carlisle <carlisle.b3d@gmail.com>
Date:   Sun Jul 5 16:45:56 2020 -0400

    RNA Manual Reference: Update links

commit 247a28f242
Author: Jacques Lucke <jacques@blender.org>
Date:   Sun Jul 5 15:08:26 2020 +0200

    Revert "BLI: refactor how buffers for small object optimization are stored"

    This reverts commit 5d79f9f276.

    This was introducing build errors in windows. Need a bit more time to check it.

commit 5d79f9f276
Author: Jacques Lucke <jacques@blender.org>
Date:   Sun Jul 5 16:30:26 2020 +0200

    BLI: refactor how buffers for small object optimization are stored

commit 464aaf2701
Author: Antonio Vazquez <blendergit@gmail.com>
Date:   Sat Jul 4 17:31:02 2020 +0200

    Fix T78603: GPencil Noise modifier Vertex Group influence filter missing

    This was removed by error during the last refactor of modiifers.

commit 169bb4b9ce
Author: Jacques Lucke <jacques@blender.org>
Date:   Sat Jul 4 17:28:05 2020 +0200

    BLI: fix mistake in move constructor of Stack

commit 8e97694c8a
Author: Julian Eisel <julian@blender.org>
Date:   Sat Jul 4 17:06:57 2020 +0200

    Fix T78588: Material preview not visible in selection list

    Logic to determine if the library icon should be used was too general.

commit 9168ea8aab
Author: Antonio Vazquez <blendergit@gmail.com>
Date:   Sat Jul 4 11:15:11 2020 +0200

    Cleanup: Fix small typo error

commit 17603816f2
Author: Antonio Vazquez <blendergit@gmail.com>
Date:   Sat Jul 4 11:04:21 2020 +0200

    GPencil: Cleanup some comments typo

commit b0da78084b
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Sat Jul 4 01:27:12 2020 +0200

    UI: Attempt to fix OSX widget shader issue

    Some OSX GL driver implementation needs a dummy vbo read. This fixed issues
    with the Hair shaders in the past.

    Related to T78307

commit cad98923d0
Author: Richard Antalik <richardantalik@gmail.com>
Date:   Sat Jul 4 01:02:54 2020 +0200

    Cleanup: spelling

commit ea65c6a153
Author: Richard Antalik <richardantalik@gmail.com>
Date:   Sat Jul 4 00:59:09 2020 +0200

    Fix T78433: Adding Fade Generates Python Exception

    This was caused by typo in rB67a822e08684.

commit 4bf56b37ca
Author: Nathan Craddock <nzcraddock@gmail.com>
Date:   Fri Jul 3 13:31:42 2020 -0600

    Cleanup: Use C-style comments in outliner files

    No functional changes. Convert all C++ style comments to C comments.
    Also capitalize and add full stops.

    The comments themselves were not cleaned up. Some could be removed or
    reworded.

commit 59ef43147e
Author: Nathan Craddock <nzcraddock@gmail.com>
Date:   Fri Jul 3 12:48:00 2020 -0600

    Cleanup: Remove unused outliner activation code

    No functional changes. Remove commented calls to extern_set_butspace
    and unused text activation code.

commit 57a48bd0ca
Author: Nathan Craddock <nzcraddock@gmail.com>
Date:   Fri Jul 3 12:36:09 2020 -0600

    Cleanup: Use _fn suffix for outliner button callbacks

    No functional changes. Use _fn instead of _cb.

commit d7dbf90a02
Author: Sebastian Parborg <darkdefende@gmail.com>
Date:   Fri Jul 3 21:22:41 2020 +0200

    Clang-tidy: Enable braces-around-statements warning

commit 185fe9cd8b
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Fri Jul 3 18:55:32 2020 +0200

    Cleanup: compiler warning

commit 46fcc12e83
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Fri Jul 3 18:54:04 2020 +0200

    Fix error in new Hair data type file reading

commit d2db481dc7
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 18:04:40 2020 +0200

    Cleanup: Blendkernel, Clang-Tidy else-after-return fixes (incomplete)

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/blenkernel` module. Not all warnings are
    addressed in this commit.

    No functional changes.

commit a21cb22f8b
Author: Hans Goudey <h.goudey@me.com>
Date:   Fri Jul 3 11:58:43 2020 -0400

    Cleanup: Deduplicate code for finding context object

    Instead of manually checking the pinned object, use the existing
    ED_object_active_context function. This requires adding const
    to the context in that function.

commit 33a74941c5
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 17:30:31 2020 +0200

    Cleanup: Editors, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors` module.

    No functional changes.

commit 367034f210
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 17:30:09 2020 +0200

    Cleanup: Editors/Space/UV-Edit, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/uv_edit` module.

    No functional changes.

commit 651d1aa7c8
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 17:25:04 2020 +0200

    Cleanup: Editors/Transform, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/transform` module.

    No functional changes.

commit 35ce16939c
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 17:20:58 2020 +0200

    Cleanup: Editors/Space/sequencer, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/space_sequencer` module.

    No functional changes.

commit a201020cd3
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 17:20:41 2020 +0200

    Cleanup: Editors/Space/Clip, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/space_clip` module.

    No functional changes.

commit f254f66587
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 17:20:22 2020 +0200

    Cleanup: Editors/Space/Outliner, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/space_outliner` module.

    No functional changes.

commit 3aa53b361d
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 17:20:08 2020 +0200

    Cleanup: Editors/Space/Node, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/space_node` module.

    No functional changes.

commit bf532b1106
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 17:19:13 2020 +0200

    Cleanup: Editors/Space/Text, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/space_text` module.

    No functional changes.

commit 2f6fc5a7e8
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 17:18:56 2020 +0200

    Cleanup: Editors/Space/View3D, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/space_view3d` module.

    No functional changes.

commit b61ecb785c
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 16:34:57 2020 +0200

    Cleanup: Explicit return in each `else if` block in `buttons_context()`

    This is a similar change as in rB4283da83cc9.

    No functional changes.

commit f43fedd400
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 3 17:35:31 2020 +0200

    Cleanup: remove side effect in assertion

commit 4a48939f04
Author: Hans Goudey <h.goudey@me.com>
Date:   Fri Jul 3 11:18:24 2020 -0400

    UI: Fix bevel modifier not showing vertex group

commit cad2d32be6
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Fri Jul 3 17:09:24 2020 +0200

    Clang-Tidy: Enable bugprone-misplaced-widening-cast

commit 4a5389816b
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 3 17:07:01 2020 +0200

    Clang-Tidy: enable readability-named-parameter

commit fac2e63bc0
Author: Bastien Montagne <bastien@blender.org>
Date:   Fri Jul 3 16:57:55 2020 +0200

    Fix utterly broken code regarding GPUtextures of MovieClip in readfile.c

    Treat those as pure runtime code, reset to NULL by reading code, for
    now.

    Think those could be handled like Image gputextures (i.e. considered
    runtime cache and preserved across undo steps), but probably not
    critical for now.

commit 1bdabd7b4f
Author: Bastien Montagne <bastien@blender.org>
Date:   Fri Jul 3 16:55:13 2020 +0200

    Move MovieClip to new undo cache management system.

commit 1019c9f582
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 3 16:54:08 2020 +0200

    Clang-Tidy: enable bugprone-too-small-loop-variable

commit 883f9dd6e5
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 3 16:48:04 2020 +0200

    Clang-Tidy: enable bugprone-assert-side-effect

    Looks like we have no assertions with side effects.

commit 9739fc4d1b
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Fri Jul 3 16:44:46 2020 +0200

    Clang-Tidy: More fixed of redundant check before delete

    For some reason got unnoticed in the original cleanup pass.

commit 14fd91e7e8
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 3 16:38:01 2020 +0200

    Clang-Tidy: enable bugprone-argument-comment

    It was called `inverted` in the header.

commit f4fdb8efc5
Author: Hans Goudey <h.goudey@me.com>
Date:   Fri Jul 3 10:38:49 2020 -0400

    Cleanup: Remove redundant logic

commit f66aafa391
Author: Hans Goudey <h.goudey@me.com>
Date:   Fri Jul 3 10:37:58 2020 -0400

    Fix memory leak when dragging shaderfx

commit f891d4e2ad
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Fri Jul 3 16:32:12 2020 +0200

    Clang-Tidy: Fix readability-delete-null-pointer warnings

    Also enable it in the configuration.

commit 53d41e1a6f
Author: Hans Goudey <h.goudey@me.com>
Date:   Fri Jul 3 10:28:13 2020 -0400

    UI: Use sliders and [0, 1] ranges in ocean modifier

    The ocean modifier has two properties that use a [0, 10] hard min and
    hard max. The values act as factors though, so it makes more sense to
    use sliders and a 0 to 1 range.

    This commit also bumps the file subversion to avoid repeatedly applying
    the change to the properties' range.

    Differential Revision: https://developer.blender.org/D8186

commit 2a39b34a09
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 16:09:51 2020 +0200

    Cleanup: Editors/Sculpt/Paint, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/sculpt_paint` module.

    No functional changes.

commit fd5b093f84
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 16:01:15 2020 +0200

    Cleanup: Editors/Screen, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/screen` module.

    No functional changes.

commit 4283da83cc
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 15:59:48 2020 +0200

    Cleanup: Explicit return in each `else if` block in `ed_screen_context()`

    The `ed_screen_context()` function is approximately 700 lines long, and
    its main structure is a huge chain of `else if` statements. Some of the
    bodies did not return, but rather fell through and relied on the `return
    -1;` at the bottom of the function. This means that in order to truly
    understand what is going on in one of those `else if` blocks, it could
    be required to scroll past all the following `else if` blocks,
    double-checking that they all had an `else`, and then see what happens
    below.

    By adding explicit `return -1;` everywhere this happened, this is all
    avoided, increasing local understandability of the code. Furthermore, it
    makes the upcoming cleanup with the Clang-Tidy rule
    `readability-else-after-return` a lot easier to do.

    No functional changes.

commit de7c9f41e6
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 15:42:22 2020 +0200

    Cleanup: Editors/Object, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/object` module.

    No functional changes.

commit 19483125f8
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 15:19:52 2020 +0200

    Cleanup: Editors/Mesh, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/mesh` module.

    No functional changes.

commit 7d0a0b8a6d
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 14:52:32 2020 +0200

    Cleanup: Editors/Armature, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/armature` module.

    No functional changes.

commit f82e52ebc8
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 14:51:19 2020 +0200

    Cleanup: Editors/Animation, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/animation` module.

    No functional changes.

commit 17ba566018
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Fri Jul 3 02:15:54 2020 +0200

    Fix Pose Brush crashing after disabling connected only in FK mode

    This function was returning the ik_chain before disabling the
    fake_neighbors, so when the brush was used again with fake neighbors
    disabled after rebuilding the PBVH and free them, they were still
    enabled in the SculptSession, causing a the crash.

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8195

commit 3a59c184b9
Author: Bastien Montagne <bastien@blender.org>
Date:   Fri Jul 3 16:09:58 2020 +0200

    Move Scene's cache management during undo to new system.

commit a33756d783
Author: Hans Goudey <h.goudey@me.com>
Date:   Fri Jul 3 10:09:19 2020 -0400

    Cleanup: Unused variables in non-debug build

commit 6a58e15548
Author: Hans Goudey <h.goudey@me.com>
Date:   Fri Jul 3 10:03:16 2020 -0400

    Cleanup: Remove obsolete code in interface_panel.c

    Some code delt with panel merging in earlier versions of Blender,
    which is no longer needed. Other code delt with controls that aren't
    used anymore, and in some cases have region-level equivalents.

    There's a surprising amount of this unused code in this file, so removing it
    will be helpful for the future.

    Differential Revision: https://developer.blender.org/D7938

commit 88d358902f
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 3 15:54:55 2020 +0200

    Clang-Tidy: Enable readability-redundant-string-cstr

commit 405e6c6cc9
Author: Antonio Vazquez <blendergit@gmail.com>
Date:   Fri Jul 3 15:53:44 2020 +0200

    Fix T78555: GPencil bake animation operator loose frame setting

    The values were reset for each run

commit 19ff145e66
Author: Hans Goudey <h.goudey@me.com>
Date:   Fri Jul 3 09:41:55 2020 -0400

    Clang-Tidy: Enable readability-redundant-control-flow

commit ffef562bf7
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Fri Jul 3 15:31:23 2020 +0200

    Disable clang-tidy for code-generated RNA files

    This needs some extra care, which is probably easier once the initial
    pass over integration is done.

commit c9975088a9
Author: Bastien Montagne <bastien@blender.org>
Date:   Fri Jul 3 15:27:12 2020 +0200

    Move volume to new cache management system for undo.

commit 1e255ce031
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 3 15:27:02 2020 +0200

    Fix T72214: Fluids: noise does not work with negative frame numbers

    The issue is duplicated code. There are two functions that zero-fill
    the frame number. They worked the same for positive frames numbers, but
    behaved differently for negative ones.

    On frame `-100`, `BLI_path_frame` outputs `-0100` and
    `fluid_cache_get_framenr_formatted_$ID$` outputted `-100`.

    I changed the behavior of the latter, because we depend on the behavior
    of the former for much longer already.

    Reviewers: sebbas

    Differential Revision: https://developer.blender.org/D8107
2020-07-17 21:40:09 -04:00
cd9b38005e Performance tuning: early rejection of trivial intersections.
Starting to use floating filters to avoid expensive gmp operations
when possible. These changes speed up the sphere-sphere test with
n=64 to 5s (now 17 times slower than BMesh on this test, down from
100 times slower. But answer is correct.
Also make format.
2020-07-16 22:23:18 -04:00
7148f31a3a Reverse the operand order for Difference to match old boolean. 2020-07-14 20:49:03 -04:00
8541b335cb Hooked up new boolean to boolean modifier. 2020-07-14 20:29:39 -04:00
f86b49d710 Comment out an assert prevents running profiler on Mac.
Not sure why this assert is not known to the compiler used
when profiling.
2020-07-14 17:16:07 -04:00
ad81b1993e Speedup, using BVH tree to limit number of tri-tri intersect tests.
Intersection of my spheresphere test with n=16 (two uvspheres
with 16 rings and 32 segments overlapping), time went from
12.8 seconds to 2.3 seconds on my Mac. The n=32 test went from
195.1s to 8.9s.
2020-07-14 08:01:50 -04:00
b10b38d386 Add a mesh intersect sphere-sphere test for performance tuning. 2020-07-13 07:24:43 -04:00
0024605194 Fix a test that needs a new kind of initializer. 2020-07-12 21:45:53 -04:00
a6c80378aa Merge Master, then fixes of problems caused by that.
commit 622aa7bc5015cc3b85deb0eb13b7b315169569b4
Author: Howard Trickey <howard.trickey@gmail.com>
Date:   Sun Jul 12 21:09:59 2020 -0400

    Provided noexcept move contructors for many types.

    Needed because now a static assert trips when making Arrays
    or Vectors of these types.

commit 7a7dd53bca36506fb51788cad0444dcb491b3c13
Merge: 74c56382b8 f319eec881
Author: Howard Trickey <howard.trickey@gmail.com>
Date:   Sun Jul 12 19:22:24 2020 -0400

    Merge branch 'master' into boolmerge

commit f319eec881
Author: Jacques Lucke <jacques@blender.org>
Date:   Sun Jul 12 11:05:43 2020 +0200

    Cleanup: disable debug code

commit 30ed51d60a
Author: Jacques Lucke <jacques@blender.org>
Date:   Sun Jul 12 12:50:19 2020 +0200

    Cleanup: unused debug variable

commit 21b20ae5ec
Author: Jacques Lucke <jacques@blender.org>
Date:   Sun Jul 12 12:38:57 2020 +0200

    Particles: initial support for forces in simulation node trees

    The force node can now be used to control the behavior of particles.
    Forces can access particles attributes. Currently, there are three attributes:
    `Position` (vector), `Velocity` (vector) and `ID` (integer).

    Supported nodes are: Math, Vector Math, Separate Vector, Combine Vector and Value.

    Next, I'll have to split `simulation.cc` into multiple files and move
    some stuff out of blenkernel into another folder.

commit ebf9082e1c
Author: Jacques Lucke <jacques@blender.org>
Date:   Sun Jul 12 12:38:30 2020 +0200

    Nodes: support more implicit conversions in simulation node tree

commit 838b1742fb
Author: Jacques Lucke <jacques@blender.org>
Date:   Sun Jul 12 12:38:03 2020 +0200

    Functions: minor improvements

commit 404486e66c
Author: Jacques Lucke <jacques@blender.org>
Date:   Sun Jul 12 10:01:37 2020 +0200

    Functions: minor api improvements

commit ee5c2f6ead
Author: Antonio Vazquez <blendergit@gmail.com>
Date:   Sat Jul 11 20:41:21 2020 +0200

    GPencil: Replace "ShaderFX" with "Shader Effects" in RNA prop text

commit c7eada103c
Author: Jacques Lucke <jacques@blender.org>
Date:   Sat Jul 11 18:02:06 2020 +0200

    Nodes: support implicit conversions and incorrectly linked sockets

commit 06401157a6
Author: Jacques Lucke <jacques@blender.org>
Date:   Sat Jul 11 17:59:43 2020 +0200

    Fix: incorrect attribute type in network

commit 46b79b3d4a
Author: Jacques Lucke <jacques@blender.org>
Date:   Sat Jul 11 16:55:57 2020 +0200

    Nodes: support vector math node in simulation node tree

commit b920875893
Author: Jacques Lucke <jacques@blender.org>
Date:   Sat Jul 11 16:47:53 2020 +0200

    Nodes: support math node in simulation node tree

commit 8fae58ce0b
Author: Jacques Lucke <jacques@blender.org>
Date:   Sat Jul 11 16:39:17 2020 +0200

    Nodes: support Value node in simulation node tree

commit 16d4373158
Author: Jacques Lucke <jacques@blender.org>
Date:   Sat Jul 11 16:24:53 2020 +0200

    Nodes: move Math, Vector Math and Value shader nodes to c++ files

    This required a little bit of refactoring, because we were using c-only
    syntax for the gpu shader names. All tests are still passing.

commit 415d3ee05b
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Sat Jul 11 22:03:27 2020 +1000

    UV: add path select operator that uses the selection

    Instead of using the mouse cursor position,
    this selects between existing selected elements.

    Access this since picking a selection path doesn't
    work from the menu.

commit 6e698653df
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Sat Jul 11 20:34:17 2020 +1000

    Cleanup: remove unused function

commit 651db1b26f
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Sat Jul 11 15:10:05 2020 +1000

    Cleanup: spelling

commit 020e0f11ff
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Sat Jul 11 14:50:47 2020 +1000

    Docs: remove reference to PYTHONHOME

    This is no longer used by default, when '--python-use-system-env' is set
    there are many Python environment variables, don't list them in
    Blender's help message.

commit d2b910fafe
Author: Aaron Carlisle <carlisle.b3d@gmail.com>
Date:   Fri Jul 10 16:07:31 2020 -0400

    UI: UV: Add Select Shortest Path to menu

    This matches the 3D Viewport

commit 3dc0178390
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Fri Jul 10 20:00:20 2020 +0200

    Fix T78662: Cycles baking fails if denoising is enabled, after recent changes

    This is not supported yet.

commit 6fbacd6048
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Fri Jul 10 19:56:53 2020 +0200

    Fix build error building without OpenImageDenoise

commit 48f10319c6
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Fri Jul 10 18:40:35 2020 +0200

    Fix T78801: Eevee missing setting to enable/disable freestyle per view layer

    This was only visible when Cycles was enabled.

commit 4e8fc15586
Author: Hans Goudey <h.goudey@me.com>
Date:   Fri Jul 10 12:21:32 2020 -0400

    UI: Improve transform constraint layout

      - Remove the "mapping" subpanel and moves the source axis
        selection ot the destination subpanel.
      - Rename "Source" and "Destination" to "Map From" and "Map To" to
        make the action more clear
      - Gray out source axes when their data isn't selected.

      These changes were discussed in D8041.

commit 3e4f49fe71
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Fri Jul 10 18:02:51 2020 +0200

    Revert "Fix T78296: Performance - Use Binary Search for MDeformWeight"

    This reverts commit 39b525e0f0 and
    3121015dce as tests are failing.

commit d5208c45fa
Author: Antonio Vazquez <blendergit@gmail.com>
Date:   Fri Jul 10 17:56:05 2020 +0200

    GPencil: Fix unreported Use Falloff curve for active frame not working

    For the active frame it was using always a value of 1.0 and it was not using the curve.

commit 6eeb32706a
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Thu Jul 9 12:20:07 2020 +0200

    Cycles: support OpenImageDenoise in final renders

    Performance is not great currently due to the API not seeming to support
    efficient denoising of multiple tiles at the same time. So in many cases
    only one or a few threads will actually be denoising at the same time.

    In renders with many samples this is not a big problem, but for faster
    renders it's a signficant overhead.

    We should try to optimize this still, possibly by batching denoising of
    a bigger neighborhood of multiple tiles at once.

commit 93791381fe
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Thu Jul 9 20:01:22 2020 +0200

    Cleanup: reduce hardcoded numbers in denoising neighbor tiles code

commit e65c78cd43
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Thu Jul 9 18:54:42 2020 +0200

    Cleanup: minor refactoring in Cycles update detection code

commit ad45b8d6a4
Author: Milan Jaros <jar091>
Date:   Fri Jul 10 11:49:52 2020 +0200

    Cycles: optimize camera inside volume tests

    Only run when there are volumes in the scene, and compute in parallel.

    Ref T56939

    Differential Revision: https://developer.blender.org/D8261

commit d8e648c352
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Fri Jul 10 17:09:35 2020 +0200

    Fix T78776: Cycles OpenCL error after recent changes for holdouts

commit 9dbe9a753a
Author: Bastien Montagne <bastien@blender.org>
Date:   Fri Jul 10 16:50:26 2020 +0200

    Fix T78766: Blender crashes after deleting vertices with Custom Normals.

    Some core BMesh topology changing functions were not properly tagging
    custom normal runtime caches as dirty...

commit 5372924983
Author: Richard Antalik <richardantalik@gmail.com>
Date:   Fri Jul 10 16:14:10 2020 +0200

    Fix T78579: Proxy produces wrong preview when using Offset or Crop

    Make sure that proxy and original images are scaled to same size before
    applying offset or crop.

    During testing, I discovered, that raw cache will lose information whether
    this image was proxy or not. Because of this, proxy images will not create
    this cache type. It would be fairly easy to implement this functionality for
    cache, but I have decided to not do it now, because I did not want to pass yet
    another mostly hard-coded bool flag to cache system. Since image is proxy, it
    should be fast to read anyway.

    In case of using offset property, code was modified to make sure we scale
    image only once. I also tried to make code more readable and streamlined and
    cleaned up surrounding functions a bit.

    Reviewed By: brecht

    Differential Revision: https://developer.blender.org/D8203

commit 77f823a240
Author: Richard Antalik <richardantalik@gmail.com>
Date:   Fri Jul 10 15:57:28 2020 +0200

    Fix T78573: Crash when removing strips with prefetching

    Stop prefetching before changing content of seqbase.

    Reviewed By: brecht

    Differential Revision: https://developer.blender.org/D8256

commit 47e71f4623
Author: Richard Antalik <richardantalik@gmail.com>
Date:   Fri Jul 10 15:53:57 2020 +0200

    Fix T69440: Memory leak adding strips via python

    seq->strip was overwritten in python API function.

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8204

commit cbfedf2139
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 15:53:36 2020 +0200

    BLI: add C++ random number generator

    This adds `blender::RandomNumberGenerator` in `BLI_rand.hh`.
    Furthermore, `RNG` is now implemented in terms of this new generator.
    No functional changes are expected, the generated random numbers
    are not changed by this commit.

    Reviewers: campbellbarton, brecht

    Differential Revision: https://developer.blender.org/D8259

commit c2304d2f02
Author: Bastien Montagne <bastien@blender.org>
Date:   Fri Jul 10 15:29:03 2020 +0200

    Expose override flags to python RNA properties definition.

    Time will tell whether we need to expose more RNA override flags here.

    Implements/Fix T78534.

    Differential Revision: https://developer.blender.org/D8250

commit 4d1c3c029e
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 08:37:35 2020 +0200

    Cleanup: declaration and implementation function signature did not match

commit f93e0f1a9e
Author: Bastien Montagne <bastien@blender.org>
Date:   Fri Jul 10 15:23:52 2020 +0200

    Refactor override code to properly deal with runtime rna properties too.

    The triplet static RNA / runtime RNA / custom properties is a real pain to
    deal with...

    Using the new `PropertyRNAOrID` struct helps clarifying and properly
    dealing with all three cases.

    Note that this makes override of py-defined RNA properties working
    (support for that will be committed next).

    Differential Revision: https://developer.blender.org/D8249

commit 337e2c9029
Author: Bastien Montagne <bastien@blender.org>
Date:   Fri Jul 10 15:19:40 2020 +0200

    RNA: refactor how we get 'ensured' RNA properties.

    Introduce new PropertyRNAOrID structure, storing most useful data about
    an 'opaque' PropertyRNA in relation with a given PointerRNA struct.

    It deals with all the three cases (pure static RNA, runtime RNA where
    data is actually stored in IDProperties, and pure IDProperties, aka
    custom data.

commit 6c1157201a
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 22:59:12 2020 +1000

    Cleanup: simplify platform define checks

    Platforms besides WIN32 were in a single else clause, use elif instead.

commit 45287f909c
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 22:58:30 2020 +1000

    Fix for building on systems besides apple/windows/linux

commit 26d28ade26
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 14:40:23 2020 +0200

    Cleanup: follow code style

commit c806db6313
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 14:22:35 2020 +0200

    Functions: add utility to find dependencies of input sockets

commit 60133ff98d
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 14:20:39 2020 +0200

    Functions: store derived node tree and network in map for future access

commit 295b3aefb0
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 14:19:45 2020 +0200

    Functions: make constant folding work on unfinished networks

commit 7bae599232
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 14:18:51 2020 +0200

    Nodes: add redundant name check in debug builds to prevent errors

commit 3121015dce
Author: Jeroen Bakker <jeroen@blender.org>
Date:   Fri Jul 10 13:37:12 2020 +0200

    Fix Crash due to recent changes

    {39b525e0f07fa25dcda54226ade789959b642dec} could write in unallocated
    space.

commit 00eb6a56aa
Author: Antonio Vazquez <blendergit@gmail.com>
Date:   Fri Jul 10 13:30:08 2020 +0200

    GPencil: Fix tooltip error

    The tooltip was copied by error from Lattice modifier.

commit 8fd65a2252
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 12:56:57 2020 +0200

    Functions: use new is-equal and hash function of CPPType

commit 3edd2832b2
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 12:54:19 2020 +0200

    Functions: make generic types hashable

commit f62204718b
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 12:53:50 2020 +0200

    BLI: initial hash function for Color4b and float4x4

commit 8f6c0f2242
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 12:41:51 2020 +0200

    Functions: make generic types equality comparable

commit 52636c3059
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 12:36:06 2020 +0200

    Cleanup: various cleanups in for CPPType

commit 39b525e0f0
Author: Jeroen Bakker <jeroen@blender.org>
Date:   Fri Jul 10 12:05:31 2020 +0200

    Fix T78296: Performance - Use Binary Search for MDeformWeight

    Use binary search for querying deform weights.

    Spring 02_020_A.anim.blend on Ryzen 1700X goes from 12.4 to 12.7fps.

    During profiling it was detected that adding new items to the head was faster than adding to the tail.

    Reviewed By: Campbell Barton

    Differential Revision: https://developer.blender.org/D8127

commit 77a646279d
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 10 12:04:32 2020 +0200

    Cleanup: structure CPPType according to code style guide

commit 9c25731781
Author: Bastien Montagne <bastien@blender.org>
Date:   Fri Jul 10 11:53:11 2020 +0200

    LibOverride: Fix improper tagging of more of the backward pointers in RNA nodetrees.

commit 582a0b7e5a
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 19:02:18 2020 +1000

    Fix T78756: White UV drawing is displayed as Dashed

commit 7a9028cad1
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 18:58:36 2020 +1000

    Fix UV rip failing to disable proportional edit-mode

commit a148c4676b
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 16:04:09 2020 +1000

    Cleanup: spelling

commit 03f5acd445
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 16:03:12 2020 +1000

    Cleanup: clang-format

commit 8b660ea0ec
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 13:36:16 2020 +1000

    Fix UV path redo in vert/edge mode

    Redo was only working in some situations,
    some options were also not being forwarded.

commit 96068324cd
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 13:35:44 2020 +1000

    Fix BM_loop_at_index_find lookup

commit 89cb41faa0
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 12:55:59 2020 +1000

    UV: allow ripping face-regions

    This changes the behavior of rip when entire faces are selected.
    Now face regions are isolated and moved instead of ripping the edge-loop
    extracted from the selection boundary.

    This is a convenient alternative to separate selection & move.
    Resolves T78751.

commit 3fdd092649
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 12:38:28 2020 +1000

    Cleanup: face-center mesh calculation

    Loop over faces and calculate their centers instead of zeroing the
    face center array and accumulating all faces vertex corners.

    Move subsurf face center extraction into it's own loop since it works
    differently.

commit b0378440ce
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 12:18:43 2020 +1000

    Fix missing adjacent UV check for recent UV path select

    Path selection could cross UV islands if the destination element was
    on an island boundary.

commit 8f24ec2e26
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 12:04:29 2020 +1000

    Cleanup: add BLI_linklist_find_last

    This makes adding to the end of a linked list simpler,
    In most cases we avoid this in favor of BLI_linklist_append.

    For one off operations it's OK.

commit 3dd460aa7f
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 11:41:14 2020 +1000

    Cleanup: spelling

commit a0d3b60015
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 11:46:26 2020 +1000

    Cleanup: use FLT_MAX for the maximum path selection cost

    A large number below FLT_MAX was used to avoid overflow,
    however this doesn't cause any problems.

commit 0b77e2f4c4
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 11:31:41 2020 +1000

    Cleanup: variable names, use define for maximum path cost

commit 92bc277950
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Fri Jul 10 11:40:38 2020 +1000

    Cleanup: undeclared warnings

commit 3623db7784
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 9 19:03:50 2020 +0200

    BLI: add more operator overloads for float2

commit 03a00bda2b
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Thu Jul 9 17:16:24 2020 +0200

    Sculpt: Make Sculpt Vertex Colors features experimental

    This disables all Sculpt Vertex Colors tools, operators, panels and rendering capabilities and puts them under the "Use Sculpt Vertex Colors" experimental option.

    Reviewed By: brecht

    Differential Revision: https://developer.blender.org/D8239

commit 1e3247c078
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 9 18:19:39 2020 +0200

    Fix: add missing extern "C"

commit a90b69d065
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Thu Jul 9 18:04:13 2020 +0200

    Build: add more libc compatibility functions for upcoming libraries update

    These are needed by the x264 library.

commit 6778949e01
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Thu Jul 9 17:56:00 2020 +0200

    Fix repeated Face Sets IDs when joining meshes

    As Face Sets IDs start from 0 and increase by 1 each time a new face set
    is created in a mesh, when joining multiple meshes it could happen that
    the same ID is used by several unrelated areas in multiple objects. This
    checks the Face Sets IDs when joining meshes and ensures that they are
    not repeated between different objects when joining them, so in the
    resulting mesh all previous face sets will have different IDs.

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8224

commit 7b1c406b54
Author: Bastien Montagne <bastien@blender.org>
Date:   Thu Jul 9 15:33:34 2020 +0200

    Implement T77959: Never duplicate linked data during deep-copy.

    Note that this behavior is enforced on user level for now, but on code
    side it is controlled with a flag, which should make it easy to refine
    that behavior if needed.

    Only exception is when we duplicate a linked ID directly (then we assume
    user wants a local deep-copy of that linked data, and we always also
    duplicate linked sub-data-blocks).

    Note that this commit also slightly refactor the handling of actions of
    animdata, by simplifying `BKE_animdata_copy_id_action()` and adding an
    explicit new `BKE_animdata_duplicate_id_action()` to be used during ID
    duplication (deep copy).

    This also allows us to get rid of the special case for liboverrides.

commit 78b629a98f
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Wed Jul 8 18:10:31 2020 +0200

    Sculpt: Skip fully hidden nodes in sculpt tools

    As tools iterators skip not visible vertices, fully hidden nodes can
    also be skipped and considered as masked.

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8244

commit 1fb667da01
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Tue Jul 7 23:01:51 2020 +0200

    Fix wrong upate flag when updating the PBVH visibility

    This function was using the wrong flag to update the visibility state of
    the nodes, so I assume that most of the partially visible optimizations
    were not working.

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8243

commit e5ebaa9fd6
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Wed Jul 8 17:22:11 2020 +0200

    Fix T78664: Implement Mesh and Face Set boundary automasking in Multires

    This implements the SCULPT_vertex_is_boundary and SCULPT_vertex_has_unique_face_set functions for PBVH_GRIDS, which makes features such as automasking now work in multires. It also fixes some other face sets related features in multires, like face set boundary smoothing.

    This uses the BKE_subdiv_ccg_coarse_mesh_adjacency_info_get function to get the vertex indicies in the base mesh from multires. This way the API functions can get topology or face set information directly from it. In the future, these vertex indices can be used to get any other information from the base mesh from multires, like seams, sharp edges, disconnected elements IDs...

    Reviewed By: sergey

    Maniphest Tasks: T78664

    Differential Revision: https://developer.blender.org/D8227

commit bd84b2cbcc
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Sat Jul 4 18:28:40 2020 +0200

    Fix Sculpt Vertex Colors sample color changing brush alpha

    It is not practical to change the alpha of the paint color with the
    color picker as with the current brush design alpha is the main strength
    control for the brush.

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8208

commit 13b1374497
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Thu Jul 9 17:41:04 2020 +0200

    Fix crash when using Mask by Color in Multires

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8207

commit 78d48343ae
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Thu Jul 9 15:59:57 2020 +0200

    Make deps: Fix compilation error on CentOS

    There were two issues.

    First is related on ISPC's CMake configuration forcing C and C++
    compilers to be clang and clang++. This goes against of desired
    behavior when we use our own compiled clang compilers.

    The second issue was related on linker failure: CLang libraries
    are linked statically, and they need some of C++ 11 STL symbols
    which are coming from libstdc++.

    Differential Revision: https://developer.blender.org/D8258

commit 2be0ae7c99
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Thu Jul 9 16:51:48 2020 +0200

    Fix Cycles unnecessary updates to camera in viewport render

    Problem identified by Milan Jaros.

commit 9de09220fc
Author: Szymon Ulatowski <szulat>
Date:   Thu Jul 9 17:19:52 2020 +0200

    EEVEE: Implement the missing Sky texture

    I'm not sure if the Sky was deliberately left out or was just waiting for a
    better moment, but so many I was disappointed that Sky in EEVEE is
    completely white.

    There are already 2 implementations (osl and gpu) so this is the third one.
    Looking at other cases it seems that we are not supposed to share sources
    between cycles and the rest? So the new util_sky_model files are just
    copies of what is already in cycles, except that the data file uses the RGB
    variant of the Hosek/Wilkie model, because we output RGB anyway (but can be
    easily changed to XYZ if desired - the results are nearly identical).
    I am not sure if it is okay to pass 3*9 float values as 3 mat4 uniforms (I
    wanted to use mat3 but it does not work).
    Also, should I cache the sky model data between renders if the parameters
    do not change?

    Reviewed By: fclem, brecht

    Differential Revision: https://developer.blender.org/D7108

commit 42c99ec15b
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 9 16:37:44 2020 +0200

    BLI: rename rand.c to rand.cc

commit 580d50091c
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 9 15:40:27 2020 +0200

    Particles: Create a simulation state for every Particle Simulation node

    Every Particle Simulation node has a name (or a path when it is in a node group).
    This name has to be used in the Simulation modifier on a point cloud to see
    the particles.

    Caching has been disabled for now, because it was holding back development
    a bit. To reset the simulation, go back to frame 1.

    Currently, there is no way to influence the simulation. There are just some
    randomly moving points. Changing that is the next step.

commit 31ad43a3c7
Author: Jacques Lucke <jacques@blender.org>
Date:   Thu Jul 9 15:29:25 2020 +0200

    Blenloader: make BLO_read_data_address work in C++

commit 544c435fdd
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Thu Jul 9 12:20:07 2020 +0200

    Fix T78745: Cycles error baking with multiple materials

commit 8ddf7556a5
Author: Bastien Montagne <bastien@blender.org>
Date:   Thu Jul 9 11:44:11 2020 +0200

    Fix T78718: Crash when deleting particle system modifier with the X Shortcut.

    Duplication and deletion code of modifiers was totally wrong for
    particle system, that special weird thing needs its own custom
    management.

    Note that for now I chose not to duplicate the particle settings ID when
    duplicating the modifier...

commit ea5fe7abc1
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Tue Jul 7 17:29:17 2020 +1000

    UV: path selection support

    This adds support for path selection for vertex edge & face selection
    modes, matching mesh editing behavior, useful with the UV rip tool.

    Region select & edge tagging are currently not supported,
    although they could be added eventually.

commit 0b8221683f
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Thu Jul 9 18:23:16 2020 +1000

    BMesh: add utility functions

    - BM_edge_uv_share_vert_check
    - BM_face_uv_calc_center_median_weighted
    - BM_loop_at_index_find

commit 0b3bf69d3c
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Thu Jul 9 13:33:15 2020 +1000

    Cleanup: move BMesh UV queries into their own file

commit 754c5d6a14
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Thu Jul 9 13:29:48 2020 +1000

    Cleanup: clang-format

commit 31bc76ea4e
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 22:29:10 2020 +0200

    Cleanup: remove unnecessary calls to as_span

    This uses the new implicit conversions and constructors
    that have been committed in the previous commit.

    I tested these changes on Linux with gcc and on Windows.

commit 403384998a
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 22:27:25 2020 +0200

    BLI: improve constructors and conversions to span

    This allows us to avoid many calls to `as_span()` methods. I will
    remove those in the next commit. Furthermore, constructors
    of Vector and Array can convert from one type to another now.

    I tested these changes on Linux with gcc and on Windows.

commit 4b85ed819d
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 20:41:00 2020 +0200

    Cleanup: remove unused function

    This is not necessary in C++17 anymore.

commit f7d5d4ee3b
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 20:39:12 2020 +0200

    Cleanup: use c++17 helper variable templates

commit e4926c167b
Author: Bastien Montagne <bastien@blender.org>
Date:   Wed Jul 8 18:08:08 2020 +0200

    Fix T78718: Crash when deleting particle system modifier with the X Shortcut.

    Again those backward pointers not properly flagged in RNA, hence
    generating infinite loops.

commit f4a39cafa1
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 17:05:40 2020 +0200

    Functions: add AttributesRef class

    This is the same as MutableAttributesRef, but the data in it cannot be changed.

commit 439c238bb4
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 17:04:50 2020 +0200

    Cleanup: use different internal socket name

commit 05365d1376
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 17:04:09 2020 +0200

    Functions: support hashing MFDataType and CPPType

commit 2de5de57c5
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Wed Jul 8 15:03:06 2020 +0200

    Build: fix stack linker warning with ffmpeg on macOS

    The ff_cfhd_init_vlcs() function was using a lot of stack space, which
    made linker on macOS unhappy. Using heap allocation allows to silence
    the warning without causing other side-effects.

    Kept the patch enabled for all platforms to avoid difference in behavior
    and performance on different platforms, which could make certain types
    of investigation very tricky.

    Differential Revision: https://developer.blender.org/D8248

commit cb3c4218bf
Author: Bastien Montagne <bastien@blender.org>
Date:   Wed Jul 8 15:43:57 2020 +0200

    Minor cleanup in rna override code.

commit d1f4546a59
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 15:10:24 2020 +0200

    Functions: implement common subnetwork elimination optimization

    This was the last of the three network optimizations I developed in
    the functions branch. Common subnetwork elimination and constant
    folding together can get rid of most unnecessary nodes.

commit e3e42c00cb
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 15:06:32 2020 +0200

    Functions: Support getting MFSocket based on its id

commit 2b9d62b73a
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 15:06:04 2020 +0200

    Functions: Support accessing socket index of MFSocket

commit 34d175f372
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 15:04:28 2020 +0200

    Functions: initial hash/equals implementation for constant multi-functions

commit 840941215d
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 15:02:47 2020 +0200

    Functions: allow multi-functions to override a hash and equals function

commit 36a547af7b
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 15:01:33 2020 +0200

    Cleanup: add correct license header to tests

commit ff133bbd33
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 14:57:31 2020 +0200

    BLI: add disjoint set data structure

    This can be used to find separate islands in meshes efficiently (as is
    done in cycles already). Furthermore, this helps to implement some
    algorithms on node trees more efficiently.

commit a8ff8b64dc
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 14:40:34 2020 +0200

    BLI: add comparison operators and hash functions for float3, etc.

commit ff444da7c4
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Thu Jul 2 12:28:57 2020 +0200

    macOS: upgrade minimum required version to 10.13 High Sierra

    C++17 does not work on 10.12, and Apple extended support ended for 10.12 in
    October 2019.

    Maniphest Tasks: T76783, T76184

    Differential Revision: https://developer.blender.org/D8179

commit 6435acd8f6
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Wed Jul 8 12:57:59 2020 +0200

    Cycles: support shader transparency for holdout objects

    Now transparent areas of the object will render objects behind.

    Fixes T78728.

commit 643196cc37
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Wed Jul 8 11:04:49 2020 +0200

    CMake: Fix spelling of Embree passed to find package

    The spelling and capitalization of package name passed to find_package()
    and find_package_handle_standard_args() needs to match.

    Silences CMake warning about mismatch.

    Differential Revision: https://developer.blender.org/D8247

commit 45004d82e0
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 11:18:43 2020 +0200

    Functions: add dead node removal and constant folding optimization

    Those optimizations work on the multi-function network level.
    Not only will they make the network evaluation faster, but they also
    simplify the network a lot. That makes it easier to understand the
    exported dot graph.

commit 50d7c00d9c
Author: Jacques Lucke <jacques@blender.org>
Date:   Wed Jul 8 10:16:56 2020 +0200

    Cleanup: fix comment

commit 01c8aa12a1
Author: Alexander Gavrilov <angavrilov@gmail.com>
Date:   Wed Jul 1 17:38:07 2020 +0300

    Apply Modifier: support applying as shape key and keeping the modifier.

    This can be useful to save the result of a cloth simulation as a
    shape key without destroying the simulation, so it's possible to
    e.g. re-run it to get other shapes, or simply use the new shape
    key to start the simulation already in a draped state.

    It also makes sense to allow applying as shape key even when the
    mesh is shared, because the operation itself just adds a shape
    key. To support this, split the apply operator into Apply and
    Apply As Shapekey so that they can have different poll callbacks.

    Differential Revision: https://developer.blender.org/D8173

commit 7fcb6bc59c
Author: Lukas Stockner <lukas.stockner@freenet.de>
Date:   Wed Jul 8 02:10:02 2020 +0200

    Fix T78324: Different Sky Texture results between CPU and GPU

    The problem here was numerical precision: The code calculates the angle between
    sun and view direction, and the usual acos(dot(a, b)) approach for that has
    poor numerical performance for almost parallel angles.

    As a result, the generally tiny difference between floating point computation
    between CPU and GPU was enough to make the sun vanish at different radii,
    causing different results.

    The new version fixes the difference by making the computation much more robust
    on both platforms.

commit afcb41a0aa
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 20:32:40 2020 +0200

    BLI: simplify copy constructor of Array

commit eb5fb1741d
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 20:29:35 2020 +0200

    Cleanup: don't end description with a '.'

commit 8713109212
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 20:27:34 2020 +0200

    Cleanup: fix typo

commit 902ee4d13c
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 19:46:10 2020 +0200

    Functions: cleanup loop that traverses the MFNetwork

commit 22158162ef
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 19:34:35 2020 +0200

    Functions: add generic functions that output constants

commit f4633cf46c
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 19:16:31 2020 +0200

    BLI: simplify copy constructor of vector

commit 67042aa6a1
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 18:45:34 2020 +0200

    Functions: extend multi-function network api

commit adfae89f96
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 18:40:42 2020 +0200

    BLI: provide access to underlying node in dot exporter

commit a8627ea66d
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 18:39:24 2020 +0200

    Functions: Add debug print and destruct callback to CPPType

commit 4990e4dd01
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 18:23:33 2020 +0200

    Nodes: Generate multi-function network from node tree

    This adds new callbacks to `bNodeSocketType` and `bNodeType`.
    Those are used to generate a multi-function network from a node
    tree. Later, this network is evaluated on e.g. particle data.

    Reviewers: brecht

    Differential Revision: https://developer.blender.org/D8169

commit ff97545c50
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Tue Jul 7 18:37:35 2020 +0200

    Fix T75943 EEVEE: Cubemaps shows black

    Caused by faulty driver implementation. Force fallback method.

commit 1e2ff4f81b
Author: Hans Goudey <h.goudey@me.com>
Date:   Tue Jul 7 11:10:42 2020 -0400

    Cleanup: Add braces for clang tidy

commit 0edf2fc128
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Tue Jul 7 16:51:03 2020 +0200

    BLI: Correct spin lock definition

    The MSVC atomic function is defined for an unsigned type.

    Not sure why this became an issue after switch to TBB by default,
    maybe some CFLAGS changed to be more strict after that.

commit dad3de89dc
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Tue Jul 7 11:27:09 2020 -0300

    Fix: remove accidental code

    `v1` and `v2` are already set.

commit d352902758
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Tue Jul 7 11:16:31 2020 +0200

    Make deps: Use own nasm for ffmpeg and x264

    Fixes the warning: building for macOS, but linking in object file

    Differential Revision: https://developer.blender.org/D8235

commit 1e3c0b4b03
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Tue Jul 7 10:47:09 2020 +0200

    Make deps: Compile own version of nasm for Apple

    The upstream version of nasm does not put version information to the
    generated object files, which makes linker to show the following
    warning:

      building for macOS, but linking in object file

    Using own patched version of nasm which puts required information to
    the object file, making linker happy.

    The plan is to either streamline the patch and provide it to the
    upstream, or, it that takes too long, get an independent fix from the
    upstream.

commit 202e7ccaae
Author: Jeroen Bakker <j.bakker@atmind.nl>
Date:   Mon Jul 6 14:33:59 2020 +0200

    Fix T77455: Blender Freezes when using the 3d Scale Gizmo

    Issue is reported on Linux ith Intel HD6xx iGPU. Inside
    `gpu_select_sample_query.c` the call to `glGetQueryObjectuiv` froze. After
    bisecting this lead to the polyline shader. When using a 3d color shader
    in stead of the polyline shader during selection seems to fix the issue.

    Other parts of blender might also be effective, but I wasn't able to
    freeze blender in these areas. When it does, we might want to add
    a similar work-around to button2d, cage2d, cage3d & move3d, navigate.

    Backport this patch to 2.83.

    Reviewed By: Clément Foucault

    Differential Revision: https://developer.blender.org/D8217

commit d1dcd2b464
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Tue Jul 7 16:17:36 2020 +0200

    BLI: Fix mistake in SpinLock TBB migration

    Copy-paste mistake.

commit 20558848d3
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Tue Jul 7 09:45:53 2020 -0300

    Optimization: use `BLI_bvhtree_intersect_plane` to detect faces that will be affected by the knife tool

    The knife code currently calls the `BLI_bvhtree_overlap` function that
    tests the overlap between the mesh tree and an AABB that encompasses the
    points projected in the clip_start, clip_end and or clip_planes of the
    view.

    This resulted in many false positives since the AABB is very large.
    Often all the triangles "overlapped".

    The solution was to create a new function that actually tests the
    intersection of AABB with a plane.

    Even not considering the clip_planes of the view, this solution is more
    appropriate than using overlap.

    Differential Revision: https://developer.blender.org/D8229

commit 630c6226e2
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Tue Jul 7 16:26:01 2020 +0200

    Fix T78307 UI: Drawing artifacts in the Blender UI on macOS

    This was due to a bad driver which was not respecting this bit of the
    specification:

    `If the current primitive does not originate from an instanced draw command, the value of gl_InstanceID is zero.`

commit 737bd549b6
Author: Patrick Mours <pmours@nvidia.com>
Date:   Mon Jul 6 12:25:54 2020 +0200

    Cycles: Add support for native OptiX curve primitive

    This patch adds support for the curve primitive from OptiX to Cycles. It's currently hidden
    behind a debug option, since there can be some slight rendering differences still (because no
    backface culling is performed and something seems off with endcaps). The curve primitive
    was added with the OptiX 7.1 SDK and requires a r450 driver or newer, so this also updates
    the codebase to be able to build with the new SDK.

    Reviewed By: brecht

    Differential Revision: https://developer.blender.org/D8223

commit 95f0f31279
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Tue Jul 7 14:45:31 2020 +0200

    Fix T78692: improve UI regarding the effect of the denoiser on denoising passes

    It wasn't obvious that the choice of Cycles denoiser also generates different
    denoising data passes for compositing.

commit a394aac8b4
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Tue Jul 7 14:47:59 2020 +0200

    Fix T78666: Cycles non-uniformly scaled hair renders wrong for static objects

    Don't apply the matrix transform optimization in this case, curve points and
    radius can't represent non-uniform scale the way is possible with triangle
    meshes and vertices.

    This would cause abrupt change if objects had e.g. motion blur in one frame
    and not in the next.

commit 98bee41c8a
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Tue Jul 7 14:30:55 2020 +0200

    IO: Reversed persistent ID order in exports to Alembic and USD

    Each duplicated (a.k.a. instanced) object has a Persistent ID, which
    identifies a dupli within the context of its duplicator. This ID
    consists of several numbers when there are nested duplis (for example a
    mesh instancing empties on its vertices, where each empty instances a
    collection). When exporting to Alembic/USD, these are used to uniquely
    name the duplicated objects in the export.

    This commit reverses the order of the persistent ID numbers, so that the
    first number identifies the first level of recursion. This produces
    trees like this:

        ABC
         `--Triangle
             |--Triangle
             |--Empty-1
             |    `--Pole-1-0
             |        |--Pole
             |        `--Block-1-1
             |            `--Block
             |--Empty
             |    `--Pole-0
             |        |--Pole
             |        `--Block-1
             |            `--Block
             |--Empty-2
             |    `--Pole-2-0
             |        |--Pole
             |        `--Block-2-1
             |            `--Block
             `--Empty-0
                 `--Pole-0-0
                     |--Pole
                     `--Block-0-1
                         `--Block

    It is now clearer that `Pole-2-0` and `Block-2-1` are instanced by
    `Empty-2`. Before this commit, they would have been named `Pole-0-2` and
    `Block-1-2`.

commit 70b1c09d7a
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Tue Jul 7 12:45:30 2020 +0200

    IO: Fix bug exporting dupli parent/child relations

    Exporting a scene to USD or Alembic would fail when there are multiple
    duplicates of parent & child objects, duplicated by the same object. For
    example, this happens when such a hierarchy of objects is contained in a
    collection, and that collection is instanced multiple times by mesh
    vertices. The problem here is that the 'parent' pointer of each
    duplicated object points to the real parent; Blender would not figure
    out properly which duplicated parent should be used.

    This is now resolved by keeping track of the persistent ID of each
    duplicated instance, which makes it possible to reconstruct the
    parent-child relations of duplicated objects. This does use up some
    memory for each dupli, so it could be heavy to export a Spring scene
    (with all the pebbles and leaves), but it's only a small addition on top
    of the USD/Alembic writer objects that have to be created anyway. At
    least with this patch, they're created correctly.

    Code-wise, the following changes are made:

    - The export graph (that maps export parent to its export children) used
      to have as its key (Object, Duplicator). This is insufficient to
      correctly distinguish between multiple duplis of the same object by
      the same duplicator, so this is now extended to (Object, Duplicator,
      Persistent ID). To make this possible, new classes `ObjectIdentifier`
      and `PersistentID` are introduced.
    - Finding the parent of a duplicated object is done via its persistent
      ID. In Python notation, the code first tries to find the parent
      instance where `child_persistent_id[1:] == parent_persistent_id[1:]`.
      If that fails, the dupli with persistent ID `child_persistent_id[1:]`
      is used as parent.

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8233

commit f2175e06a7
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Tue Jul 7 12:43:18 2020 +0200

    Mae deps: Ensure Brotli is disabled for FreeType

    We don't need it and it was optionally enabled, causing Blender to fail
    to link on certain configuration (when Brotli is installed via Homebrew
    for example).

commit 02cd159539
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 12:31:10 2020 +0200

    Cleanup: add comment explaining operator delete

commit cc311e4a52
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Tue Jun 30 15:13:54 2020 +0200

    IO: print export name instead of object name in debug export graph output

    This is just a change in `AbstractHierarchyIterator::debug_print_export_graph()`
    to aid in debugging. It'll make it possible to distinguish between
    different duplicates of the same object.

    No functional changes to Blender itself.

commit 5761cb9ee2
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 11:52:45 2020 +0200

    Guarded Allocator: add missing operator delete

    This resolves warning C4291 on windows.

commit 80fe5e1b15
Author: Johan Walles <walles>
Date:   Tue Jul 7 11:09:31 2020 +0200

    UI: Add units to motion tracking solve errors

    The unit being "pixels".

    Before this change the solve errors were unitless in the UI.

    With this change in place, the UI is now clear on that the unit of the
    reprojection errors is pixels (px).

    Differential Revision: https://developer.blender.org/D8000

commit 6d9a6f12b3
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Tue Jul 7 10:06:14 2020 +0200

    Make deps: Fix compilation error of Python on macOS

    The configuration was confused about gettext installed via Homebrew
    and isysroot passed to Python's compilation but not to test programs.

    After this change `import gettext` still works, but it is unclear how
    to test it further,

    Differential Revision: https://developer.blender.org/D8231

commit 955abbeff2
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 09:01:01 2020 +0200

    Fix sign conversion error

commit e233ee1c1f
Author: Philipp Oeser <info@graphics-engineer.com>
Date:   Thu Jun 25 14:37:22 2020 +0200

    Fix T78186: Dyntopo panel error with tools that dont have a brush

    Maniphest Tasks: T78186

    Differential Revision: https://developer.blender.org/D8120

commit 19d4e265b6
Author: Jacques Lucke <jacques@blender.org>
Date:   Tue Jul 7 10:35:28 2020 +0200

    Cleanup: remove redundant comments

    Searching in these files for "_as" will reveal a comment at the
    top, that explains what these methods are for. There is no need
    to duplicate that knowledge all over the place.

commit 6e609f0eb0
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Tue Jul 7 17:50:33 2020 +1000

    Cleanup: use doxy comments

commit 62774baded
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Tue Jul 7 16:06:05 2020 +1000

    UI: add merge/split menus

    This makes the menus and keymap match the edit-mesh
    (M for merge, Alt-M for split).

commit d212b3dc43
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Mon Jul 6 15:28:19 2020 +0200

    Make deps: Fixes for macOS platform

    Set of fixes which had to be made in order to have dependencies built
    on own laptop:

    - Require bison as a dependent software. It is required by ISPC.

      On macOS it is required to be installed via Homebrew. This is because
      Bison from Xcode toolchain is too old.

    - Made sure Boost is compiled using clang.

      Without this gcc was used, and some unsupported command line argument
      was passed to it.

    - Modify OGG in a way which does in fact pull fixed sized types.
      They are defined in stdint.h.

      Without this fix FFmpeg will not detect presence of OGG because the
      test program fails to compile.

    - Force disable zstd compression and make wepb optional for the TIFF
      library. Without this TIFF might pick up development libraries from
      Homebrew.

    Differential Revision: https://developer.blender.org/D8221

commit b28683b8b5
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Tue Jul 7 16:03:26 2020 +1000

    Cleanup: remove unused arguments

commit 0c58970da7
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Tue Jul 7 12:44:47 2020 +1000

    Cleanup: spelling

commit ad0edc626d
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Tue Jul 7 12:43:45 2020 +1000

    Cleanup: unused World struct members linfac, logfac

commit e20171e59f
Author: Hans Goudey <h.goudey@me.com>
Date:   Mon Jul 6 16:39:28 2020 -0400

    Fix build error with tests for removed functions

    These GHash functions were removed in 12817083ec,
    so the tests should be removed too.

commit d557f05502
Author: Hans Goudey <h.goudey@me.com>
Date:   Mon Jul 6 16:07:54 2020 -0400

    Cleanup: Use bool instead of int

commit 053e0c0af3
Author: Hans Goudey <h.goudey@me.com>
Date:   Mon Jul 6 15:35:21 2020 -0400

    UI: Add shortcuts for shader effect panels

    Only the delete shortcut applies here, although the move up and down
    operators can optionally be assigned in the keymap.

    See rB1fa40c9f8a81 for more details and rB5d2005cbb54b for the
    grease pencil modifier panel implementation, which is the same.

commit 12817083ec
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Mon Jul 6 14:44:30 2020 -0300

    Cleanup: Use the BLI_edgehash API in the sewing simulation of cloths

    Also remove the code in the ghash that is no longer used.

    This change simplifies the existing code.

    Differential Revision: https://developer.blender.org/D8219

commit a856de700b
Author: Hans Goudey <h.goudey@me.com>
Date:   Mon Jul 6 13:17:07 2020 -0400

    Fix T77730: ShaderFx Missing Update Notifier

    This adds a notification type for shaderfx so the properties editor can
    be properly notified to redraw.

    Another possible solution would be to also redraw the shaderfx tab
     with a ND_MODIFIER update, but this solution allows us to avoid
     some unecessary redraws too. There were no existing cases of
    ND_OBJECT | NC_MODIFIER updates, so those cases were
    removed from buttons_area_listener.

    Differential Revision: https://developer.blender.org/D8159

commit f6f4043924
Author: Jacques Lucke <jacques@blender.org>
Date:   Mon Jul 6 17:59:04 2020 +0200

    BLI: add methods to lookup a stored key in a set

commit 1562c9f031
Author: Patrick Mours <pmours@nvidia.com>
Date:   Mon Jul 6 17:32:32 2020 +0200

    Fix OptiX viewport denoising not working when rendering scene (without OptiX) that uses unsupported features

    Denoising devices do not need to load the full feature set of kernels, so only activate the denoising
    feature for them (so that it is possible to use features that are supported by the render devices, but
    not the denoising devices).

commit aabfd2fb9b
Author: Bastien Montagne <bastien@blender.org>
Date:   Mon Jul 6 16:55:00 2020 +0200

    Cleanup: readfile: remove old deprecated OldNewMap for runtime caches.

commit ee3eba902a
Author: Bastien Montagne <bastien@blender.org>
Date:   Mon Jul 6 16:21:41 2020 +0200

    Runtime cache preservation during undo: add support for nodes and embedded IDs.

commit bfc644dcfb
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Mon Jul 6 16:52:28 2020 +0200

    Reduce `DupliObject::persistent_id` from 16 to 8 items

    For historical reasons, `DupliObject::persistent_id` was of size
    `2*MAX_DUPLI_RECUR`. These reasons are now gone, and the persistent ID
    always gets exactly one array element for every dupli-recursion.

    Differential Revision: https://developer.blender.org/D8222

    Reviewed by: brecht

commit 0b07f9b717
Author: Bastien Montagne <bastien@blender.org>
Date:   Mon Jul 6 15:07:12 2020 +0200

    Fix T78608: Memory leak in Material properties: "Data from SCE".

    Caused by recent own refactor of cache presevation handling in readfile,
    EEVEE's lightcache are weird birds that can also be saved in .blend
    files, need a special handling for those 'persistent' caches...

commit 99feb10b8b
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Mon Jul 6 23:01:36 2020 +1000

    Cleanup: warning, spelling

commit 20446f07f6
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Mon Jul 6 22:52:29 2020 +1000

    Docs: reference bl_rna_get_subclass_py instead of bl_rna_get_subclass

    bl_rna_get_subclass only works for Nodes at the moment.

commit ffaf294c3f
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Mon Jul 6 14:53:39 2020 +0200

    Fix alignment/size issue on ARM/RPi architecture

    Addresses 964305 from Debian bug tracker.

commit 924578ce19
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Mon Jul 6 09:49:00 2020 -0300

    Optimization: Don't compute the snap to face on the knife tool twice

    Both `knife_find_closest_vert` and `knife_find_closest_edge` call
    `knife_find_closest_face`. Thus, running the raycast twice and setting
    values like `kcd->curr.bmface` and `kcd->curr.is_space` repeatedly.

    So:
    - separate `knife_find_closest_face` from `knife_find_closest_vert` and `knife_find_closest_edge`.
    - rename `knife_find_closest_vert` to `knife_find_closest_vert_of_face`
    - rename `knife_find_closest_edge `to `knife_find_closest_edge_of_face`.
    - do not set parameters previously set.

    Differential Revision: https://developer.blender.org/D8198

commit 073c426900
Author: Germano Cavalcante <germano.costa@ig.com.br>
Date:   Mon Jul 6 09:03:33 2020 -0300

    Fix faces disappearing when AutoMerge & Split

commit c632cf9ccd
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Mon Jul 6 21:23:35 2020 +1000

    Fix UV select separate not refreshing the display

commit 2c0cab03ca
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Mon Jul 6 21:14:12 2020 +1000

    UV: add rip region to toolbar

commit dbe171fb26
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Mon Jul 6 21:03:45 2020 +1000

    Cleanup: spelling, comments

commit 18b6c49a90
Author: Jacques Lucke <jacques@blender.org>
Date:   Mon Jul 6 12:37:11 2020 +0200

    Cleanup: rename namespace TimeIt to timeit

    According to our style guide, namespaces should have
    lower case names.

commit 572c48cf98
Author: Jacques Lucke <jacques@blender.org>
Date:   Mon Jul 6 09:08:53 2020 +0200

    BLI: improve exception safety of memory utils

    Even if we do not use exception in many places in Blender, our core C++ library
    should become exception safe. Otherwise, we don't even have the option
    to work with exceptions if we decide to do so.

commit 703a73fa84
Author: Jacques Lucke <jacques@blender.org>
Date:   Mon Jul 6 10:56:26 2020 +0200

    BLI: refactor how buffers for small object optimization are stored

    Previously, there was an error when operator-> was returning an
    invalid type. See error C2839.

commit 80393a0eba
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Mon Jul 6 17:41:36 2020 +1000

    UV: add rip tool

    New rip tool matching edit-mesh rip functionality.

    Useful as disconnecting UV's, especially for loops is inconvenient
    without this.

    This uses 'V' to rip, changing stitch to 'Alt-V'.

commit 9353477383
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Mon Jul 6 17:41:17 2020 +1000

    BMesh: add BM_face_calc_uv_cross

commit b51b893df8
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Mon Jul 6 17:40:55 2020 +1000

    BMesh: add BM_loop_other_vert_loop_by_edge

commit 705015e0a4
Author: Jeroen Bakker <j.bakker@atmind.nl>
Date:   Mon Jul 6 10:21:14 2020 +0200

    Fix T78481: Workbench Shadow effects XRay

    When in XRay some effects (shadow, cavity & depth of field) aren't supported.
    This patch makes sure that these effects aren't enabled.

commit 4f3045999d
Author: Campbell Barton <ideasman42@gmail.com>
Date:   Mon Jul 6 17:35:41 2020 +1000

    Cleanup: warnings, spelling

commit 0f617cd67e
Author: Jeroen Bakker <j.bakker@atmind.nl>
Date:   Mon Jul 6 07:45:10 2020 +0200

    GPU: Remove local shaders workaround for Intel/Windows

    It has been tested that local shaders workaround isn't needed for the
    latest Windows/Intel 6xx GPU's.

    Currently the local shaders workaround doesn't work anymore during the
    investigation it was detected that the intel drivers didn't need it
    anymore.

    Local shaders should still be fixed as it is also used for some legacy
    iGPU's. The current work around crashes when doing preview renders in
    EEVEE as the default materials aren't available but for the work around
    they should. (See T77346 for more information)

commit baf124c753
Author: Aaron Carlisle <carlisle.b3d@gmail.com>
Date:   Sun Jul 5 16:45:56 2020 -0400

    RNA Manual Reference: Update links

commit 247a28f242
Author: Jacques Lucke <jacques@blender.org>
Date:   Sun Jul 5 15:08:26 2020 +0200

    Revert "BLI: refactor how buffers for small object optimization are stored"

    This reverts commit 5d79f9f276.

    This was introducing build errors in windows. Need a bit more time to check it.

commit 5d79f9f276
Author: Jacques Lucke <jacques@blender.org>
Date:   Sun Jul 5 16:30:26 2020 +0200

    BLI: refactor how buffers for small object optimization are stored

commit 464aaf2701
Author: Antonio Vazquez <blendergit@gmail.com>
Date:   Sat Jul 4 17:31:02 2020 +0200

    Fix T78603: GPencil Noise modifier Vertex Group influence filter missing

    This was removed by error during the last refactor of modiifers.

commit 169bb4b9ce
Author: Jacques Lucke <jacques@blender.org>
Date:   Sat Jul 4 17:28:05 2020 +0200

    BLI: fix mistake in move constructor of Stack

commit 8e97694c8a
Author: Julian Eisel <julian@blender.org>
Date:   Sat Jul 4 17:06:57 2020 +0200

    Fix T78588: Material preview not visible in selection list

    Logic to determine if the library icon should be used was too general.

commit 9168ea8aab
Author: Antonio Vazquez <blendergit@gmail.com>
Date:   Sat Jul 4 11:15:11 2020 +0200

    Cleanup: Fix small typo error

commit 17603816f2
Author: Antonio Vazquez <blendergit@gmail.com>
Date:   Sat Jul 4 11:04:21 2020 +0200

    GPencil: Cleanup some comments typo

commit b0da78084b
Author: Clément Foucault <foucault.clem@gmail.com>
Date:   Sat Jul 4 01:27:12 2020 +0200

    UI: Attempt to fix OSX widget shader issue

    Some OSX GL driver implementation needs a dummy vbo read. This fixed issues
    with the Hair shaders in the past.

    Related to T78307

commit cad98923d0
Author: Richard Antalik <richardantalik@gmail.com>
Date:   Sat Jul 4 01:02:54 2020 +0200

    Cleanup: spelling

commit ea65c6a153
Author: Richard Antalik <richardantalik@gmail.com>
Date:   Sat Jul 4 00:59:09 2020 +0200

    Fix T78433: Adding Fade Generates Python Exception

    This was caused by typo in rB67a822e08684.

commit 4bf56b37ca
Author: Nathan Craddock <nzcraddock@gmail.com>
Date:   Fri Jul 3 13:31:42 2020 -0600

    Cleanup: Use C-style comments in outliner files

    No functional changes. Convert all C++ style comments to C comments.
    Also capitalize and add full stops.

    The comments themselves were not cleaned up. Some could be removed or
    reworded.

commit 59ef43147e
Author: Nathan Craddock <nzcraddock@gmail.com>
Date:   Fri Jul 3 12:48:00 2020 -0600

    Cleanup: Remove unused outliner activation code

    No functional changes. Remove commented calls to extern_set_butspace
    and unused text activation code.

commit 57a48bd0ca
Author: Nathan Craddock <nzcraddock@gmail.com>
Date:   Fri Jul 3 12:36:09 2020 -0600

    Cleanup: Use _fn suffix for outliner button callbacks

    No functional changes. Use _fn instead of _cb.

commit d7dbf90a02
Author: Sebastian Parborg <darkdefende@gmail.com>
Date:   Fri Jul 3 21:22:41 2020 +0200

    Clang-tidy: Enable braces-around-statements warning

commit 185fe9cd8b
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Fri Jul 3 18:55:32 2020 +0200

    Cleanup: compiler warning

commit 46fcc12e83
Author: Brecht Van Lommel <brecht@blender.org>
Date:   Fri Jul 3 18:54:04 2020 +0200

    Fix error in new Hair data type file reading

commit d2db481dc7
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 18:04:40 2020 +0200

    Cleanup: Blendkernel, Clang-Tidy else-after-return fixes (incomplete)

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/blenkernel` module. Not all warnings are
    addressed in this commit.

    No functional changes.

commit a21cb22f8b
Author: Hans Goudey <h.goudey@me.com>
Date:   Fri Jul 3 11:58:43 2020 -0400

    Cleanup: Deduplicate code for finding context object

    Instead of manually checking the pinned object, use the existing
    ED_object_active_context function. This requires adding const
    to the context in that function.

commit 33a74941c5
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 17:30:31 2020 +0200

    Cleanup: Editors, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors` module.

    No functional changes.

commit 367034f210
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 17:30:09 2020 +0200

    Cleanup: Editors/Space/UV-Edit, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/uv_edit` module.

    No functional changes.

commit 651d1aa7c8
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 17:25:04 2020 +0200

    Cleanup: Editors/Transform, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/transform` module.

    No functional changes.

commit 35ce16939c
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 17:20:58 2020 +0200

    Cleanup: Editors/Space/sequencer, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/space_sequencer` module.

    No functional changes.

commit a201020cd3
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 17:20:41 2020 +0200

    Cleanup: Editors/Space/Clip, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/space_clip` module.

    No functional changes.

commit f254f66587
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 17:20:22 2020 +0200

    Cleanup: Editors/Space/Outliner, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/space_outliner` module.

    No functional changes.

commit 3aa53b361d
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 17:20:08 2020 +0200

    Cleanup: Editors/Space/Node, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/space_node` module.

    No functional changes.

commit bf532b1106
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 17:19:13 2020 +0200

    Cleanup: Editors/Space/Text, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/space_text` module.

    No functional changes.

commit 2f6fc5a7e8
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 17:18:56 2020 +0200

    Cleanup: Editors/Space/View3D, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/space_view3d` module.

    No functional changes.

commit b61ecb785c
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 16:34:57 2020 +0200

    Cleanup: Explicit return in each `else if` block in `buttons_context()`

    This is a similar change as in rB4283da83cc9.

    No functional changes.

commit f43fedd400
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 3 17:35:31 2020 +0200

    Cleanup: remove side effect in assertion

commit 4a48939f04
Author: Hans Goudey <h.goudey@me.com>
Date:   Fri Jul 3 11:18:24 2020 -0400

    UI: Fix bevel modifier not showing vertex group

commit cad2d32be6
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Fri Jul 3 17:09:24 2020 +0200

    Clang-Tidy: Enable bugprone-misplaced-widening-cast

commit 4a5389816b
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 3 17:07:01 2020 +0200

    Clang-Tidy: enable readability-named-parameter

commit fac2e63bc0
Author: Bastien Montagne <bastien@blender.org>
Date:   Fri Jul 3 16:57:55 2020 +0200

    Fix utterly broken code regarding GPUtextures of MovieClip in readfile.c

    Treat those as pure runtime code, reset to NULL by reading code, for
    now.

    Think those could be handled like Image gputextures (i.e. considered
    runtime cache and preserved across undo steps), but probably not
    critical for now.

commit 1bdabd7b4f
Author: Bastien Montagne <bastien@blender.org>
Date:   Fri Jul 3 16:55:13 2020 +0200

    Move MovieClip to new undo cache management system.

commit 1019c9f582
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 3 16:54:08 2020 +0200

    Clang-Tidy: enable bugprone-too-small-loop-variable

commit 883f9dd6e5
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 3 16:48:04 2020 +0200

    Clang-Tidy: enable bugprone-assert-side-effect

    Looks like we have no assertions with side effects.

commit 9739fc4d1b
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Fri Jul 3 16:44:46 2020 +0200

    Clang-Tidy: More fixed of redundant check before delete

    For some reason got unnoticed in the original cleanup pass.

commit 14fd91e7e8
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 3 16:38:01 2020 +0200

    Clang-Tidy: enable bugprone-argument-comment

    It was called `inverted` in the header.

commit f4fdb8efc5
Author: Hans Goudey <h.goudey@me.com>
Date:   Fri Jul 3 10:38:49 2020 -0400

    Cleanup: Remove redundant logic

commit f66aafa391
Author: Hans Goudey <h.goudey@me.com>
Date:   Fri Jul 3 10:37:58 2020 -0400

    Fix memory leak when dragging shaderfx

commit f891d4e2ad
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Fri Jul 3 16:32:12 2020 +0200

    Clang-Tidy: Fix readability-delete-null-pointer warnings

    Also enable it in the configuration.

commit 53d41e1a6f
Author: Hans Goudey <h.goudey@me.com>
Date:   Fri Jul 3 10:28:13 2020 -0400

    UI: Use sliders and [0, 1] ranges in ocean modifier

    The ocean modifier has two properties that use a [0, 10] hard min and
    hard max. The values act as factors though, so it makes more sense to
    use sliders and a 0 to 1 range.

    This commit also bumps the file subversion to avoid repeatedly applying
    the change to the properties' range.

    Differential Revision: https://developer.blender.org/D8186

commit 2a39b34a09
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 16:09:51 2020 +0200

    Cleanup: Editors/Sculpt/Paint, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/sculpt_paint` module.

    No functional changes.

commit fd5b093f84
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 16:01:15 2020 +0200

    Cleanup: Editors/Screen, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/screen` module.

    No functional changes.

commit 4283da83cc
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 15:59:48 2020 +0200

    Cleanup: Explicit return in each `else if` block in `ed_screen_context()`

    The `ed_screen_context()` function is approximately 700 lines long, and
    its main structure is a huge chain of `else if` statements. Some of the
    bodies did not return, but rather fell through and relied on the `return
    -1;` at the bottom of the function. This means that in order to truly
    understand what is going on in one of those `else if` blocks, it could
    be required to scroll past all the following `else if` blocks,
    double-checking that they all had an `else`, and then see what happens
    below.

    By adding explicit `return -1;` everywhere this happened, this is all
    avoided, increasing local understandability of the code. Furthermore, it
    makes the upcoming cleanup with the Clang-Tidy rule
    `readability-else-after-return` a lot easier to do.

    No functional changes.

commit de7c9f41e6
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 15:42:22 2020 +0200

    Cleanup: Editors/Object, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/object` module.

    No functional changes.

commit 19483125f8
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 15:19:52 2020 +0200

    Cleanup: Editors/Mesh, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/mesh` module.

    No functional changes.

commit 7d0a0b8a6d
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 14:52:32 2020 +0200

    Cleanup: Editors/Armature, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/armature` module.

    No functional changes.

commit f82e52ebc8
Author: Sybren A. Stüvel <sybren@blender.org>
Date:   Fri Jul 3 14:51:19 2020 +0200

    Cleanup: Editors/Animation, Clang-Tidy else-after-return fixes

    This addresses warnings from Clang-Tidy's `readability-else-after-return`
    rule in the `source/blender/editors/animation` module.

    No functional changes.

commit 17ba566018
Author: Pablo Dobarro <pablodp606@gmail.com>
Date:   Fri Jul 3 02:15:54 2020 +0200

    Fix Pose Brush crashing after disabling connected only in FK mode

    This function was returning the ik_chain before disabling the
    fake_neighbors, so when the brush was used again with fake neighbors
    disabled after rebuilding the PBVH and free them, they were still
    enabled in the SculptSession, causing a the crash.

    Reviewed By: sergey

    Differential Revision: https://developer.blender.org/D8195

commit 3a59c184b9
Author: Bastien Montagne <bastien@blender.org>
Date:   Fri Jul 3 16:09:58 2020 +0200

    Move Scene's cache management during undo to new system.

commit a33756d783
Author: Hans Goudey <h.goudey@me.com>
Date:   Fri Jul 3 10:09:19 2020 -0400

    Cleanup: Unused variables in non-debug build

commit 6a58e15548
Author: Hans Goudey <h.goudey@me.com>
Date:   Fri Jul 3 10:03:16 2020 -0400

    Cleanup: Remove obsolete code in interface_panel.c

    Some code delt with panel merging in earlier versions of Blender,
    which is no longer needed. Other code delt with controls that aren't
    used anymore, and in some cases have region-level equivalents.

    There's a surprising amount of this unused code in this file, so removing it
    will be helpful for the future.

    Differential Revision: https://developer.blender.org/D7938

commit 88d358902f
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 3 15:54:55 2020 +0200

    Clang-Tidy: Enable readability-redundant-string-cstr

commit 405e6c6cc9
Author: Antonio Vazquez <blendergit@gmail.com>
Date:   Fri Jul 3 15:53:44 2020 +0200

    Fix T78555: GPencil bake animation operator loose frame setting

    The values were reset for each run

commit 19ff145e66
Author: Hans Goudey <h.goudey@me.com>
Date:   Fri Jul 3 09:41:55 2020 -0400

    Clang-Tidy: Enable readability-redundant-control-flow

commit ffef562bf7
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date:   Fri Jul 3 15:31:23 2020 +0200

    Disable clang-tidy for code-generated RNA files

    This needs some extra care, which is probably easier once the initial
    pass over integration is done.

commit c9975088a9
Author: Bastien Montagne <bastien@blender.org>
Date:   Fri Jul 3 15:27:12 2020 +0200

    Move volume to new cache management system for undo.

commit 1e255ce031
Author: Jacques Lucke <jacques@blender.org>
Date:   Fri Jul 3 15:27:02 2020 +0200

    Fix T72214: Fluids: noise does not work with negative frame numbers

    The issue is duplicated code. There are two functions that zero-fill
    the frame number. They worked the same for positive frames numbers, but
    behaved differently for negative ones.

    On frame `-100`, `BLI_path_frame` outputs `-0100` and
    `fluid_cache_get_framenr_formatted_$ID$` outputted `-100`.

    I changed the behavior of the latter, because we depend on the behavior
    of the former for much longer already.

    Reviewers: sebbas

    Differential Revision: https://developer.blender.org/D8107
2020-07-12 21:12:27 -04:00
74c56382b8 A large refactor of newboolean to perpare for performance tuning.
Many changes aimed at, broadly, more sharing and less copying;
and having coordinates stored simultaneously in double and multiprecision,
as that will be needed for floating predicate filtering.
Biggest change is that faces are represented by arrays of pointers to
Verts instead of as integer indices into a vertex array.
2020-07-12 16:27:57 -04:00
ad3dcb7bb9 Got rid of clang-tidy errors. 2020-07-03 13:31:01 -04:00
e459c26413 Fixed violations of new Blender C++ style rules. 2020-07-03 11:03:26 -04:00
141d3400a7 Merge branch 'master' into newboolean 2020-07-03 09:08:26 -04:00
15ebad8c6e Added two more tests for boolean. 2020-07-02 12:55:05 -04:00
6633d6d7d0 Made two functions static to silence a warning. 2020-07-02 11:15:28 -04:00
956005f9dd First coplanar boolean test passes.
Implemented sorting of coplanar triangles.
Also, make format.
2020-07-02 10:13:19 -04:00
7776909026 Change boolean blenlib interface to be purely C++. 2020-07-01 12:42:04 -04:00
590ce6817d Change bmesh_boolean.c into a C++ file and start using PolyMesh interface.
Also, use BLI_math_mpq.hh everywhere instead of gmpxx.h.
2020-07-01 09:15:17 -04:00
a62bca844c Fix problem after master merge with Optional -> optional migration.
On Mac, there's an error re using the value() member of std::optional.
Working around it for now.
2020-06-30 15:31:00 -04:00
028f8b5b64 Merge branch 'master' into newboolean 2020-06-30 14:54:19 -04:00
66f511018e Dissolving triangulation edges and verts passes first test. 2020-06-30 14:46:08 -04:00
4d58e68565 First test with dissolve of triangulation edges is passing.
Still lots to do. And this includes a horribly inefficient way
of finding which edges are dissolvable -- to be fixed later.
2020-06-28 18:47:08 -04:00
ce37092668 Merge branch 'master' into newboolean 2020-06-26 08:36:23 -04:00
f80378cc66 Continued work on getting triangulation edges removed from output. 2020-06-19 15:53:56 -04:00
59805fa7e0 Merge branch 'master' into newboolean 2020-06-17 08:58:20 -04:00
d40819946b Start of PolyMesh interface for boolean.
Also refactored delaunay to put the 2d mesh representation into
an externally visible CDTArrangement class. Not sure yet whether
I will use this; if I end up not using it, will move that part of
the header back into the implementation file.
2020-06-17 08:55:05 -04:00
95da735c59 Fixed bug for some binary boolean ops. Fixed a memory leak.
Now the basic binary booleans work from the tool (not the modifier).
Still to do: (1) coplanar and non-connected-component cases;
(2) dissolve triangulation lines and new verts due only to them;
(3) properly transfer mesh attributes from old to new;
(4) hook up to modifier;
(5) attention to and tuning of performance.
2020-06-14 07:58:31 -04:00
7a775b8088 Made binary version of boolean and hooked up to Boolean tool.
Union seems to work. Other ops are flaky because I haven't
quite got the winding number propagation right yet.
2020-06-13 19:54:17 -04:00
2307f4f05d More boolean tests pass.
Fixed bug re confusion of how to sort triangles around an edge.
Fixed bug in first tettet test (inconsistent normals in input).
2020-06-13 11:11:02 -04:00
b0f9d093a6 Proper implementation of finding ambient cell.
Also fixed bug in boolean test where passed wrong output
to the obj writer.
2020-06-12 10:50:08 -04:00
cd6447fe03 First real boolean union output test works. 2020-06-11 20:37:17 -04:00
5cc3f006b5 Quient some warnings on Linux. 2020-06-11 18:46:02 -04:00
3917661753 After merge from master, updated for changes to BLI.
Mainly namespace changes, BLI -> blender, so I changed my
own namespaces to follow that pattern.
ArrayRef -> Span.
Now can have hash() as member of data structures rather
that having to make a DefaultHash for them.
Fixed a bad assumption about Arrays of bool being initialized to false.
2020-06-11 13:47:20 -04:00
d7b3d0aa27 Merge branch 'master' into newboolean 2020-06-11 05:44:10 -04:00
f1e7f42f9d Format previous commit. 2020-06-11 05:41:43 -04:00
16e3e9f3e2 A lot of progress towards working boolean library function.
The code to partition space into cells is mostly done.
The code to propagate winding numbers and flag cells according to the
boolean function is mostly done.
Only final extraction code is left, and a few other things.
2020-06-10 22:00:08 -04:00
9105af1b39 Added code that partitions triangle mesh into patches.
A patch is a set of triangles connected only by manifold edges.
Each patch will either appear or not appear in the boolean output
as a whole.
2020-06-07 16:19:44 -04:00
d985aa7117 Ran make format. 2020-06-07 06:02:01 -04:00
e4c25b0ab7 Move to exact arithmetic for new boolean implementation.
This is a regression in functionality from the previous version,
as I have not yet got anything beyond intersection working (and
that only for triangulated meshes). But want to get this into
the repository now while I continue to work on the functionality,
and then, the performance.
2020-06-06 18:46:06 -04:00
61ae661103 Merge branch 'master' into newboolean. 2020-06-06 18:31:12 -04:00
3353d6f8ee Merge branch 'master' into newboolean 2020-04-21 08:39:02 -04:00
1b93b09f6d Fixed Newboolean bug: how face sides were tracked.
Also, being more paranoid about new BMesh elements changing
positions in their tables after creating new elements, so
copying them all first.
2020-04-20 17:38:09 -04:00
3622e831ba Merge branch 'master' into newboolean 2020-04-04 15:26:14 -04:00
7a6224f76c Fix crash in debug newboolean due to repeated vertex. 2020-03-11 08:06:21 -04:00
73a0368d19 Boolean: fixed case where example came from new edge.
The code keeps track of which edges are to be used for examples,
and missed a case where the split edge was a new one so shouldn't
have an example.
2020-03-08 15:32:35 -04:00
5fdada4019 Merge branch 'master' into newboolean 2020-03-08 11:06:47 -04:00
bd59ad1602 Turn off debug in repository for newboolean. 2020-03-03 09:08:45 -05:00
6237dc70b3 Merge branch 'master' into newboolean 2020-03-03 08:46:30 -05:00
f747651698 Merge branch 'master' into newboolean 2020-03-01 19:11:59 -05:00
dfcb2a8865 Silence some unused warnings. 2020-03-01 10:54:24 -05:00
43051e5770 Update for new flag needed for BLI_delaunay_2d_cdt_calc, 2020-02-29 16:12:03 -05:00
e19aa157cd Merge branch 'master' into newboolean 2020-02-29 15:49:58 -05:00
9c6c299c7f Merge branch 'master' into newboolean 2020-01-28 12:20:20 -05:00
22faf7696c Merge branch 'master' into newboolean 2019-12-16 07:41:17 -05:00
d7b36d55d4 More consistent face-face intersections.
Changed the part-part intersect algorithm so that the same calculation
is done whenever a particular edge intersects a plane.
2019-12-12 14:19:54 -05:00
6724aa5478 Merge branch 'master' into newboolean 2019-12-06 07:02:31 -05:00
8009ff01db Removed #pragma marks -- didn't work on Windows.
Also a few tweaks to debugging output.
2019-12-06 06:48:36 -05:00
fed631a2d2 Merge branch 'master' into newboolean 2019-12-03 07:00:31 -05:00
dd3ea78bc8 Some fixes for some small epsilon cases.
Also changed default epsilon to 1e-5 from 1e-6, as the latter
is too close to hairy edge and anyway produceds really tiny faces
and edges that I doubt users really want. There's even a case for
it being 1e-4 by default.
2019-12-02 08:29:28 -05:00
b877aff607 Initial work on making modifier work. Debugging still. 2019-12-02 07:15:59 -05:00
c1c6eb15c9 Use arrays in MeshAdd for faster access. 2019-12-02 07:15:59 -05:00
20748f1639 Added stuff to make MeshAdd access faster. 2019-12-02 07:15:59 -05:00
19b1c64459 Faster find_coplanar_parts. 2019-12-02 07:15:59 -05:00
70f2025e9b Fixed memory leak of bvh trees. 2019-12-02 07:15:59 -05:00
ff4f28e15d Use BVH for partset pair intersection tests.
All regression tests pass.
2019-12-02 07:15:59 -05:00
b24e83be74 Added kdtree for faster coplanar. 2019-12-02 07:15:59 -05:00
97ac88df51 Stashing progress. 2019-12-02 07:15:59 -05:00
27f1452d0a Fixed gwn (atan2 instead of atan), and some perf speedups. 2019-12-02 07:15:59 -05:00
a3ca50c7b3 Boolean coplanar cone-on-cube works.
Needed some work on coplanar faces that may have
reversed normals from projection.
2019-12-02 07:15:59 -05:00
1632e55b11 Attempt to do boolean with coplanar faces - doesn't work yet. 2019-12-02 07:15:59 -05:00
aae3b4b67a Forgot to initialize an intset. 2019-12-02 07:15:59 -05:00
d3a8855da3 Plumbed through faces that are on both sides of boolean op. 2019-12-02 07:15:59 -05:00
6945602ae3 Keep track of other orig faces besides eg for a face. 2019-12-02 07:15:59 -05:00
8ea588043c Regression tests 0-25 all pass.
Code was working but had commented out actual apply of meshchange.
2019-12-02 07:15:59 -05:00
65021f8746 clang-format 2019-12-02 07:15:59 -05:00
9c4b18597d Most regression tests now pass.
Put in option checkbox in UI so can choose old or new method.
2019-12-02 07:15:59 -05:00
f5622630c2 Stash changes. 2019-12-02 07:15:59 -05:00
230ff38946 Coplanar case works except CDT makes a face with repeated vert. 2019-12-02 07:15:59 -05:00
c66cfa01a9 Changes to master for this branch. 2019-12-02 07:15:59 -05:00
e4b24e6e0c All tri-tri non-coplanar tests work. 2019-12-02 07:15:59 -05:00
942 changed files with 62689 additions and 88194 deletions

View File

@@ -120,6 +120,7 @@ endif()
if(NOT WIN32 OR ENABLE_MINGW64)
include(cmake/gmp.cmake)
include(cmake/openjpeg.cmake)
include(cmake/gmp.cmake)
if(NOT WIN32 OR BUILD_MODE STREQUAL Release)
if(WIN32)
include(cmake/zlib_mingw.cmake)

View File

@@ -25,13 +25,6 @@ else()
set(GMP_OPTIONS --enable-static --disable-shared )
endif()
if(APPLE AND ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64"))
set(GMP_OPTIONS
${GMP_OPTIONS}
--disable-assembly
)
endif()
ExternalProject_Add(external_gmp
URL ${GMP_URI}
DOWNLOAD_DIR ${DOWNLOAD_DIR}

View File

@@ -0,0 +1,11 @@
--- UserMacros.cmake
+++ UserMacros.cmake
@@ -16,6 +16,8 @@
if (BUILD_USER_DEFINED_LIBS)
MACRO_USER_DEFINED_LIBS ()
endif (BUILD_USER_DEFINED_LIBS)
+
+include(Config/cmake/usermacros/windows_mt.cmake)
#-----------------------------------------------------------------------------
#------------------- E X A M P L E E N D -----------------------------------
#-----------------------------------------------------------------------------

View File

@@ -10,6 +10,77 @@ diff -x .git -ur usd.orig/cmake/defaults/Packages.cmake external_usd/cmake/defau
add_definitions(${TBB_DEFINITIONS})
# --math
diff -x .git -ur usd.orig/pxr/base/plug/initConfig.cpp external_usd/pxr/base/plug/initConfig.cpp
--- usd.orig/pxr/base/plug/initConfig.cpp.orig 2020-06-12 17:20:07.478199779 +0200
+++ external_usd/pxr/base/plug/initConfig.cpp 2020-06-12 17:25:28.648588552 +0200
@@ -69,10 +69,40 @@
ARCH_CONSTRUCTOR(Plug_InitConfig, 2, void)
{
+ /* The contents of this constructor have been moved to usd_initialise_plugin_path(...) */
+}
+
+}; // end of anonymous namespace
+
+/**
+ * The contents of this function used to be in the static constructor Plug_InitConfig.
+ * This static constructor made it impossible for Blender to pass a path to the USD
+ * library at runtime, as the constructor would run before Blender's main() function.
+ *
+ * This function is wrapped in a C function of the same name (defined below),
+ * so that it can be called from Blender's main() function.
+ *
+ * The datafiles_usd_path path is used to point to the USD plugin path when Blender
+ * has been installed. The fallback_usd_path path should point to the build-time
+ * location of the USD plugin files so that Blender can be run on a development machine
+ * without requiring an installation step.
+ */
+void
+usd_initialise_plugin_path(const char *datafiles_usd_path)
+{
std::vector<std::string> result;
std::vector<std::string> debugMessages;
+ // Add Blender-specific paths. They MUST end in a slash, or symlinks will not be treated as directory.
+ if (datafiles_usd_path != NULL && datafiles_usd_path[0] != '\0') {
+ std::string datafiles_usd_path_str(datafiles_usd_path);
+ if (datafiles_usd_path_str.back() != '/') {
+ datafiles_usd_path_str += "/";
+ }
+ result.push_back(datafiles_usd_path_str);
+ }
+
// Determine the absolute path to the Plug shared library. Any relative
// paths specified in the plugin search path will be anchored to this
// directory, to allow for relocatability. Note that this can fail when pxr
@@ -114,9 +144,24 @@
_AppendPathList(&result, installLocation, binaryPath);
#endif // PXR_INSTALL_LOCATION
- Plug_SetPaths(result, debugMessages);
-}
+ if (!TfGetenv("PXR_PATH_DEBUG").empty()) {
+ printf("USD Plugin paths: (%zu in total):\n", result.size());
+ for(const std::string &path : result) {
+ printf(" %s\n", path.c_str());
+ }
+ }
+ Plug_SetPaths(result, debugMessages);
}
PXR_NAMESPACE_CLOSE_SCOPE
+
+/* Workaround to make it possible to pass a path at runtime to USD. */
+extern "C" {
+void
+usd_initialise_plugin_path(
+ const char *datafiles_usd_path)
+{
+ PXR_NS::usd_initialise_plugin_path(datafiles_usd_path);
+}
+}
diff -Naur external_usd_base/cmake/macros/Public.cmake external_usd/cmake/macros/Public.cmake
--- external_usd_base/cmake/macros/Public.cmake 2019-10-24 14:39:53 -0600
+++ external_usd/cmake/macros/Public.cmake 2020-01-11 13:33:29 -0700

View File

@@ -80,7 +80,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(GMP DEFAULT_MSG
GMP_LIBRARY GMPXX_LIBRARY GMP_INCLUDE_DIR GMPXX_INCLUDE_DIR)
IF(GMP_FOUND)
SET(GMP_LIBRARIES ${GMPXX_LIBRARY} ${GMP_LIBRARY})
SET(GMP_LIBRARIES ${GMP_LIBRARY} ${GMPXX_LIBRARY})
SET(GMP_INCLUDE_DIRS ${GMP_INCLUDE_DIR} ${GMPXX_INCLUDE_DIR})
ENDIF(GMP_FOUND)

View File

@@ -15,7 +15,7 @@ set(WITH_CYCLES_EMBREE ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_OSL ON CACHE BOOL "" FORCE)
set(WITH_DRACO ON CACHE BOOL "" FORCE)
set(WITH_FFTW3 ON CACHE BOOL "" FORCE)
set(WITH_GMP ON CACHE BOOL "" FORCE)
set(WITH_GMP OFF CACHE BOOL "" FORCE)
set(WITH_LIBMV ON CACHE BOOL "" FORCE)
set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE)
set(WITH_COMPOSITOR ON CACHE BOOL "" FORCE)

View File

@@ -16,7 +16,7 @@ set(WITH_CYCLES_EMBREE ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_OSL ON CACHE BOOL "" FORCE)
set(WITH_DRACO ON CACHE BOOL "" FORCE)
set(WITH_FFTW3 ON CACHE BOOL "" FORCE)
set(WITH_GMP ON CACHE BOOL "" FORCE)
set(WITH_GMP OFF CACHE BOOL "" FORCE)
set(WITH_LIBMV ON CACHE BOOL "" FORCE)
set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE)
set(WITH_COMPOSITOR ON CACHE BOOL "" FORCE)

View File

@@ -5,14 +5,6 @@ if(WITH_WINDOWS_BUNDLE_CRT)
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE)
set(CMAKE_INSTALL_OPENMP_LIBRARIES ${WITH_OPENMP})
# This sometimes can change when updates are installed and the compiler version
# changes, so test if it exists and if not, give InstallRequiredSystemLibraries
# another chance to figure out the path.
if(MSVC_REDIST_DIR AND NOT EXISTS "${MSVC_REDIST_DIR}")
unset(MSVC_REDIST_DIR CACHE)
endif()
include(InstallRequiredSystemLibraries)
# Install the CRT to the blender.crt Sub folder.

View File

@@ -2016,7 +2016,7 @@ AUD_API Sound* checkSound(PyObject* sound)
bool initializeSound()
{
import_array1(false);
import_array();
return PyType_Ready(&SoundType) >= 0;
}

View File

@@ -18,16 +18,6 @@
# All rights reserved.
# ***** END GPL LICENSE BLOCK *****
# avoid noisy warnings
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
remove_cc_flag(
"-Wall"
)
endif()
# Use double precision to make simulations of small objects stable.
add_definitions(-DBT_USE_DOUBLE_PRECISION)
set(INC
.
src
@@ -44,6 +34,7 @@ set(SRC
src/BulletCollision/BroadphaseCollision/btDbvt.cpp
src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
src/BulletCollision/BroadphaseCollision/btDispatcher.cpp
src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp
src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
@@ -91,14 +82,12 @@ set(SRC
src/BulletCollision/CollisionShapes/btCylinderShape.cpp
src/BulletCollision/CollisionShapes/btEmptyShape.cpp
src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
src/BulletCollision/CollisionShapes/btMiniSDF.cpp
src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp
src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp
src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp
src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp
src/BulletCollision/CollisionShapes/btSdfCollisionShape.cpp
src/BulletCollision/CollisionShapes/btShapeHull.cpp
src/BulletCollision/CollisionShapes/btSphereShape.cpp
src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp
@@ -152,6 +141,7 @@ set(SRC
src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp
src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp
src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp
src/BulletDynamics/Dynamics/Bullet-C-API.cpp
src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
src/BulletDynamics/Dynamics/btRigidBody.cpp
src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp
@@ -184,7 +174,6 @@ set(SRC
src/LinearMath/btPolarDecomposition.cpp
src/LinearMath/btQuickprof.cpp
src/LinearMath/btSerializer.cpp
src/LinearMath/btSerializer64.cpp
src/LinearMath/btVector3.cpp
src/BulletCollision/BroadphaseCollision/btAxisSweep3.h
@@ -194,6 +183,7 @@ set(SRC
src/BulletCollision/BroadphaseCollision/btDbvt.h
src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
src/BulletCollision/BroadphaseCollision/btDispatcher.h
src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h
src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
@@ -247,14 +237,12 @@ set(SRC
src/BulletCollision/CollisionShapes/btEmptyShape.h
src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
src/BulletCollision/CollisionShapes/btMaterial.h
src/BulletCollision/CollisionShapes/btMiniSDF.h
src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h
src/BulletCollision/CollisionShapes/btMultiSphereShape.h
src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h
src/BulletCollision/CollisionShapes/btOptimizedBvh.h
src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h
src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h
src/BulletCollision/CollisionShapes/btSdfCollisionShape.h
src/BulletCollision/CollisionShapes/btShapeHull.h
src/BulletCollision/CollisionShapes/btSphereShape.h
src/BulletCollision/CollisionShapes/btStaticPlaneShape.h
@@ -416,6 +404,7 @@ set(SRC
src/btBulletCollisionCommon.h
src/btBulletDynamicsCommon.h
src/Bullet-C-Api.h
)
set(LIB

368
extern/bullet2/patches/blender.patch vendored Normal file
View File

@@ -0,0 +1,368 @@
diff --git a/extern/bullet2/src/LinearMath/btVector3.h b/extern/bullet2/src/LinearMath/btVector3.h
index 839b19c..3058195 100644
--- a/extern/bullet2/src/LinearMath/btVector3.h
+++ b/extern/bullet2/src/LinearMath/btVector3.h
@@ -39,7 +39,7 @@ subject to the following restrictions:
#endif
-#define BT_SHUFFLE(x,y,z,w) ((w)<<6 | (z)<<4 | (y)<<2 | (x))
+#define BT_SHUFFLE(x,y,z,w) (((w) << 6 | (z) << 4 | (y) << 2 | (x)) & 0xff)
//#define bt_pshufd_ps( _a, _mask ) (__m128) _mm_shuffle_epi32((__m128i)(_a), (_mask) )
#define bt_pshufd_ps( _a, _mask ) _mm_shuffle_ps((_a), (_a), (_mask) )
#define bt_splat3_ps( _a, _i ) bt_pshufd_ps((_a), BT_SHUFFLE(_i,_i,_i, 3) )
diff --git a/extern/bullet2/src/LinearMath/btScalar.h b/extern/bullet2/src/LinearMath/btScalar.h
--- a/extern/bullet2/src/LinearMath/btScalar.h
+++ b/extern/bullet2/src/LinearMath/btScalar.h
@@ -16,6 +16,9 @@
#ifndef BT_SCALAR_H
#define BT_SCALAR_H
+#if defined(_MSC_VER) && defined(__clang__) /* clang supplies it's own overloads already */
+#define BT_NO_SIMD_OPERATOR_OVERLOADS
+#endif
#ifdef BT_MANAGED_CODE
//Aligned data types not supported in managed code
@@ -83,7 +86,7 @@
#ifdef BT_USE_SSE
#if (_MSC_FULL_VER >= 170050727)//Visual Studio 2012 can compile SSE4/FMA3 (but SSE4/FMA3 is not enabled by default)
- #define BT_ALLOW_SSE4
+ //#define BT_ALLOW_SSE4 //disable this cause blender targets sse2
#endif //(_MSC_FULL_VER >= 160040219)
//BT_USE_SSE_IN_API is disabled under Windows by default, because
@@ -102,7 +105,7 @@
#endif //__MINGW32__
#ifdef BT_DEBUG
- #ifdef _MSC_VER
+ #if defined(_MSC_VER) && !defined(__clang__)
#include <stdio.h>
#define btAssert(x) { if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);__debugbreak(); }}
#else//_MSC_VER
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h
index be9eca6..ec40c96 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h
@@ -15,7 +15,7 @@ subject to the following restrictions:
/**
- * @mainpage Bullet Documentation
+ * @page Bullet Documentation
*
* @section intro_sec Introduction
* Bullet is a Collision Detection and Rigid Body Dynamics Library. The Library is Open Source and free for commercial use, under the ZLib license ( http://opensource.org/licenses/zlib-license.php ).
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
index 36dd043..57eb817 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
@@ -579,14 +579,10 @@ btCollisionShape* btCollisionWorldImporter::convertCollisionShape( btCollisionS
btCompoundShapeData* compoundData = (btCompoundShapeData*)shapeData;
btCompoundShape* compoundShape = createCompoundShape();
- btCompoundShapeChildData* childShapeDataArray = &compoundData->m_childShapePtr[0];
-
btAlignedObjectArray<btCollisionShape*> childShapes;
for (int i=0;i<compoundData->m_numChildShapes;i++)
{
- btCompoundShapeChildData* ptr = &compoundData->m_childShapePtr[i];
-
btCollisionShapeData* cd = compoundData->m_childShapePtr[i].m_childShape;
btCollisionShape* childShape = convertCollisionShape(cd);
diff --git a/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp b/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp
index 57fc119..31faf1d 100644
--- a/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp
+++ b/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp
@@ -29,14 +29,11 @@ subject to the following restrictions:
static btVector3
getNormalizedVector(const btVector3& v)
{
- btScalar l = v.length();
- btVector3 n = v;
- if (l < SIMD_EPSILON) {
- n.setValue(0,0,0);
- } else {
- n /= l;
- }
+ btVector3 n(0, 0, 0);
+ if (v.length() > SIMD_EPSILON) {
+ n = v.normalized();
+ }
return n;
}
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h
index 27ccefe..8e4456e 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h
@@ -37,8 +37,13 @@ struct btSimdScalar
{
}
-
+/* workaround for clang 3.4 ( == apple clang 5.1 ) issue, friction would fail with forced inlining */
+#if (defined(__clang__) && defined(__apple_build_version__) && (__clang_major__ == 5) && (__clang_minor__ == 1)) \
+|| (defined(__clang__) && !defined(__apple_build_version__) && (__clang_major__ == 3) && (__clang_minor__ == 4))
+ inline __attribute__ ((noinline)) btSimdScalar(float fl)
+#else
SIMD_FORCE_INLINE btSimdScalar(float fl)
+#endif
:m_vec128 (_mm_set1_ps(fl))
{
}
diff --git a/extern/bullet2/src/BulletDynamics/Featherstone/btMultiBody.cpp b/extern/bullet2/src/BulletDynamics/Featherstone/btMultiBody.cpp
index 5d62da7..fcd312e 100644
--- a/extern/bullet2/src/BulletDynamics/Featherstone/btMultiBody.cpp
+++ b/extern/bullet2/src/BulletDynamics/Featherstone/btMultiBody.cpp
@@ -28,7 +28,6 @@
#include "btMultiBodyJointFeedback.h"
#include "LinearMath/btTransformUtil.h"
#include "LinearMath/btSerializer.h"
-#include "Bullet3Common/b3Logging.h"
// #define INCLUDE_GYRO_TERM
///todo: determine if we need these options. If so, make a proper API, otherwise delete those globals
@@ -1732,7 +1731,6 @@ void btMultiBody::goToSleep()
void btMultiBody::checkMotionAndSleepIfRequired(btScalar timestep)
{
- int num_links = getNumLinks();
extern bool gDisableDeactivation;
if (!m_canSleep || gDisableDeactivation)
{
diff --git a/extern/bullet2/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp b/extern/bullet2/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
index 8a034b3..4f66b20 100644
--- a/extern/bullet2/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
+++ b/extern/bullet2/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
@@ -809,7 +809,6 @@ static void applyJointFeedback(btMultiBodyJacobianData& data, const btMultiBodyS
}
#endif
-#include "Bullet3Common/b3Logging.h"
void btMultiBodyConstraintSolver::writeBackSolverBodyToMultiBody(btMultiBodySolverConstraint& c, btScalar deltaTime)
{
#if 1
diff --git a/extern/bullet2/src/BulletSoftBody/btSparseSDF.h b/extern/bullet2/src/BulletSoftBody/btSparseSDF.h
index bcf0c79..8992ddb 100644
--- a/extern/bullet2/src/BulletSoftBody/btSparseSDF.h
+++ b/extern/bullet2/src/BulletSoftBody/btSparseSDF.h
@@ -185,7 +185,6 @@ struct btSparseSdf
{
++nprobes;
++ncells;
- int sz = sizeof(Cell);
if (ncells>m_clampCells)
{
static int numResets=0;
diff --git a/extern/bullet2/src/LinearMath/btConvexHullComputer.cpp b/extern/bullet2/src/LinearMath/btConvexHullComputer.cpp
index d58ac95..3fd77df 100644
--- a/extern/bullet2/src/LinearMath/btConvexHullComputer.cpp
+++ b/extern/bullet2/src/LinearMath/btConvexHullComputer.cpp
@@ -2665,6 +2665,7 @@ btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, in
}
vertices.resize(0);
+ original_vertex_index.resize(0);
edges.resize(0);
faces.resize(0);
@@ -2675,6 +2676,7 @@ btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, in
{
btConvexHullInternal::Vertex* v = oldVertices[copied];
vertices.push_back(hull.getCoordinates(v));
+ original_vertex_index.push_back(v->point.index);
btConvexHullInternal::Edge* firstEdge = v->edges;
if (firstEdge)
{
diff --git a/extern/bullet2/src/LinearMath/btConvexHullComputer.h b/extern/bullet2/src/LinearMath/btConvexHullComputer.h
index 7240ac4..6871ce8 100644
--- a/extern/bullet2/src/LinearMath/btConvexHullComputer.h
+++ b/extern/bullet2/src/LinearMath/btConvexHullComputer.h
@@ -67,6 +67,7 @@ class btConvexHullComputer
// Vertices of the output hull
btAlignedObjectArray<btVector3> vertices;
+ btAlignedObjectArray<int> original_vertex_index;
// Edges of the output hull
btAlignedObjectArray<Edge> edges;
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp
index 0623e35..02ea503 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp
@@ -13,9 +13,9 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-#if defined (_WIN32) || defined (__i386__)
-#define BT_USE_SSE_IN_API
-#endif
+//#if defined (_WIN32) || defined (__i386__)
+//#define BT_USE_SSE_IN_API
+//#endif
#include "btConvexHullShape.h"
#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp
index b56d729..88018b4 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp
@@ -13,9 +13,9 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-#if defined (_WIN32) || defined (__i386__)
-#define BT_USE_SSE_IN_API
-#endif
+//#if defined (_WIN32) || defined (__i386__)
+//#define BT_USE_SSE_IN_API
+//#endif
#include "btConvexShape.h"
#include "btTriangleShape.h"
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
index a7362ea..6abfdff 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
@@ -13,9 +13,9 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-#if defined (_WIN32) || defined (__i386__)
-#define BT_USE_SSE_IN_API
-#endif
+//#if defined (_WIN32) || defined (__i386__)
+//#define BT_USE_SSE_IN_API
+//#endif
#include "btMultiSphereShape.h"
#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
index 4854f37..9095c59 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
@@ -12,9 +12,9 @@ subject to the following restrictions:
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
-#if defined (_WIN32) || defined (__i386__)
-#define BT_USE_SSE_IN_API
-#endif
+//#if defined (_WIN32) || defined (__i386__)
+//#define BT_USE_SSE_IN_API
+//#endif
#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
#include "btConvexPolyhedron.h"
diff --git a/extern/bullet2/src/LinearMath/btVector3.cpp b/extern/bullet2/src/LinearMath/btVector3.cpp
index e05bdcc..dbcf2b6 100644
--- a/extern/bullet2/src/LinearMath/btVector3.cpp
+++ b/extern/bullet2/src/LinearMath/btVector3.cpp
@@ -15,9 +15,9 @@
This source version has been altered.
*/
-#if defined (_WIN32) || defined (__i386__)
-#define BT_USE_SSE_IN_API
-#endif
+//#if defined (_WIN32) || defined (__i386__)
+//#define BT_USE_SSE_IN_API
+//#endif
#include "btVector3.h"
diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp
index e0e8bc7..a788268 100644
--- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp
+++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp
@@ -425,50 +425,38 @@ void btRigidBody::setCenterOfMassTransform(const btTransform& xform)
}
+bool btRigidBody::checkCollideWithOverride(const btCollisionObject* co) const
+{
+ const btRigidBody* otherRb = btRigidBody::upcast(co);
+ if (!otherRb)
+ return true;
+
+ for (int i = 0; i < m_constraintRefs.size(); ++i)
+ {
+ const btTypedConstraint* c = m_constraintRefs[i];
+ if (c->isEnabled())
+ if (&c->getRigidBodyA() == otherRb || &c->getRigidBodyB() == otherRb)
+ return false;
+ }
+
+ return true;
+}
void btRigidBody::addConstraintRef(btTypedConstraint* c)
{
- ///disable collision with the 'other' body
-
int index = m_constraintRefs.findLinearSearch(c);
- //don't add constraints that are already referenced
- //btAssert(index == m_constraintRefs.size());
if (index == m_constraintRefs.size())
- {
- m_constraintRefs.push_back(c);
- btCollisionObject* colObjA = &c->getRigidBodyA();
- btCollisionObject* colObjB = &c->getRigidBodyB();
- if (colObjA == this)
- {
- colObjA->setIgnoreCollisionCheck(colObjB, true);
- }
- else
- {
- colObjB->setIgnoreCollisionCheck(colObjA, true);
- }
- }
+ m_constraintRefs.push_back(c);
+
+ m_checkCollideWith = true;
}
void btRigidBody::removeConstraintRef(btTypedConstraint* c)
{
- int index = m_constraintRefs.findLinearSearch(c);
- //don't remove constraints that are not referenced
- if(index < m_constraintRefs.size())
- {
- m_constraintRefs.remove(c);
- btCollisionObject* colObjA = &c->getRigidBodyA();
- btCollisionObject* colObjB = &c->getRigidBodyB();
- if (colObjA == this)
- {
- colObjA->setIgnoreCollisionCheck(colObjB, false);
- }
- else
- {
- colObjB->setIgnoreCollisionCheck(colObjA, false);
- }
- }
+ m_constraintRefs.remove(c);
+ m_checkCollideWith = m_constraintRefs.size() > 0;
}
int btRigidBody::calculateSerializeBufferSize() const
diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h
index 1d177db..c2f8c5d 100644
--- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h
+++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h
@@ -509,6 +509,8 @@ public:
return (getBroadphaseProxy() != 0);
}
+ virtual bool checkCollideWithOverride(const btCollisionObject* co) const;
+
void addConstraintRef(btTypedConstraint* c);
void removeConstraintRef(btTypedConstraint* c);

View File

@@ -0,0 +1,41 @@
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
index 9095c592d87..b831e20c2f9 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
@@ -406,17 +406,17 @@ void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& ine
#ifndef __SPU__
//not yet, return box inertia
- btScalar margin = getMargin();
+ //btScalar margin = getMargin();
btTransform ident;
ident.setIdentity();
btVector3 aabbMin,aabbMax;
- getAabb(ident,aabbMin,aabbMax);
+ getAabb(ident,aabbMin,aabbMax); // This already contains the margin
btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
- btScalar lx=btScalar(2.)*(halfExtents.x()+margin);
- btScalar ly=btScalar(2.)*(halfExtents.y()+margin);
- btScalar lz=btScalar(2.)*(halfExtents.z()+margin);
+ btScalar lx=btScalar(2.)*(halfExtents.x());
+ btScalar ly=btScalar(2.)*(halfExtents.y());
+ btScalar lz=btScalar(2.)*(halfExtents.z());
const btScalar x2 = lx*lx;
const btScalar y2 = ly*ly;
const btScalar z2 = lz*lz;
@@ -476,10 +476,10 @@ void btPolyhedralConvexAabbCachingShape::recalcLocalAabb()
for ( int i = 0; i < 3; ++i )
{
- m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin;
- m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin;
+ m_localAabbMax[i] = _supporting[i][i];
+ m_localAabbMin[i] = _supporting[i + 3][i];
}
-
+
#else
for (int i=0;i<3;i++)

View File

@@ -1,113 +0,0 @@
From 1b4c1687748bafd3c521f454bfdfc89b3857b65e Mon Sep 17 00:00:00 2001
From: David Vogel <Dadido3@aol.com>
Date: Mon, 30 Mar 2020 19:45:23 +0200
Subject: [PATCH 1/2] Fix inertia and margin calculation for
btPolyhedralConvexShape
---
.../CollisionShapes/btPolyhedralConvexShape.cpp | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
index 521ecfc760..e4bd7bb4d5 100644
--- a/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
+++ b/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
@@ -463,17 +463,17 @@ void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass, btVector3& in
#ifndef __SPU__
//not yet, return box inertia
- btScalar margin = getMargin();
+ //btScalar margin = getMargin();
btTransform ident;
ident.setIdentity();
btVector3 aabbMin, aabbMax;
- getAabb(ident, aabbMin, aabbMax);
+ getAabb(ident, aabbMin, aabbMax); // This already contains the margin
btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
- btScalar lx = btScalar(2.) * (halfExtents.x() + margin);
- btScalar ly = btScalar(2.) * (halfExtents.y() + margin);
- btScalar lz = btScalar(2.) * (halfExtents.z() + margin);
+ btScalar lx = btScalar(2.) * (halfExtents.x());
+ btScalar ly = btScalar(2.) * (halfExtents.y());
+ btScalar lz = btScalar(2.) * (halfExtents.z());
const btScalar x2 = lx * lx;
const btScalar y2 = ly * ly;
const btScalar z2 = lz * lz;
@@ -529,8 +529,8 @@ void btPolyhedralConvexAabbCachingShape::recalcLocalAabb()
for (int i = 0; i < 3; ++i)
{
- m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin;
- m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin;
+ m_localAabbMax[i] = _supporting[i][i];
+ m_localAabbMin[i] = _supporting[i + 3][i];
}
#else
From 4b9a201d4c1b8cacbcdd68f9cdb55745caa6adc4 Mon Sep 17 00:00:00 2001
From: David Vogel <Dadido3@aol.com>
Date: Mon, 30 Mar 2020 20:43:55 +0200
Subject: [PATCH 2/2] Fix margins
- Margin in ineratia calculation of btConeShape is already contained in the AABB
- Remove margin from the cached AABB in btConvexInternalShape, as it is added on getAabb()
---
src/BulletCollision/CollisionShapes/btConeShape.h | 10 ++++------
.../CollisionShapes/btConvexInternalShape.cpp | 8 ++++----
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/src/BulletCollision/CollisionShapes/btConeShape.h b/src/BulletCollision/CollisionShapes/btConeShape.h
index 49f26bc4e5..ee6786c807 100644
--- a/src/BulletCollision/CollisionShapes/btConeShape.h
+++ b/src/BulletCollision/CollisionShapes/btConeShape.h
@@ -56,15 +56,13 @@ btConeShape : public btConvexInternalShape
btTransform identity;
identity.setIdentity();
btVector3 aabbMin, aabbMax;
- getAabb(identity, aabbMin, aabbMax);
+ getAabb(identity, aabbMin, aabbMax); // This already contains the margin
btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
- btScalar margin = getMargin();
-
- btScalar lx = btScalar(2.) * (halfExtents.x() + margin);
- btScalar ly = btScalar(2.) * (halfExtents.y() + margin);
- btScalar lz = btScalar(2.) * (halfExtents.z() + margin);
+ btScalar lx = btScalar(2.) * (halfExtents.x());
+ btScalar ly = btScalar(2.) * (halfExtents.y());
+ btScalar lz = btScalar(2.) * (halfExtents.z());
const btScalar x2 = lx * lx;
const btScalar y2 = ly * ly;
const btScalar z2 = lz * lz;
diff --git a/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp b/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
index 4d598b1aa2..b847f8f40f 100644
--- a/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
+++ b/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
@@ -117,8 +117,8 @@ void btConvexInternalAabbCachingShape::recalcLocalAabb()
for (int i = 0; i < 3; ++i)
{
- m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin;
- m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin;
+ m_localAabbMax[i] = _supporting[i][i];
+ m_localAabbMin[i] = _supporting[i + 3][i];
}
#else
@@ -128,10 +128,10 @@ void btConvexInternalAabbCachingShape::recalcLocalAabb()
btVector3 vec(btScalar(0.), btScalar(0.), btScalar(0.));
vec[i] = btScalar(1.);
btVector3 tmp = localGetSupportingVertex(vec);
- m_localAabbMax[i] = tmp[i] + m_collisionMargin;
+ m_localAabbMax[i] = tmp[i];
vec[i] = btScalar(-1.);
tmp = localGetSupportingVertex(vec);
- m_localAabbMin[i] = tmp[i] - m_collisionMargin;
+ m_localAabbMin[i] = tmp[i];
}
#endif
}

187
extern/bullet2/src/Bullet-C-Api.h vendored Normal file
View File

@@ -0,0 +1,187 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/*
Draft high-level generic physics C-API. For low-level access, use the physics SDK native API's.
Work in progress, functionality will be added on demand.
If possible, use the richer Bullet C++ API, by including "btBulletDynamicsCommon.h"
*/
#ifndef BULLET_C_API_H
#define BULLET_C_API_H
#define PL_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
#ifdef BT_USE_DOUBLE_PRECISION
typedef double plReal;
#else
typedef float plReal;
#endif
typedef plReal plVector3[3];
typedef plReal plQuaternion[4];
#ifdef __cplusplus
extern "C" {
#endif
/** Particular physics SDK (C-API) */
PL_DECLARE_HANDLE(plPhysicsSdkHandle);
/** Dynamics world, belonging to some physics SDK (C-API)*/
PL_DECLARE_HANDLE(plDynamicsWorldHandle);
/** Rigid Body that can be part of a Dynamics World (C-API)*/
PL_DECLARE_HANDLE(plRigidBodyHandle);
/** Collision Shape/Geometry, property of a Rigid Body (C-API)*/
PL_DECLARE_HANDLE(plCollisionShapeHandle);
/** Constraint for Rigid Bodies (C-API)*/
PL_DECLARE_HANDLE(plConstraintHandle);
/** Triangle Mesh interface (C-API)*/
PL_DECLARE_HANDLE(plMeshInterfaceHandle);
/** Broadphase Scene/Proxy Handles (C-API)*/
PL_DECLARE_HANDLE(plCollisionBroadphaseHandle);
PL_DECLARE_HANDLE(plBroadphaseProxyHandle);
PL_DECLARE_HANDLE(plCollisionWorldHandle);
/**
Create and Delete a Physics SDK
*/
extern plPhysicsSdkHandle plNewBulletSdk(void); //this could be also another sdk, like ODE, PhysX etc.
extern void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk);
/** Collision World, not strictly necessary, you can also just create a Dynamics World with Rigid Bodies which internally manages the Collision World with Collision Objects */
typedef void(*btBroadphaseCallback)(void* clientData, void* object1,void* object2);
extern plCollisionBroadphaseHandle plCreateSapBroadphase(btBroadphaseCallback beginCallback,btBroadphaseCallback endCallback);
extern void plDestroyBroadphase(plCollisionBroadphaseHandle bp);
extern plBroadphaseProxyHandle plCreateProxy(plCollisionBroadphaseHandle bp, void* clientData, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ);
extern void plDestroyProxy(plCollisionBroadphaseHandle bp, plBroadphaseProxyHandle proxyHandle);
extern void plSetBoundingBox(plBroadphaseProxyHandle proxyHandle, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ);
/* todo: add pair cache support with queries like add/remove/find pair */
extern plCollisionWorldHandle plCreateCollisionWorld(plPhysicsSdkHandle physicsSdk);
/* todo: add/remove objects */
/* Dynamics World */
extern plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdk);
extern void plDeleteDynamicsWorld(plDynamicsWorldHandle world);
extern void plStepSimulation(plDynamicsWorldHandle, plReal timeStep);
extern void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object);
extern void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object);
/* Rigid Body */
extern plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionShapeHandle cshape );
extern void plDeleteRigidBody(plRigidBodyHandle body);
/* Collision Shape definition */
extern plCollisionShapeHandle plNewSphereShape(plReal radius);
extern plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z);
extern plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height);
extern plCollisionShapeHandle plNewConeShape(plReal radius, plReal height);
extern plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height);
extern plCollisionShapeHandle plNewCompoundShape(void);
extern void plAddChildShape(plCollisionShapeHandle compoundShape,plCollisionShapeHandle childShape, plVector3 childPos,plQuaternion childOrn);
extern void plDeleteShape(plCollisionShapeHandle shape);
/* Convex Meshes */
extern plCollisionShapeHandle plNewConvexHullShape(void);
extern void plAddVertex(plCollisionShapeHandle convexHull, plReal x,plReal y,plReal z);
/* Concave static triangle meshes */
extern plMeshInterfaceHandle plNewMeshInterface(void);
extern void plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2);
extern plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle);
extern void plSetScaling(plCollisionShapeHandle shape, plVector3 scaling);
/* SOLID has Response Callback/Table/Management */
/* PhysX has Triggers, User Callbacks and filtering */
/* ODE has the typedef void dNearCallback (void *data, dGeomID o1, dGeomID o2); */
/* typedef void plUpdatedPositionCallback(void* userData, plRigidBodyHandle rbHandle, plVector3 pos); */
/* typedef void plUpdatedOrientationCallback(void* userData, plRigidBodyHandle rbHandle, plQuaternion orientation); */
/* get world transform */
extern void plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix);
extern void plGetPosition(plRigidBodyHandle object,plVector3 position);
extern void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation);
/* set world transform (position/orientation) */
extern void plSetPosition(plRigidBodyHandle object, const plVector3 position);
extern void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation);
extern void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient);
extern void plSetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix);
typedef struct plRayCastResult {
plRigidBodyHandle m_body;
plCollisionShapeHandle m_shape;
plVector3 m_positionWorld;
plVector3 m_normalWorld;
} plRayCastResult;
extern int plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plRayCastResult res);
/* Sweep API */
/* extern plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); */
/* Continuous Collision Detection API */
// needed for source/blender/blenkernel/intern/collision.c
double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]);
/* Convex Hull */
PL_DECLARE_HANDLE(plConvexHull);
plConvexHull plConvexHullCompute(float (*coords)[3], int count);
void plConvexHullDelete(plConvexHull hull);
int plConvexHullNumVertices(plConvexHull hull);
int plConvexHullNumFaces(plConvexHull hull);
void plConvexHullGetVertex(plConvexHull hull, int n, float coords[3], int *original_index);
int plConvexHullGetFaceSize(plConvexHull hull, int n);
void plConvexHullGetFaceVertices(plConvexHull hull, int n, int *vertices);
#ifdef __cplusplus
}
#endif
#endif //BULLET_C_API_H

View File

@@ -2,6 +2,7 @@
//Bullet Continuous Collision Detection and Physics Library
//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
//
// btAxisSweep3
//
@@ -18,15 +19,18 @@
// 3. This notice may not be removed or altered from any source distribution.
#include "btAxisSweep3.h"
btAxisSweep3::btAxisSweep3(const btVector3& worldAabbMin, const btVector3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
: btAxisSweep3Internal<unsigned short int>(worldAabbMin, worldAabbMax, 0xfffe, 0xffff, maxHandles, pairCache, disableRaycastAccelerator)
btAxisSweep3::btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
:btAxisSweep3Internal<unsigned short int>(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache,disableRaycastAccelerator)
{
// 1 handle is reserved as sentinel
btAssert(maxHandles > 1 && maxHandles < 32767);
}
bt32BitAxisSweep3::bt32BitAxisSweep3(const btVector3& worldAabbMin, const btVector3& worldAabbMax, unsigned int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
: btAxisSweep3Internal<unsigned int>(worldAabbMin, worldAabbMax, 0xfffffffe, 0x7fffffff, maxHandles, pairCache, disableRaycastAccelerator)
bt32BitAxisSweep3::bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache , bool disableRaycastAccelerator)
:btAxisSweep3Internal<unsigned int>(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache,disableRaycastAccelerator)
{
// 1 handle is reserved as sentinel
btAssert(maxHandles > 1 && maxHandles < 2147483647);

File diff suppressed because it is too large Load Diff

View File

@@ -1,954 +0,0 @@
//Bullet Continuous Collision Detection and Physics Library
//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
//
// btAxisSweep3.h
//
// Copyright (c) 2006 Simon Hobbs
//
// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
#ifndef BT_AXIS_SWEEP_3_INTERNAL_H
#define BT_AXIS_SWEEP_3_INTERNAL_H
#include "LinearMath/btVector3.h"
#include "btOverlappingPairCache.h"
#include "btBroadphaseInterface.h"
#include "btBroadphaseProxy.h"
#include "btOverlappingPairCallback.h"
#include "btDbvtBroadphase.h"
//#define DEBUG_BROADPHASE 1
#define USE_OVERLAP_TEST_ON_REMOVES 1
/// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase.
/// It uses quantized integers to represent the begin and end points for each of the 3 axis.
/// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead.
template <typename BP_FP_INT_TYPE>
class btAxisSweep3Internal : public btBroadphaseInterface
{
protected:
BP_FP_INT_TYPE m_bpHandleMask;
BP_FP_INT_TYPE m_handleSentinel;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
class Edge
{
public:
BP_FP_INT_TYPE m_pos; // low bit is min/max
BP_FP_INT_TYPE m_handle;
BP_FP_INT_TYPE IsMax() const { return static_cast<BP_FP_INT_TYPE>(m_pos & 1); }
};
public:
class Handle : public btBroadphaseProxy
{
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
// indexes into the edge arrays
BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12
// BP_FP_INT_TYPE m_uniqueId;
btBroadphaseProxy* m_dbvtProxy; //for faster raycast
//void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject
SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) { m_minEdges[0] = next; }
SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const { return m_minEdges[0]; }
}; // 24 bytes + 24 for Edge structures = 44 bytes total per entry
protected:
btVector3 m_worldAabbMin; // overall system bounds
btVector3 m_worldAabbMax; // overall system bounds
btVector3 m_quantize; // scaling factor for quantization
BP_FP_INT_TYPE m_numHandles; // number of active handles
BP_FP_INT_TYPE m_maxHandles; // max number of handles
Handle* m_pHandles; // handles pool
BP_FP_INT_TYPE m_firstFreeHandle; // free handles list
Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries)
void* m_pEdgesRawPtr[3];
btOverlappingPairCache* m_pairCache;
///btOverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
btOverlappingPairCallback* m_userPairCallback;
bool m_ownsPairCache;
int m_invalidPair;
///additional dynamic aabb structure, used to accelerate ray cast queries.
///can be disabled using a optional argument in the constructor
btDbvtBroadphase* m_raycastAccelerator;
btOverlappingPairCache* m_nullPairCache;
// allocation/deallocation
BP_FP_INT_TYPE allocHandle();
void freeHandle(BP_FP_INT_TYPE handle);
bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB, int axis0, int axis1);
#ifdef DEBUG_BROADPHASE
void debugPrintAxis(int axis, bool checkCardinality = true);
#endif //DEBUG_BROADPHASE
//Overlap* AddOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
//void RemoveOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
public:
btAxisSweep3Internal(const btVector3& worldAabbMin, const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
virtual ~btAxisSweep3Internal();
BP_FP_INT_TYPE getNumHandles() const
{
return m_numHandles;
}
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
BP_FP_INT_TYPE addHandle(const btVector3& aabbMin, const btVector3& aabbMax, void* pOwner, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
void removeHandle(BP_FP_INT_TYPE handle, btDispatcher* dispatcher);
void updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const { return m_pHandles + index; }
virtual void resetPool(btDispatcher* dispatcher);
void processAllOverlappingPairs(btOverlapCallback* callback);
//Broadphase Interface
virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0));
virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
void quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const;
///unQuantize should be conservative: aabbMin/aabbMax should be larger then 'getAabb' result
void unQuantize(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
bool testAabbOverlap(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
btOverlappingPairCache* getOverlappingPairCache()
{
return m_pairCache;
}
const btOverlappingPairCache* getOverlappingPairCache() const
{
return m_pairCache;
}
void setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback)
{
m_userPairCallback = pairCallback;
}
const btOverlappingPairCallback* getOverlappingPairUserCallback() const
{
return m_userPairCallback;
}
///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
///will add some transform later
virtual void getBroadphaseAabb(btVector3& aabbMin, btVector3& aabbMax) const
{
aabbMin = m_worldAabbMin;
aabbMax = m_worldAabbMax;
}
virtual void printStats()
{
/* printf("btAxisSweep3.h\n");
printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
printf("aabbMin=%f,%f,%f,aabbMax=%f,%f,%f\n",m_worldAabbMin.getX(),m_worldAabbMin.getY(),m_worldAabbMin.getZ(),
m_worldAabbMax.getX(),m_worldAabbMax.getY(),m_worldAabbMax.getZ());
*/
}
};
////////////////////////////////////////////////////////////////////
#ifdef DEBUG_BROADPHASE
#include <stdio.h>
template <typename BP_FP_INT_TYPE>
void btAxisSweep3<BP_FP_INT_TYPE>::debugPrintAxis(int axis, bool checkCardinality)
{
int numEdges = m_pHandles[0].m_maxEdges[axis];
printf("SAP Axis %d, numEdges=%d\n", axis, numEdges);
int i;
for (i = 0; i < numEdges + 1; i++)
{
Edge* pEdge = m_pEdges[axis] + i;
Handle* pHandlePrev = getHandle(pEdge->m_handle);
int handleIndex = pEdge->IsMax() ? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis];
char beginOrEnd;
beginOrEnd = pEdge->IsMax() ? 'E' : 'B';
printf(" [%c,h=%d,p=%x,i=%d]\n", beginOrEnd, pEdge->m_handle, pEdge->m_pos, handleIndex);
}
if (checkCardinality)
btAssert(numEdges == m_numHandles * 2 + 1);
}
#endif //DEBUG_BROADPHASE
template <typename BP_FP_INT_TYPE>
btBroadphaseProxy* btAxisSweep3Internal<BP_FP_INT_TYPE>::createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher)
{
(void)shapeType;
BP_FP_INT_TYPE handleId = addHandle(aabbMin, aabbMax, userPtr, collisionFilterGroup, collisionFilterMask, dispatcher);
Handle* handle = getHandle(handleId);
if (m_raycastAccelerator)
{
btBroadphaseProxy* rayProxy = m_raycastAccelerator->createProxy(aabbMin, aabbMax, shapeType, userPtr, collisionFilterGroup, collisionFilterMask, dispatcher);
handle->m_dbvtProxy = rayProxy;
}
return handle;
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
{
Handle* handle = static_cast<Handle*>(proxy);
if (m_raycastAccelerator)
m_raycastAccelerator->destroyProxy(handle->m_dbvtProxy, dispatcher);
removeHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), dispatcher);
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher)
{
Handle* handle = static_cast<Handle*>(proxy);
handle->m_aabbMin = aabbMin;
handle->m_aabbMax = aabbMax;
updateHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), aabbMin, aabbMax, dispatcher);
if (m_raycastAccelerator)
m_raycastAccelerator->setAabb(handle->m_dbvtProxy, aabbMin, aabbMax, dispatcher);
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin, const btVector3& aabbMax)
{
if (m_raycastAccelerator)
{
m_raycastAccelerator->rayTest(rayFrom, rayTo, rayCallback, aabbMin, aabbMax);
}
else
{
//choose axis?
BP_FP_INT_TYPE axis = 0;
//for each proxy
for (BP_FP_INT_TYPE i = 1; i < m_numHandles * 2 + 1; i++)
{
if (m_pEdges[axis][i].IsMax())
{
rayCallback.process(getHandle(m_pEdges[axis][i].m_handle));
}
}
}
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
{
if (m_raycastAccelerator)
{
m_raycastAccelerator->aabbTest(aabbMin, aabbMax, callback);
}
else
{
//choose axis?
BP_FP_INT_TYPE axis = 0;
//for each proxy
for (BP_FP_INT_TYPE i = 1; i < m_numHandles * 2 + 1; i++)
{
if (m_pEdges[axis][i].IsMax())
{
Handle* handle = getHandle(m_pEdges[axis][i].m_handle);
if (TestAabbAgainstAabb2(aabbMin, aabbMax, handle->m_aabbMin, handle->m_aabbMax))
{
callback.process(handle);
}
}
}
}
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const
{
Handle* pHandle = static_cast<Handle*>(proxy);
aabbMin = pHandle->m_aabbMin;
aabbMax = pHandle->m_aabbMax;
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::unQuantize(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const
{
Handle* pHandle = static_cast<Handle*>(proxy);
unsigned short vecInMin[3];
unsigned short vecInMax[3];
vecInMin[0] = m_pEdges[0][pHandle->m_minEdges[0]].m_pos;
vecInMax[0] = m_pEdges[0][pHandle->m_maxEdges[0]].m_pos + 1;
vecInMin[1] = m_pEdges[1][pHandle->m_minEdges[1]].m_pos;
vecInMax[1] = m_pEdges[1][pHandle->m_maxEdges[1]].m_pos + 1;
vecInMin[2] = m_pEdges[2][pHandle->m_minEdges[2]].m_pos;
vecInMax[2] = m_pEdges[2][pHandle->m_maxEdges[2]].m_pos + 1;
aabbMin.setValue((btScalar)(vecInMin[0]) / (m_quantize.getX()), (btScalar)(vecInMin[1]) / (m_quantize.getY()), (btScalar)(vecInMin[2]) / (m_quantize.getZ()));
aabbMin += m_worldAabbMin;
aabbMax.setValue((btScalar)(vecInMax[0]) / (m_quantize.getX()), (btScalar)(vecInMax[1]) / (m_quantize.getY()), (btScalar)(vecInMax[2]) / (m_quantize.getZ()));
aabbMax += m_worldAabbMin;
}
template <typename BP_FP_INT_TYPE>
btAxisSweep3Internal<BP_FP_INT_TYPE>::btAxisSweep3Internal(const btVector3& worldAabbMin, const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
: m_bpHandleMask(handleMask),
m_handleSentinel(handleSentinel),
m_pairCache(pairCache),
m_userPairCallback(0),
m_ownsPairCache(false),
m_invalidPair(0),
m_raycastAccelerator(0)
{
BP_FP_INT_TYPE maxHandles = static_cast<BP_FP_INT_TYPE>(userMaxHandles + 1); //need to add one sentinel handle
if (!m_pairCache)
{
void* ptr = btAlignedAlloc(sizeof(btHashedOverlappingPairCache), 16);
m_pairCache = new (ptr) btHashedOverlappingPairCache();
m_ownsPairCache = true;
}
if (!disableRaycastAccelerator)
{
m_nullPairCache = new (btAlignedAlloc(sizeof(btNullPairCache), 16)) btNullPairCache();
m_raycastAccelerator = new (btAlignedAlloc(sizeof(btDbvtBroadphase), 16)) btDbvtBroadphase(m_nullPairCache); //m_pairCache);
m_raycastAccelerator->m_deferedcollide = true; //don't add/remove pairs
}
//btAssert(bounds.HasVolume());
// init bounds
m_worldAabbMin = worldAabbMin;
m_worldAabbMax = worldAabbMax;
btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin;
BP_FP_INT_TYPE maxInt = m_handleSentinel;
m_quantize = btVector3(btScalar(maxInt), btScalar(maxInt), btScalar(maxInt)) / aabbSize;
// allocate handles buffer, using btAlignedAlloc, and put all handles on free list
m_pHandles = new Handle[maxHandles];
m_maxHandles = maxHandles;
m_numHandles = 0;
// handle 0 is reserved as the null index, and is also used as the sentinel
m_firstFreeHandle = 1;
{
for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++)
m_pHandles[i].SetNextFree(static_cast<BP_FP_INT_TYPE>(i + 1));
m_pHandles[maxHandles - 1].SetNextFree(0);
}
{
// allocate edge buffers
for (int i = 0; i < 3; i++)
{
m_pEdgesRawPtr[i] = btAlignedAlloc(sizeof(Edge) * maxHandles * 2, 16);
m_pEdges[i] = new (m_pEdgesRawPtr[i]) Edge[maxHandles * 2];
}
}
//removed overlap management
// make boundary sentinels
m_pHandles[0].m_clientObject = 0;
for (int axis = 0; axis < 3; axis++)
{
m_pHandles[0].m_minEdges[axis] = 0;
m_pHandles[0].m_maxEdges[axis] = 1;
m_pEdges[axis][0].m_pos = 0;
m_pEdges[axis][0].m_handle = 0;
m_pEdges[axis][1].m_pos = m_handleSentinel;
m_pEdges[axis][1].m_handle = 0;
#ifdef DEBUG_BROADPHASE
debugPrintAxis(axis);
#endif //DEBUG_BROADPHASE
}
}
template <typename BP_FP_INT_TYPE>
btAxisSweep3Internal<BP_FP_INT_TYPE>::~btAxisSweep3Internal()
{
if (m_raycastAccelerator)
{
m_nullPairCache->~btOverlappingPairCache();
btAlignedFree(m_nullPairCache);
m_raycastAccelerator->~btDbvtBroadphase();
btAlignedFree(m_raycastAccelerator);
}
for (int i = 2; i >= 0; i--)
{
btAlignedFree(m_pEdgesRawPtr[i]);
}
delete[] m_pHandles;
if (m_ownsPairCache)
{
m_pairCache->~btOverlappingPairCache();
btAlignedFree(m_pairCache);
}
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const
{
#ifdef OLD_CLAMPING_METHOD
///problem with this clamping method is that the floating point during quantization might still go outside the range [(0|isMax) .. (m_handleSentinel&m_bpHandleMask]|isMax]
///see http://code.google.com/p/bullet/issues/detail?id=87
btVector3 clampedPoint(point);
clampedPoint.setMax(m_worldAabbMin);
clampedPoint.setMin(m_worldAabbMax);
btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize;
out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & m_bpHandleMask) | isMax);
out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & m_bpHandleMask) | isMax);
out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & m_bpHandleMask) | isMax);
#else
btVector3 v = (point - m_worldAabbMin) * m_quantize;
out[0] = (v[0] <= 0) ? (BP_FP_INT_TYPE)isMax : (v[0] >= m_handleSentinel) ? (BP_FP_INT_TYPE)((m_handleSentinel & m_bpHandleMask) | isMax) : (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[0] & m_bpHandleMask) | isMax);
out[1] = (v[1] <= 0) ? (BP_FP_INT_TYPE)isMax : (v[1] >= m_handleSentinel) ? (BP_FP_INT_TYPE)((m_handleSentinel & m_bpHandleMask) | isMax) : (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[1] & m_bpHandleMask) | isMax);
out[2] = (v[2] <= 0) ? (BP_FP_INT_TYPE)isMax : (v[2] >= m_handleSentinel) ? (BP_FP_INT_TYPE)((m_handleSentinel & m_bpHandleMask) | isMax) : (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[2] & m_bpHandleMask) | isMax);
#endif //OLD_CLAMPING_METHOD
}
template <typename BP_FP_INT_TYPE>
BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::allocHandle()
{
btAssert(m_firstFreeHandle);
BP_FP_INT_TYPE handle = m_firstFreeHandle;
m_firstFreeHandle = getHandle(handle)->GetNextFree();
m_numHandles++;
return handle;
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::freeHandle(BP_FP_INT_TYPE handle)
{
btAssert(handle > 0 && handle < m_maxHandles);
getHandle(handle)->SetNextFree(m_firstFreeHandle);
m_firstFreeHandle = handle;
m_numHandles--;
}
template <typename BP_FP_INT_TYPE>
BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::addHandle(const btVector3& aabbMin, const btVector3& aabbMax, void* pOwner, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher)
{
// quantize the bounds
BP_FP_INT_TYPE min[3], max[3];
quantize(min, aabbMin, 0);
quantize(max, aabbMax, 1);
// allocate a handle
BP_FP_INT_TYPE handle = allocHandle();
Handle* pHandle = getHandle(handle);
pHandle->m_uniqueId = static_cast<int>(handle);
//pHandle->m_pOverlaps = 0;
pHandle->m_clientObject = pOwner;
pHandle->m_collisionFilterGroup = collisionFilterGroup;
pHandle->m_collisionFilterMask = collisionFilterMask;
// compute current limit of edge arrays
BP_FP_INT_TYPE limit = static_cast<BP_FP_INT_TYPE>(m_numHandles * 2);
// insert new edges just inside the max boundary edge
for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++)
{
m_pHandles[0].m_maxEdges[axis] += 2;
m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1];
m_pEdges[axis][limit - 1].m_pos = min[axis];
m_pEdges[axis][limit - 1].m_handle = handle;
m_pEdges[axis][limit].m_pos = max[axis];
m_pEdges[axis][limit].m_handle = handle;
pHandle->m_minEdges[axis] = static_cast<BP_FP_INT_TYPE>(limit - 1);
pHandle->m_maxEdges[axis] = limit;
}
// now sort the new edges to their correct position
sortMinDown(0, pHandle->m_minEdges[0], dispatcher, false);
sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher, false);
sortMinDown(1, pHandle->m_minEdges[1], dispatcher, false);
sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher, false);
sortMinDown(2, pHandle->m_minEdges[2], dispatcher, true);
sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher, true);
return handle;
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::removeHandle(BP_FP_INT_TYPE handle, btDispatcher* dispatcher)
{
Handle* pHandle = getHandle(handle);
//explicitly remove the pairs containing the proxy
//we could do it also in the sortMinUp (passing true)
///@todo: compare performance
if (!m_pairCache->hasDeferredRemoval())
{
m_pairCache->removeOverlappingPairsContainingProxy(pHandle, dispatcher);
}
// compute current limit of edge arrays
int limit = static_cast<int>(m_numHandles * 2);
int axis;
for (axis = 0; axis < 3; axis++)
{
m_pHandles[0].m_maxEdges[axis] -= 2;
}
// remove the edges by sorting them up to the end of the list
for (axis = 0; axis < 3; axis++)
{
Edge* pEdges = m_pEdges[axis];
BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis];
pEdges[max].m_pos = m_handleSentinel;
sortMaxUp(axis, max, dispatcher, false);
BP_FP_INT_TYPE i = pHandle->m_minEdges[axis];
pEdges[i].m_pos = m_handleSentinel;
sortMinUp(axis, i, dispatcher, false);
pEdges[limit - 1].m_handle = 0;
pEdges[limit - 1].m_pos = m_handleSentinel;
#ifdef DEBUG_BROADPHASE
debugPrintAxis(axis, false);
#endif //DEBUG_BROADPHASE
}
// free the handle
freeHandle(handle);
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::resetPool(btDispatcher* /*dispatcher*/)
{
if (m_numHandles == 0)
{
m_firstFreeHandle = 1;
{
for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < m_maxHandles; i++)
m_pHandles[i].SetNextFree(static_cast<BP_FP_INT_TYPE>(i + 1));
m_pHandles[m_maxHandles - 1].SetNextFree(0);
}
}
}
//#include <stdio.h>
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::calculateOverlappingPairs(btDispatcher* dispatcher)
{
if (m_pairCache->hasDeferredRemoval())
{
btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
int i;
btBroadphasePair previousPair;
previousPair.m_pProxy0 = 0;
previousPair.m_pProxy1 = 0;
previousPair.m_algorithm = 0;
for (i = 0; i < overlappingPairArray.size(); i++)
{
btBroadphasePair& pair = overlappingPairArray[i];
bool isDuplicate = (pair == previousPair);
previousPair = pair;
bool needsRemoval = false;
if (!isDuplicate)
{
///important to use an AABB test that is consistent with the broadphase
bool hasOverlap = testAabbOverlap(pair.m_pProxy0, pair.m_pProxy1);
if (hasOverlap)
{
needsRemoval = false; //callback->processOverlap(pair);
}
else
{
needsRemoval = true;
}
}
else
{
//remove duplicate
needsRemoval = true;
//should have no algorithm
btAssert(!pair.m_algorithm);
}
if (needsRemoval)
{
m_pairCache->cleanOverlappingPair(pair, dispatcher);
// m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
// m_overlappingPairArray.pop_back();
pair.m_pProxy0 = 0;
pair.m_pProxy1 = 0;
m_invalidPair++;
}
}
///if you don't like to skip the invalid pairs in the array, execute following code:
#define CLEAN_INVALID_PAIRS 1
#ifdef CLEAN_INVALID_PAIRS
//perform a sort, to sort 'invalid' pairs to the end
overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
#endif //CLEAN_INVALID_PAIRS
//printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
}
}
template <typename BP_FP_INT_TYPE>
bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testAabbOverlap(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
{
const Handle* pHandleA = static_cast<Handle*>(proxy0);
const Handle* pHandleB = static_cast<Handle*>(proxy1);
//optimization 1: check the array index (memory address), instead of the m_pos
for (int axis = 0; axis < 3; axis++)
{
if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] ||
pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis])
{
return false;
}
}
return true;
}
template <typename BP_FP_INT_TYPE>
bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB, int axis0, int axis1)
{
//optimization 1: check the array index (memory address), instead of the m_pos
if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] ||
pHandleB->m_maxEdges[axis0] < pHandleA->m_minEdges[axis0] ||
pHandleA->m_maxEdges[axis1] < pHandleB->m_minEdges[axis1] ||
pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1])
{
return false;
}
return true;
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher)
{
// btAssert(bounds.IsFinite());
//btAssert(bounds.HasVolume());
Handle* pHandle = getHandle(handle);
// quantize the new bounds
BP_FP_INT_TYPE min[3], max[3];
quantize(min, aabbMin, 0);
quantize(max, aabbMax, 1);
// update changed edges
for (int axis = 0; axis < 3; axis++)
{
BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis];
BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis];
int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos;
int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos;
m_pEdges[axis][emin].m_pos = min[axis];
m_pEdges[axis][emax].m_pos = max[axis];
// expand (only adds overlaps)
if (dmin < 0)
sortMinDown(axis, emin, dispatcher, true);
if (dmax > 0)
sortMaxUp(axis, emax, dispatcher, true);
// shrink (only removes overlaps)
if (dmin > 0)
sortMinUp(axis, emin, dispatcher, true);
if (dmax < 0)
sortMaxDown(axis, emax, dispatcher, true);
#ifdef DEBUG_BROADPHASE
debugPrintAxis(axis);
#endif //DEBUG_BROADPHASE
}
}
// sorting a min edge downwards can only ever *add* overlaps
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
{
Edge* pEdge = m_pEdges[axis] + edge;
Edge* pPrev = pEdge - 1;
Handle* pHandleEdge = getHandle(pEdge->m_handle);
while (pEdge->m_pos < pPrev->m_pos)
{
Handle* pHandlePrev = getHandle(pPrev->m_handle);
if (pPrev->IsMax())
{
// if previous edge is a maximum check the bounds and add an overlap if necessary
const int axis1 = (1 << axis) & 3;
const int axis2 = (1 << axis1) & 3;
if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev, axis1, axis2))
{
m_pairCache->addOverlappingPair(pHandleEdge, pHandlePrev);
if (m_userPairCallback)
m_userPairCallback->addOverlappingPair(pHandleEdge, pHandlePrev);
//AddOverlap(pEdge->m_handle, pPrev->m_handle);
}
// update edge reference in other handle
pHandlePrev->m_maxEdges[axis]++;
}
else
pHandlePrev->m_minEdges[axis]++;
pHandleEdge->m_minEdges[axis]--;
// swap the edges
Edge swap = *pEdge;
*pEdge = *pPrev;
*pPrev = swap;
// decrement
pEdge--;
pPrev--;
}
#ifdef DEBUG_BROADPHASE
debugPrintAxis(axis);
#endif //DEBUG_BROADPHASE
}
// sorting a min edge upwards can only ever *remove* overlaps
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
{
Edge* pEdge = m_pEdges[axis] + edge;
Edge* pNext = pEdge + 1;
Handle* pHandleEdge = getHandle(pEdge->m_handle);
while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
{
Handle* pHandleNext = getHandle(pNext->m_handle);
if (pNext->IsMax())
{
Handle* handle0 = getHandle(pEdge->m_handle);
Handle* handle1 = getHandle(pNext->m_handle);
const int axis1 = (1 << axis) & 3;
const int axis2 = (1 << axis1) & 3;
// if next edge is maximum remove any overlap between the two handles
if (updateOverlaps
#ifdef USE_OVERLAP_TEST_ON_REMOVES
&& testOverlap2D(handle0, handle1, axis1, axis2)
#endif //USE_OVERLAP_TEST_ON_REMOVES
)
{
m_pairCache->removeOverlappingPair(handle0, handle1, dispatcher);
if (m_userPairCallback)
m_userPairCallback->removeOverlappingPair(handle0, handle1, dispatcher);
}
// update edge reference in other handle
pHandleNext->m_maxEdges[axis]--;
}
else
pHandleNext->m_minEdges[axis]--;
pHandleEdge->m_minEdges[axis]++;
// swap the edges
Edge swap = *pEdge;
*pEdge = *pNext;
*pNext = swap;
// increment
pEdge++;
pNext++;
}
}
// sorting a max edge downwards can only ever *remove* overlaps
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
{
Edge* pEdge = m_pEdges[axis] + edge;
Edge* pPrev = pEdge - 1;
Handle* pHandleEdge = getHandle(pEdge->m_handle);
while (pEdge->m_pos < pPrev->m_pos)
{
Handle* pHandlePrev = getHandle(pPrev->m_handle);
if (!pPrev->IsMax())
{
// if previous edge was a minimum remove any overlap between the two handles
Handle* handle0 = getHandle(pEdge->m_handle);
Handle* handle1 = getHandle(pPrev->m_handle);
const int axis1 = (1 << axis) & 3;
const int axis2 = (1 << axis1) & 3;
if (updateOverlaps
#ifdef USE_OVERLAP_TEST_ON_REMOVES
&& testOverlap2D(handle0, handle1, axis1, axis2)
#endif //USE_OVERLAP_TEST_ON_REMOVES
)
{
//this is done during the overlappingpairarray iteration/narrowphase collision
m_pairCache->removeOverlappingPair(handle0, handle1, dispatcher);
if (m_userPairCallback)
m_userPairCallback->removeOverlappingPair(handle0, handle1, dispatcher);
}
// update edge reference in other handle
pHandlePrev->m_minEdges[axis]++;
;
}
else
pHandlePrev->m_maxEdges[axis]++;
pHandleEdge->m_maxEdges[axis]--;
// swap the edges
Edge swap = *pEdge;
*pEdge = *pPrev;
*pPrev = swap;
// decrement
pEdge--;
pPrev--;
}
#ifdef DEBUG_BROADPHASE
debugPrintAxis(axis);
#endif //DEBUG_BROADPHASE
}
// sorting a max edge upwards can only ever *add* overlaps
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
{
Edge* pEdge = m_pEdges[axis] + edge;
Edge* pNext = pEdge + 1;
Handle* pHandleEdge = getHandle(pEdge->m_handle);
while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
{
Handle* pHandleNext = getHandle(pNext->m_handle);
const int axis1 = (1 << axis) & 3;
const int axis2 = (1 << axis1) & 3;
if (!pNext->IsMax())
{
// if next edge is a minimum check the bounds and add an overlap if necessary
if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext, axis1, axis2))
{
Handle* handle0 = getHandle(pEdge->m_handle);
Handle* handle1 = getHandle(pNext->m_handle);
m_pairCache->addOverlappingPair(handle0, handle1);
if (m_userPairCallback)
m_userPairCallback->addOverlappingPair(handle0, handle1);
}
// update edge reference in other handle
pHandleNext->m_minEdges[axis]--;
}
else
pHandleNext->m_maxEdges[axis]--;
pHandleEdge->m_maxEdges[axis]++;
// swap the edges
Edge swap = *pEdge;
*pEdge = *pNext;
*pNext = swap;
// increment
pEdge++;
pNext++;
}
}
#endif

View File

@@ -13,8 +13,10 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_BROADPHASE_INTERFACE_H
#define BT_BROADPHASE_INTERFACE_H
#ifndef BT_BROADPHASE_INTERFACE_H
#define BT_BROADPHASE_INTERFACE_H
struct btDispatcherInfo;
class btDispatcher;
@@ -22,23 +24,23 @@ class btDispatcher;
class btOverlappingPairCache;
struct btBroadphaseAabbCallback
struct btBroadphaseAabbCallback
{
virtual ~btBroadphaseAabbCallback() {}
virtual bool process(const btBroadphaseProxy* proxy) = 0;
virtual bool process(const btBroadphaseProxy* proxy) = 0;
};
struct btBroadphaseRayCallback : public btBroadphaseAabbCallback
struct btBroadphaseRayCallback : public btBroadphaseAabbCallback
{
///added some cached data to accelerate ray-AABB tests
btVector3 m_rayDirectionInverse;
unsigned int m_signs[3];
btScalar m_lambda_max;
btVector3 m_rayDirectionInverse;
unsigned int m_signs[3];
btScalar m_lambda_max;
virtual ~btBroadphaseRayCallback() {}
protected:
btBroadphaseRayCallback() {}
};
#include "LinearMath/btVector3.h"
@@ -51,29 +53,30 @@ class btBroadphaseInterface
public:
virtual ~btBroadphaseInterface() {}
virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher) = 0;
virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher) = 0;
virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher) = 0;
virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const = 0;
virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy) =0;
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0;
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0;
virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const =0;
virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0)) = 0;
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)) = 0;
virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) = 0;
virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) = 0;
///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
virtual void calculateOverlappingPairs(btDispatcher* dispatcher) = 0;
virtual void calculateOverlappingPairs(btDispatcher* dispatcher)=0;
virtual btOverlappingPairCache* getOverlappingPairCache() = 0;
virtual const btOverlappingPairCache* getOverlappingPairCache() const = 0;
virtual btOverlappingPairCache* getOverlappingPairCache()=0;
virtual const btOverlappingPairCache* getOverlappingPairCache() const =0;
///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
///will add some transform later
virtual void getBroadphaseAabb(btVector3& aabbMin, btVector3& aabbMax) const = 0;
virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const =0;
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(btDispatcher* dispatcher) { (void)dispatcher; };
virtual void resetPool(btDispatcher* dispatcher) { (void) dispatcher; };
virtual void printStats() = 0;
virtual void printStats() = 0;
};
#endif //BT_BROADPHASE_INTERFACE_H
#endif //BT_BROADPHASE_INTERFACE_H

View File

@@ -15,4 +15,3 @@ subject to the following restrictions:
#include "btBroadphaseProxy.h"
BT_NOT_EMPTY_FILE // fix warning LNK4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library

View File

@@ -16,10 +16,11 @@ subject to the following restrictions:
#ifndef BT_BROADPHASE_PROXY_H
#define BT_BROADPHASE_PROXY_H
#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE
#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE
#include "LinearMath/btVector3.h"
#include "LinearMath/btAlignedAllocator.h"
/// btDispatcher uses these types
/// IMPORTANT NOTE:The types are ordered polyhedral, implicit convex and concave
/// to facilitate type checking
@@ -34,8 +35,8 @@ enum BroadphaseNativeTypes
CONVEX_HULL_SHAPE_PROXYTYPE,
CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE,
CUSTOM_POLYHEDRAL_SHAPE_TYPE,
//implicit convex shapes
IMPLICIT_CONVEX_SHAPES_START_HERE,
//implicit convex shapes
IMPLICIT_CONVEX_SHAPES_START_HERE,
SPHERE_SHAPE_PROXYTYPE,
MULTI_SPHERE_SHAPE_PROXYTYPE,
CAPSULE_SHAPE_PROXYTYPE,
@@ -48,8 +49,8 @@ enum BroadphaseNativeTypes
BOX_2D_SHAPE_PROXYTYPE,
CONVEX_2D_SHAPE_PROXYTYPE,
CUSTOM_CONVEX_SHAPE_TYPE,
//concave shapes
CONCAVE_SHAPES_START_HERE,
//concave shapes
CONCAVE_SHAPES_START_HERE,
//keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
TRIANGLE_MESH_SHAPE_PROXYTYPE,
SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE,
@@ -57,16 +58,15 @@ enum BroadphaseNativeTypes
FAST_CONCAVE_MESH_PROXYTYPE,
//terrain
TERRAIN_SHAPE_PROXYTYPE,
///Used for GIMPACT Trimesh integration
///Used for GIMPACT Trimesh integration
GIMPACT_SHAPE_PROXYTYPE,
///Multimaterial mesh
MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE,
///Multimaterial mesh
MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE,
EMPTY_SHAPE_PROXYTYPE,
STATIC_PLANE_PROXYTYPE,
CUSTOM_CONCAVE_SHAPE_TYPE,
SDF_SHAPE_PROXYTYPE = CUSTOM_CONCAVE_SHAPE_TYPE,
CONCAVE_SHAPES_END_HERE,
CONCAVE_SHAPES_END_HERE,
COMPOUND_SHAPE_PROXYTYPE,
@@ -76,37 +76,38 @@ enum BroadphaseNativeTypes
INVALID_SHAPE_PROXYTYPE,
MAX_BROADPHASE_COLLISION_TYPES
};
///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases.
///It stores collision shape type information, collision filter information and a client object, typically a btCollisionObject or btRigidBody.
ATTRIBUTE_ALIGNED16(struct)
btBroadphaseProxy
{
BT_DECLARE_ALIGNED_ALLOCATOR();
///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases.
///It stores collision shape type information, collision filter information and a client object, typically a btCollisionObject or btRigidBody.
ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy
{
BT_DECLARE_ALIGNED_ALLOCATOR();
///optional filtering to cull potential collisions
enum CollisionFilterGroups
{
DefaultFilter = 1,
StaticFilter = 2,
KinematicFilter = 4,
DebrisFilter = 8,
SensorTrigger = 16,
CharacterFilter = 32,
AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
DefaultFilter = 1,
StaticFilter = 2,
KinematicFilter = 4,
DebrisFilter = 8,
SensorTrigger = 16,
CharacterFilter = 32,
AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
};
//Usually the client btCollisionObject or Rigidbody class
void* m_clientObject;
int m_collisionFilterGroup;
int m_collisionFilterMask;
void* m_clientObject;
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
void* m_multiSapParentProxy;
int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
int m_uniqueId; //m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
btVector3 m_aabbMin;
btVector3 m_aabbMax;
btVector3 m_aabbMin;
btVector3 m_aabbMax;
SIMD_FORCE_INLINE int getUid() const
{
@@ -114,45 +115,48 @@ btBroadphaseProxy
}
//used for memory pools
btBroadphaseProxy() : m_clientObject(0)
btBroadphaseProxy() :m_clientObject(0),m_multiSapParentProxy(0)
{
}
btBroadphaseProxy(const btVector3& aabbMin, const btVector3& aabbMax, void* userPtr, int collisionFilterGroup, int collisionFilterMask)
: m_clientObject(userPtr),
m_collisionFilterGroup(collisionFilterGroup),
m_collisionFilterMask(collisionFilterMask),
m_aabbMin(aabbMin),
m_aabbMax(aabbMax)
btBroadphaseProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0)
:m_clientObject(userPtr),
m_collisionFilterGroup(collisionFilterGroup),
m_collisionFilterMask(collisionFilterMask),
m_aabbMin(aabbMin),
m_aabbMax(aabbMax)
{
m_multiSapParentProxy = multiSapParentProxy;
}
static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType)
{
return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE);
return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE);
}
static SIMD_FORCE_INLINE bool isConvex(int proxyType)
static SIMD_FORCE_INLINE bool isConvex(int proxyType)
{
return (proxyType < CONCAVE_SHAPES_START_HERE);
}
static SIMD_FORCE_INLINE bool isNonMoving(int proxyType)
static SIMD_FORCE_INLINE bool isNonMoving(int proxyType)
{
return (isConcave(proxyType) && !(proxyType == GIMPACT_SHAPE_PROXYTYPE));
return (isConcave(proxyType) && !(proxyType==GIMPACT_SHAPE_PROXYTYPE));
}
static SIMD_FORCE_INLINE bool isConcave(int proxyType)
static SIMD_FORCE_INLINE bool isConcave(int proxyType)
{
return ((proxyType > CONCAVE_SHAPES_START_HERE) &&
(proxyType < CONCAVE_SHAPES_END_HERE));
(proxyType < CONCAVE_SHAPES_END_HERE));
}
static SIMD_FORCE_INLINE bool isCompound(int proxyType)
static SIMD_FORCE_INLINE bool isCompound(int proxyType)
{
return (proxyType == COMPOUND_SHAPE_PROXYTYPE);
}
static SIMD_FORCE_INLINE bool isSoftBody(int proxyType)
static SIMD_FORCE_INLINE bool isSoftBody(int proxyType)
{
return (proxyType == SOFTBODY_SHAPE_PROXYTYPE);
}
@@ -164,55 +168,67 @@ btBroadphaseProxy
static SIMD_FORCE_INLINE bool isConvex2d(int proxyType)
{
return (proxyType == BOX_2D_SHAPE_PROXYTYPE) || (proxyType == CONVEX_2D_SHAPE_PROXYTYPE);
return (proxyType == BOX_2D_SHAPE_PROXYTYPE) || (proxyType == CONVEX_2D_SHAPE_PROXYTYPE);
}
};
}
;
class btCollisionAlgorithm;
struct btBroadphaseProxy;
///The btBroadphasePair class contains a pair of aabb-overlapping objects.
///A btDispatcher can search a btCollisionAlgorithm that performs exact/narrowphase collision detection on the actual collision shapes.
ATTRIBUTE_ALIGNED16(struct)
btBroadphasePair
ATTRIBUTE_ALIGNED16(struct) btBroadphasePair
{
btBroadphasePair()
: m_pProxy0(0),
m_pProxy1(0),
m_algorithm(0),
m_internalInfo1(0)
btBroadphasePair ()
:
m_pProxy0(0),
m_pProxy1(0),
m_algorithm(0),
m_internalInfo1(0)
{
}
BT_DECLARE_ALIGNED_ALLOCATOR();
BT_DECLARE_ALIGNED_ALLOCATOR();
btBroadphasePair(btBroadphaseProxy & proxy0, btBroadphaseProxy & proxy1)
btBroadphasePair(const btBroadphasePair& other)
: m_pProxy0(other.m_pProxy0),
m_pProxy1(other.m_pProxy1),
m_algorithm(other.m_algorithm),
m_internalInfo1(other.m_internalInfo1)
{
}
btBroadphasePair(btBroadphaseProxy& proxy0,btBroadphaseProxy& proxy1)
{
//keep them sorted, so the std::set operations work
if (proxy0.m_uniqueId < proxy1.m_uniqueId)
{
m_pProxy0 = &proxy0;
m_pProxy1 = &proxy1;
}
else
{
m_pProxy0 = &proxy1;
m_pProxy1 = &proxy0;
}
{
m_pProxy0 = &proxy0;
m_pProxy1 = &proxy1;
}
else
{
m_pProxy0 = &proxy1;
m_pProxy1 = &proxy0;
}
m_algorithm = 0;
m_internalInfo1 = 0;
}
}
btBroadphaseProxy* m_pProxy0;
btBroadphaseProxy* m_pProxy1;
mutable btCollisionAlgorithm* m_algorithm;
union {
void* m_internalInfo1;
int m_internalTmpValue;
}; //don't use this data, it will be removed in future version.
union { void* m_internalInfo1; int m_internalTmpValue;};//don't use this data, it will be removed in future version.
};
/*
@@ -224,25 +240,31 @@ SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePa
}
*/
class btBroadphasePairSortPredicate
{
public:
bool operator()(const btBroadphasePair& a, const btBroadphasePair& b) const
{
const int uidA0 = a.m_pProxy0 ? a.m_pProxy0->m_uniqueId : -1;
const int uidB0 = b.m_pProxy0 ? b.m_pProxy0->m_uniqueId : -1;
const int uidA1 = a.m_pProxy1 ? a.m_pProxy1->m_uniqueId : -1;
const int uidB1 = b.m_pProxy1 ? b.m_pProxy1->m_uniqueId : -1;
public:
return uidA0 > uidB0 ||
(a.m_pProxy0 == b.m_pProxy0 && uidA1 > uidB1) ||
(a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm);
}
bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b ) const
{
const int uidA0 = a.m_pProxy0 ? a.m_pProxy0->m_uniqueId : -1;
const int uidB0 = b.m_pProxy0 ? b.m_pProxy0->m_uniqueId : -1;
const int uidA1 = a.m_pProxy1 ? a.m_pProxy1->m_uniqueId : -1;
const int uidB1 = b.m_pProxy1 ? b.m_pProxy1->m_uniqueId : -1;
return uidA0 > uidB0 ||
(a.m_pProxy0 == b.m_pProxy0 && uidA1 > uidB1) ||
(a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm);
}
};
SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphasePair& b)
SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphasePair& b)
{
return (a.m_pProxy0 == b.m_pProxy0) && (a.m_pProxy1 == b.m_pProxy1);
return (a.m_pProxy0 == b.m_pProxy0) && (a.m_pProxy1 == b.m_pProxy1);
}
#endif //BT_BROADPHASE_PROXY_H
#endif //BT_BROADPHASE_PROXY_H

View File

@@ -20,3 +20,4 @@ btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructio
{
m_dispatcher = ci.m_dispatcher1;
}

View File

@@ -25,51 +25,57 @@ class btManifoldResult;
class btCollisionObject;
struct btCollisionObjectWrapper;
struct btDispatcherInfo;
class btPersistentManifold;
class btPersistentManifold;
typedef btAlignedObjectArray<btPersistentManifold*> btManifoldArray;
typedef btAlignedObjectArray<btPersistentManifold*> btManifoldArray;
struct btCollisionAlgorithmConstructionInfo
{
btCollisionAlgorithmConstructionInfo()
: m_dispatcher1(0),
m_manifold(0)
:m_dispatcher1(0),
m_manifold(0)
{
}
btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher, int temp)
: m_dispatcher1(dispatcher)
btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp)
:m_dispatcher1(dispatcher)
{
(void)temp;
}
btDispatcher* m_dispatcher1;
btPersistentManifold* m_manifold;
btDispatcher* m_dispatcher1;
btPersistentManifold* m_manifold;
// int getDispatcherId();
// int getDispatcherId();
};
///btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatcher.
///It is persistent over frames
class btCollisionAlgorithm
{
protected:
btDispatcher* m_dispatcher;
protected:
// int getDispatcherId();
btDispatcher* m_dispatcher;
protected:
// int getDispatcherId();
public:
btCollisionAlgorithm(){};
btCollisionAlgorithm() {};
btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
virtual ~btCollisionAlgorithm(){};
virtual ~btCollisionAlgorithm() {};
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut) = 0;
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut) = 0;
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
virtual void getAllContactManifolds(btManifoldArray& manifoldArray) = 0;
virtual void getAllContactManifolds(btManifoldArray& manifoldArray) = 0;
};
#endif //BT_COLLISION_ALGORITHM_H
#endif //BT_COLLISION_ALGORITHM_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -24,16 +24,15 @@ subject to the following restrictions:
// Compile time config
//
#define DBVT_BP_PROFILE 0
#define DBVT_BP_PROFILE 0
//#define DBVT_BP_SORTPAIRS 1
#define DBVT_BP_PREVENTFALSEUPDATE 0
#define DBVT_BP_ACCURATESLEEPING 0
#define DBVT_BP_ENABLE_BENCHMARK 0
//#define DBVT_BP_MARGIN (btScalar)0.05
extern btScalar gDbvtMargin;
#define DBVT_BP_PREVENTFALSEUPDATE 0
#define DBVT_BP_ACCURATESLEEPING 0
#define DBVT_BP_ENABLE_BENCHMARK 0
#define DBVT_BP_MARGIN (btScalar)0.05
#if DBVT_BP_PROFILE
#define DBVT_BP_PROFILING_RATE 256
#define DBVT_BP_PROFILING_RATE 256
#include "LinearMath/btQuickprof.h"
#endif
@@ -42,90 +41,89 @@ extern btScalar gDbvtMargin;
//
struct btDbvtProxy : btBroadphaseProxy
{
/* Fields */
/* Fields */
//btDbvtAabbMm aabb;
btDbvtNode* leaf;
btDbvtProxy* links[2];
int stage;
/* ctor */
btDbvtProxy(const btVector3& aabbMin, const btVector3& aabbMax, void* userPtr, int collisionFilterGroup, int collisionFilterMask) : btBroadphaseProxy(aabbMin, aabbMax, userPtr, collisionFilterGroup, collisionFilterMask)
btDbvtNode* leaf;
btDbvtProxy* links[2];
int stage;
/* ctor */
btDbvtProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) :
btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask)
{
links[0] = links[1] = 0;
links[0]=links[1]=0;
}
};
typedef btAlignedObjectArray<btDbvtProxy*> btDbvtProxyArray;
typedef btAlignedObjectArray<btDbvtProxy*> btDbvtProxyArray;
///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt).
///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other.
///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3.
struct btDbvtBroadphase : btBroadphaseInterface
struct btDbvtBroadphase : btBroadphaseInterface
{
/* Config */
enum
{
DYNAMIC_SET = 0, /* Dynamic set index */
FIXED_SET = 1, /* Fixed set index */
STAGECOUNT = 2 /* Number of stages */
/* Config */
enum {
DYNAMIC_SET = 0, /* Dynamic set index */
FIXED_SET = 1, /* Fixed set index */
STAGECOUNT = 2 /* Number of stages */
};
/* Fields */
btDbvt m_sets[2]; // Dbvt sets
btDbvtProxy* m_stageRoots[STAGECOUNT + 1]; // Stages list
btOverlappingPairCache* m_paircache; // Pair cache
btScalar m_prediction; // Velocity prediction
int m_stageCurrent; // Current stage
int m_fupdates; // % of fixed updates per frame
int m_dupdates; // % of dynamic updates per frame
int m_cupdates; // % of cleanup updates per frame
int m_newpairs; // Number of pairs created
int m_fixedleft; // Fixed optimization left
unsigned m_updates_call; // Number of updates call
unsigned m_updates_done; // Number of updates done
btScalar m_updates_ratio; // m_updates_done/m_updates_call
int m_pid; // Parse id
int m_cid; // Cleanup index
int m_gid; // Gen id
bool m_releasepaircache; // Release pair cache on delete
bool m_deferedcollide; // Defere dynamic/static collision to collide call
bool m_needcleanup; // Need to run cleanup?
btAlignedObjectArray<btAlignedObjectArray<const btDbvtNode*> > m_rayTestStacks;
/* Fields */
btDbvt m_sets[2]; // Dbvt sets
btDbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list
btOverlappingPairCache* m_paircache; // Pair cache
btScalar m_prediction; // Velocity prediction
int m_stageCurrent; // Current stage
int m_fupdates; // % of fixed updates per frame
int m_dupdates; // % of dynamic updates per frame
int m_cupdates; // % of cleanup updates per frame
int m_newpairs; // Number of pairs created
int m_fixedleft; // Fixed optimization left
unsigned m_updates_call; // Number of updates call
unsigned m_updates_done; // Number of updates done
btScalar m_updates_ratio; // m_updates_done/m_updates_call
int m_pid; // Parse id
int m_cid; // Cleanup index
int m_gid; // Gen id
bool m_releasepaircache; // Release pair cache on delete
bool m_deferedcollide; // Defere dynamic/static collision to collide call
bool m_needcleanup; // Need to run cleanup?
#if DBVT_BP_PROFILE
btClock m_clock;
struct
{
unsigned long m_total;
unsigned long m_ddcollide;
unsigned long m_fdcollide;
unsigned long m_cleanup;
unsigned long m_jobcount;
} m_profiling;
btClock m_clock;
struct {
unsigned long m_total;
unsigned long m_ddcollide;
unsigned long m_fdcollide;
unsigned long m_cleanup;
unsigned long m_jobcount;
} m_profiling;
#endif
/* Methods */
btDbvtBroadphase(btOverlappingPairCache* paircache = 0);
/* Methods */
btDbvtBroadphase(btOverlappingPairCache* paircache=0);
~btDbvtBroadphase();
void collide(btDispatcher* dispatcher);
void optimize();
void collide(btDispatcher* dispatcher);
void optimize();
/* btBroadphaseInterface Implementation */
btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0));
virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0));
virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
virtual btOverlappingPairCache* getOverlappingPairCache();
virtual const btOverlappingPairCache* getOverlappingPairCache() const;
virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const;
virtual void printStats();
virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
virtual btOverlappingPairCache* getOverlappingPairCache();
virtual const btOverlappingPairCache* getOverlappingPairCache() const;
virtual void getBroadphaseAabb(btVector3& aabbMin, btVector3& aabbMax) const;
virtual void printStats();
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(btDispatcher* dispatcher);
void performDeferredRemoval(btDispatcher* dispatcher);
void setVelocityPrediction(btScalar prediction)
void performDeferredRemoval(btDispatcher* dispatcher);
void setVelocityPrediction(btScalar prediction)
{
m_prediction = prediction;
}
@@ -134,13 +132,15 @@ struct btDbvtBroadphase : btBroadphaseInterface
return m_prediction;
}
///this setAabbForceUpdate is similar to setAabb but always forces the aabb update.
///this setAabbForceUpdate is similar to setAabb but always forces the aabb update.
///it is not part of the btBroadphaseInterface but specific to btDbvtBroadphase.
///it bypasses certain optimizations that prevent aabb updates (when the aabb shrinks), see
///http://code.google.com/p/bullet/issues/detail?id=223
void setAabbForceUpdate(btBroadphaseProxy* absproxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* /*dispatcher*/);
void setAabbForceUpdate( btBroadphaseProxy* absproxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* /*dispatcher*/);
static void benchmark(btBroadphaseInterface*);
static void benchmark(btBroadphaseInterface*);
};
#endif

View File

@@ -17,4 +17,6 @@ subject to the following restrictions:
btDispatcher::~btDispatcher()
{
}

View File

@@ -20,7 +20,7 @@ subject to the following restrictions:
class btCollisionAlgorithm;
struct btBroadphaseProxy;
class btRigidBody;
class btCollisionObject;
class btCollisionObject;
class btOverlappingPairCache;
struct btCollisionObjectWrapper;
@@ -35,76 +35,73 @@ struct btDispatcherInfo
DISPATCH_CONTINUOUS
};
btDispatcherInfo()
: m_timeStep(btScalar(0.)),
m_stepCount(0),
m_dispatchFunc(DISPATCH_DISCRETE),
m_timeOfImpact(btScalar(1.)),
m_useContinuous(true),
m_debugDraw(0),
m_enableSatConvex(false),
m_enableSPU(true),
m_useEpa(true),
m_allowedCcdPenetration(btScalar(0.04)),
m_useConvexConservativeDistanceUtil(false),
m_convexConservativeDistanceThreshold(0.0f),
m_deterministicOverlappingPairs(false)
:m_timeStep(btScalar(0.)),
m_stepCount(0),
m_dispatchFunc(DISPATCH_DISCRETE),
m_timeOfImpact(btScalar(1.)),
m_useContinuous(true),
m_debugDraw(0),
m_enableSatConvex(false),
m_enableSPU(true),
m_useEpa(true),
m_allowedCcdPenetration(btScalar(0.04)),
m_useConvexConservativeDistanceUtil(false),
m_convexConservativeDistanceThreshold(0.0f)
{
}
btScalar m_timeStep;
int m_stepCount;
int m_dispatchFunc;
mutable btScalar m_timeOfImpact;
bool m_useContinuous;
class btIDebugDraw* m_debugDraw;
bool m_enableSatConvex;
bool m_enableSPU;
bool m_useEpa;
btScalar m_allowedCcdPenetration;
bool m_useConvexConservativeDistanceUtil;
btScalar m_convexConservativeDistanceThreshold;
bool m_deterministicOverlappingPairs;
};
enum ebtDispatcherQueryType
{
BT_CONTACT_POINT_ALGORITHMS = 1,
BT_CLOSEST_POINT_ALGORITHMS = 2
}
btScalar m_timeStep;
int m_stepCount;
int m_dispatchFunc;
mutable btScalar m_timeOfImpact;
bool m_useContinuous;
class btIDebugDraw* m_debugDraw;
bool m_enableSatConvex;
bool m_enableSPU;
bool m_useEpa;
btScalar m_allowedCcdPenetration;
bool m_useConvexConservativeDistanceUtil;
btScalar m_convexConservativeDistanceThreshold;
};
///The btDispatcher interface class can be used in combination with broadphase to dispatch calculations for overlapping pairs.
///For example for pairwise collision detection, calculating contact points stored in btPersistentManifold or user callbacks (game logic).
class btDispatcher
{
public:
virtual ~btDispatcher();
virtual ~btDispatcher() ;
virtual btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btPersistentManifold* sharedManifold, ebtDispatcherQueryType queryType) = 0;
virtual btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold=0) = 0;
virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0, const btCollisionObject* b1) = 0;
virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0,const btCollisionObject* b1)=0;
virtual void releaseManifold(btPersistentManifold* manifold) = 0;
virtual void releaseManifold(btPersistentManifold* manifold)=0;
virtual void clearManifold(btPersistentManifold* manifold) = 0;
virtual void clearManifold(btPersistentManifold* manifold)=0;
virtual bool needsCollision(const btCollisionObject* body0, const btCollisionObject* body1) = 0;
virtual bool needsCollision(const btCollisionObject* body0,const btCollisionObject* body1) = 0;
virtual bool needsResponse(const btCollisionObject* body0, const btCollisionObject* body1) = 0;
virtual bool needsResponse(const btCollisionObject* body0,const btCollisionObject* body1)=0;
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher) = 0;
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) =0;
virtual int getNumManifolds() const = 0;
virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0;
virtual btPersistentManifold** getInternalManifoldPointer() = 0;
virtual btPersistentManifold** getInternalManifoldPointer() = 0;
virtual btPoolAllocator* getInternalManifoldPool() = 0;
virtual btPoolAllocator* getInternalManifoldPool() = 0;
virtual const btPoolAllocator* getInternalManifoldPool() const = 0;
virtual const btPoolAllocator* getInternalManifoldPool() const = 0;
virtual void* allocateCollisionAlgorithm(int size) = 0;
virtual void* allocateCollisionAlgorithm(int size) = 0;
virtual void freeCollisionAlgorithm(void* ptr) = 0;
virtual void freeCollisionAlgorithm(void* ptr) = 0;
};
#endif //BT_DISPATCHER_H
#endif //BT_DISPATCHER_H

View File

@@ -0,0 +1,489 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btMultiSapBroadphase.h"
#include "btSimpleBroadphase.h"
#include "LinearMath/btAabbUtil2.h"
#include "btQuantizedBvh.h"
/// btSapBroadphaseArray m_sapBroadphases;
/// btOverlappingPairCache* m_overlappingPairs;
extern int gOverlappingPairs;
/*
class btMultiSapSortedOverlappingPairCache : public btSortedOverlappingPairCache
{
public:
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
return btSortedOverlappingPairCache::addOverlappingPair((btBroadphaseProxy*)proxy0->m_multiSapParentProxy,(btBroadphaseProxy*)proxy1->m_multiSapParentProxy);
}
};
*/
btMultiSapBroadphase::btMultiSapBroadphase(int /*maxProxies*/,btOverlappingPairCache* pairCache)
:m_overlappingPairs(pairCache),
m_optimizedAabbTree(0),
m_ownsPairCache(false),
m_invalidPair(0)
{
if (!m_overlappingPairs)
{
m_ownsPairCache = true;
void* mem = btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16);
m_overlappingPairs = new (mem)btSortedOverlappingPairCache();
}
struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback
{
virtual ~btMultiSapOverlapFilterCallback()
{}
// return true when pairs need collision
virtual bool needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const
{
btBroadphaseProxy* multiProxy0 = (btBroadphaseProxy*)childProxy0->m_multiSapParentProxy;
btBroadphaseProxy* multiProxy1 = (btBroadphaseProxy*)childProxy1->m_multiSapParentProxy;
bool collides = (multiProxy0->m_collisionFilterGroup & multiProxy1->m_collisionFilterMask) != 0;
collides = collides && (multiProxy1->m_collisionFilterGroup & multiProxy0->m_collisionFilterMask);
return collides;
}
};
void* mem = btAlignedAlloc(sizeof(btMultiSapOverlapFilterCallback),16);
m_filterCallback = new (mem)btMultiSapOverlapFilterCallback();
m_overlappingPairs->setOverlapFilterCallback(m_filterCallback);
// mem = btAlignedAlloc(sizeof(btSimpleBroadphase),16);
// m_simpleBroadphase = new (mem) btSimpleBroadphase(maxProxies,m_overlappingPairs);
}
btMultiSapBroadphase::~btMultiSapBroadphase()
{
if (m_ownsPairCache)
{
m_overlappingPairs->~btOverlappingPairCache();
btAlignedFree(m_overlappingPairs);
}
}
void btMultiSapBroadphase::buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax)
{
m_optimizedAabbTree = new btQuantizedBvh();
m_optimizedAabbTree->setQuantizationValues(bvhAabbMin,bvhAabbMax);
QuantizedNodeArray& nodes = m_optimizedAabbTree->getLeafNodeArray();
for (int i=0;i<m_sapBroadphases.size();i++)
{
btQuantizedBvhNode node;
btVector3 aabbMin,aabbMax;
m_sapBroadphases[i]->getBroadphaseAabb(aabbMin,aabbMax);
m_optimizedAabbTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
m_optimizedAabbTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
int partId = 0;
node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i;
nodes.push_back(node);
}
m_optimizedAabbTree->buildInternal();
}
btBroadphaseProxy* btMultiSapBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* /*ignoreMe*/)
{
//void* ignoreMe -> we could think of recursive multi-sap, if someone is interested
void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16);
btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin, aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask);
m_multiSapProxies.push_back(proxy);
///this should deal with inserting/removal into child broadphases
setAabb(proxy,aabbMin,aabbMax,dispatcher);
return proxy;
}
void btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
{
///not yet
btAssert(0);
}
void btMultiSapBroadphase::addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase)
{
void* mem = btAlignedAlloc(sizeof(btBridgeProxy),16);
btBridgeProxy* bridgeProxyRef = new(mem) btBridgeProxy;
bridgeProxyRef->m_childProxy = childProxy;
bridgeProxyRef->m_childBroadphase = childBroadphase;
parentMultiSapProxy->m_bridgeProxies.push_back(bridgeProxyRef);
}
bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax);
bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax)
{
return
amin.getX() >= bmin.getX() && amax.getX() <= bmax.getX() &&
amin.getY() >= bmin.getY() && amax.getY() <= bmax.getY() &&
amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ();
}
void btMultiSapBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
{
btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
aabbMin = multiProxy->m_aabbMin;
aabbMax = multiProxy->m_aabbMax;
}
void btMultiSapBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax)
{
for (int i=0;i<m_multiSapProxies.size();i++)
{
rayCallback.process(m_multiSapProxies[i]);
}
}
//#include <stdio.h>
void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)
{
btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
multiProxy->m_aabbMin = aabbMin;
multiProxy->m_aabbMax = aabbMax;
// bool fullyContained = false;
// bool alreadyInSimple = false;
struct MyNodeOverlapCallback : public btNodeOverlapCallback
{
btMultiSapBroadphase* m_multiSap;
btMultiSapProxy* m_multiProxy;
btDispatcher* m_dispatcher;
MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher)
:m_multiSap(multiSap),
m_multiProxy(multiProxy),
m_dispatcher(dispatcher)
{
}
virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex)
{
btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex];
int containingBroadphaseIndex = -1;
//already found?
for (int i=0;i<m_multiProxy->m_bridgeProxies.size();i++)
{
if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
{
containingBroadphaseIndex = i;
break;
}
}
if (containingBroadphaseIndex<0)
{
//add it
btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy);
m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase);
}
}
};
MyNodeOverlapCallback myNodeCallback(this,multiProxy,dispatcher);
if (m_optimizedAabbTree)
m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
int i;
for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
{
btVector3 worldAabbMin,worldAabbMax;
multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
if (!overlapsBroadphase)
{
//remove it now
btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i];
btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1);
multiProxy->m_bridgeProxies.pop_back();
}
}
/*
if (1)
{
//find broadphase that contain this multiProxy
int numChildBroadphases = getBroadphaseArray().size();
for (int i=0;i<numChildBroadphases;i++)
{
btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
btVector3 worldAabbMin,worldAabbMax;
childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
// fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
int containingBroadphaseIndex = -1;
//if already contains this
for (int i=0;i<multiProxy->m_bridgeProxies.size();i++)
{
if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
{
containingBroadphaseIndex = i;
}
alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase);
}
if (overlapsBroadphase)
{
if (containingBroadphaseIndex<0)
{
btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
childProxy->m_multiSapParentProxy = multiProxy;
addToChildBroadphase(multiProxy,childProxy,childBroadphase);
}
} else
{
if (containingBroadphaseIndex>=0)
{
//remove
btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex];
btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1);
multiProxy->m_bridgeProxies.pop_back();
}
}
}
///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force)
///hopefully we don't end up with many entries here (can assert/provide feedback on stats)
if (0)//!multiProxy->m_bridgeProxies.size())
{
///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
///this is needed to be able to calculate the aabb overlap
btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
childProxy->m_multiSapParentProxy = multiProxy;
addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
}
}
if (!multiProxy->m_bridgeProxies.size())
{
///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
///this is needed to be able to calculate the aabb overlap
btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
childProxy->m_multiSapParentProxy = multiProxy;
addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
}
*/
//update
for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
{
btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i];
bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher);
}
}
bool stopUpdating=false;
class btMultiSapBroadphasePairSortPredicate
{
public:
bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 ) const
{
btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0;
btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0;
btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0;
btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0;
return aProxy0 > bProxy0 ||
(aProxy0 == bProxy0 && aProxy1 > bProxy1) ||
(aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm);
}
};
///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
void btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
{
// m_simpleBroadphase->calculateOverlappingPairs(dispatcher);
if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval())
{
btBroadphasePairArray& overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray();
// quicksort(overlappingPairArray,0,overlappingPairArray.size());
overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
// overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
int i;
btBroadphasePair previousPair;
previousPair.m_pProxy0 = 0;
previousPair.m_pProxy1 = 0;
previousPair.m_algorithm = 0;
for (i=0;i<overlappingPairArray.size();i++)
{
btBroadphasePair& pair = overlappingPairArray[i];
btMultiSapProxy* aProxy0 = pair.m_pProxy0 ? (btMultiSapProxy*)pair.m_pProxy0->m_multiSapParentProxy : 0;
btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0;
btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0;
btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0;
bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1);
previousPair = pair;
bool needsRemoval = false;
if (!isDuplicate)
{
bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
if (hasOverlap)
{
needsRemoval = false;//callback->processOverlap(pair);
} else
{
needsRemoval = true;
}
} else
{
//remove duplicate
needsRemoval = true;
//should have no algorithm
btAssert(!pair.m_algorithm);
}
if (needsRemoval)
{
getOverlappingPairCache()->cleanOverlappingPair(pair,dispatcher);
// m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
// m_overlappingPairArray.pop_back();
pair.m_pProxy0 = 0;
pair.m_pProxy1 = 0;
m_invalidPair++;
gOverlappingPairs--;
}
}
///if you don't like to skip the invalid pairs in the array, execute following code:
#define CLEAN_INVALID_PAIRS 1
#ifdef CLEAN_INVALID_PAIRS
//perform a sort, to sort 'invalid' pairs to the end
//overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
#endif//CLEAN_INVALID_PAIRS
//printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
}
}
bool btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1)
{
btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy;
btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy;
return TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax,
multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax);
}
void btMultiSapBroadphase::printStats()
{
/* printf("---------------------------------\n");
printf("btMultiSapBroadphase.h\n");
printf("numHandles = %d\n",m_multiSapProxies.size());
//find broadphase that contain this multiProxy
int numChildBroadphases = getBroadphaseArray().size();
for (int i=0;i<numChildBroadphases;i++)
{
btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
childBroadphase->printStats();
}
*/
}
void btMultiSapBroadphase::resetPool(btDispatcher* dispatcher)
{
// not yet
}

View File

@@ -0,0 +1,151 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_MULTI_SAP_BROADPHASE
#define BT_MULTI_SAP_BROADPHASE
#include "btBroadphaseInterface.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "btOverlappingPairCache.h"
class btBroadphaseInterface;
class btSimpleBroadphase;
typedef btAlignedObjectArray<btBroadphaseInterface*> btSapBroadphaseArray;
///The btMultiSapBroadphase is a research project, not recommended to use in production. Use btAxisSweep3 or btDbvtBroadphase instead.
///The btMultiSapBroadphase is a broadphase that contains multiple SAP broadphases.
///The user can add SAP broadphases that cover the world. A btBroadphaseProxy can be in multiple child broadphases at the same time.
///A btQuantizedBvh acceleration structures finds overlapping SAPs for each btBroadphaseProxy.
///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=328
///and http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329
class btMultiSapBroadphase :public btBroadphaseInterface
{
btSapBroadphaseArray m_sapBroadphases;
btSimpleBroadphase* m_simpleBroadphase;
btOverlappingPairCache* m_overlappingPairs;
class btQuantizedBvh* m_optimizedAabbTree;
bool m_ownsPairCache;
btOverlapFilterCallback* m_filterCallback;
int m_invalidPair;
struct btBridgeProxy
{
btBroadphaseProxy* m_childProxy;
btBroadphaseInterface* m_childBroadphase;
};
public:
struct btMultiSapProxy : public btBroadphaseProxy
{
///array with all the entries that this proxy belongs to
btAlignedObjectArray<btBridgeProxy*> m_bridgeProxies;
btVector3 m_aabbMin;
btVector3 m_aabbMax;
int m_shapeType;
/* void* m_userPtr;
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
*/
btMultiSapProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask)
:btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask),
m_aabbMin(aabbMin),
m_aabbMax(aabbMax),
m_shapeType(shapeType)
{
m_multiSapParentProxy =this;
}
};
protected:
btAlignedObjectArray<btMultiSapProxy*> m_multiSapProxies;
public:
btMultiSapBroadphase(int maxProxies = 16384,btOverlappingPairCache* pairCache=0);
btSapBroadphaseArray& getBroadphaseArray()
{
return m_sapBroadphases;
}
const btSapBroadphaseArray& getBroadphaseArray() const
{
return m_sapBroadphases;
}
virtual ~btMultiSapBroadphase();
virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy);
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0));
void addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase);
///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
virtual btOverlappingPairCache* getOverlappingPairCache()
{
return m_overlappingPairs;
}
virtual const btOverlappingPairCache* getOverlappingPairCache() const
{
return m_overlappingPairs;
}
///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
///will add some transform later
virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
{
aabbMin.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT);
aabbMax.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT);
}
void buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax);
virtual void printStats();
void quicksort (btBroadphasePairArray& a, int lo, int hi);
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(btDispatcher* dispatcher);
};
#endif //BT_MULTI_SAP_BROADPHASE

View File

@@ -13,6 +13,8 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "btOverlappingPairCache.h"
#include "btDispatcher.h"
@@ -21,95 +23,127 @@ subject to the following restrictions:
#include <stdio.h>
btHashedOverlappingPairCache::btHashedOverlappingPairCache() : m_overlapFilterCallback(0),
m_ghostPairCallback(0)
int gOverlappingPairs = 0;
int gRemovePairs =0;
int gAddedPairs =0;
int gFindPairs =0;
btHashedOverlappingPairCache::btHashedOverlappingPairCache():
m_overlapFilterCallback(0),
m_ghostPairCallback(0)
{
int initialAllocatedSize = 2;
int initialAllocatedSize= 2;
m_overlappingPairArray.reserve(initialAllocatedSize);
growTables();
}
btHashedOverlappingPairCache::~btHashedOverlappingPairCache()
{
}
void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher)
void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
{
if (pair.m_algorithm && dispatcher)
{
{
pair.m_algorithm->~btCollisionAlgorithm();
dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
pair.m_algorithm = 0;
pair.m_algorithm=0;
}
}
}
void btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
void btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
{
class CleanPairCallback : public btOverlapCallback
class CleanPairCallback : public btOverlapCallback
{
btBroadphaseProxy* m_cleanProxy;
btOverlappingPairCache* m_pairCache;
btOverlappingPairCache* m_pairCache;
btDispatcher* m_dispatcher;
public:
CleanPairCallback(btBroadphaseProxy* cleanProxy, btOverlappingPairCache* pairCache, btDispatcher* dispatcher)
: m_cleanProxy(cleanProxy),
m_pairCache(pairCache),
m_dispatcher(dispatcher)
CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
:m_cleanProxy(cleanProxy),
m_pairCache(pairCache),
m_dispatcher(dispatcher)
{
}
virtual bool processOverlap(btBroadphasePair& pair)
virtual bool processOverlap(btBroadphasePair& pair)
{
if ((pair.m_pProxy0 == m_cleanProxy) ||
(pair.m_pProxy1 == m_cleanProxy))
{
m_pairCache->cleanOverlappingPair(pair, m_dispatcher);
m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
}
return false;
}
};
CleanPairCallback cleanPairs(proxy, this, dispatcher);
CleanPairCallback cleanPairs(proxy,this,dispatcher);
processAllOverlappingPairs(&cleanPairs,dispatcher);
processAllOverlappingPairs(&cleanPairs, dispatcher);
}
void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
{
class RemovePairCallback : public btOverlapCallback
class RemovePairCallback : public btOverlapCallback
{
btBroadphaseProxy* m_obsoleteProxy;
public:
RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
: m_obsoleteProxy(obsoleteProxy)
:m_obsoleteProxy(obsoleteProxy)
{
}
virtual bool processOverlap(btBroadphasePair& pair)
virtual bool processOverlap(btBroadphasePair& pair)
{
return ((pair.m_pProxy0 == m_obsoleteProxy) ||
(pair.m_pProxy1 == m_obsoleteProxy));
(pair.m_pProxy1 == m_obsoleteProxy));
}
};
RemovePairCallback removeCallback(proxy);
processAllOverlappingPairs(&removeCallback, dispatcher);
processAllOverlappingPairs(&removeCallback,dispatcher);
}
btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
{
if (proxy0->m_uniqueId > proxy1->m_uniqueId)
btSwap(proxy0, proxy1);
gFindPairs++;
if(proxy0->m_uniqueId>proxy1->m_uniqueId)
btSwap(proxy0,proxy1);
int proxyId1 = proxy0->getUid();
int proxyId2 = proxy1->getUid();
/*if (proxyId1 > proxyId2)
/*if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);*/
int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1));
int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
if (hash >= m_hashTable.size())
{
@@ -134,8 +168,9 @@ btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* prox
//#include <stdio.h>
void btHashedOverlappingPairCache::growTables()
void btHashedOverlappingPairCache::growTables()
{
int newCapacity = m_overlappingPairArray.capacity();
if (m_hashTable.size() < newCapacity)
@@ -146,9 +181,10 @@ void btHashedOverlappingPairCache::growTables()
m_hashTable.resize(newCapacity);
m_next.resize(newCapacity);
int i;
for (i = 0; i < newCapacity; ++i)
for (i= 0; i < newCapacity; ++i)
{
m_hashTable[i] = BT_NULL_PAIR;
}
@@ -157,31 +193,35 @@ void btHashedOverlappingPairCache::growTables()
m_next[i] = BT_NULL_PAIR;
}
for (i = 0; i < curHashtableSize; i++)
for(i=0;i<curHashtableSize;i++)
{
const btBroadphasePair& pair = m_overlappingPairArray[i];
int proxyId1 = pair.m_pProxy0->getUid();
int proxyId2 = pair.m_pProxy1->getUid();
/*if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);*/
int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1)); // New hash value with new mask
int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
m_next[i] = m_hashTable[hashValue];
m_hashTable[hashValue] = i;
}
}
}
btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
{
if (proxy0->m_uniqueId > proxy1->m_uniqueId)
btSwap(proxy0, proxy1);
if(proxy0->m_uniqueId>proxy1->m_uniqueId)
btSwap(proxy0,proxy1);
int proxyId1 = proxy0->getUid();
int proxyId2 = proxy1->getUid();
/*if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);*/
int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1)); // New hash value with new mask
int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
if (pair != NULL)
@@ -203,7 +243,7 @@ btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProx
//this is where we add an actual pair, so also call the 'ghost'
if (m_ghostPairCallback)
m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
m_ghostPairCallback->addOverlappingPair(proxy0,proxy1);
int newCapacity = m_overlappingPairArray.capacity();
@@ -211,14 +251,15 @@ btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProx
{
growTables();
//hash with new capacity
hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1));
hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
}
pair = new (mem) btBroadphasePair(*proxy0, *proxy1);
// pair->m_pProxy0 = proxy0;
// pair->m_pProxy1 = proxy1;
pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
// pair->m_pProxy0 = proxy0;
// pair->m_pProxy1 = proxy1;
pair->m_algorithm = 0;
pair->m_internalTmpValue = 0;
m_next[count] = m_hashTable[hash];
m_hashTable[hash] = count;
@@ -226,17 +267,20 @@ btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProx
return pair;
}
void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher)
void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
{
if (proxy0->m_uniqueId > proxy1->m_uniqueId)
btSwap(proxy0, proxy1);
gRemovePairs++;
if(proxy0->m_uniqueId>proxy1->m_uniqueId)
btSwap(proxy0,proxy1);
int proxyId1 = proxy0->getUid();
int proxyId2 = proxy1->getUid();
/*if (proxyId1 > proxyId2)
/*if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);*/
int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1));
int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
if (pair == NULL)
@@ -244,7 +288,7 @@ void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro
return 0;
}
cleanOverlappingPair(*pair, dispatcher);
cleanOverlappingPair(*pair,dispatcher);
void* userData = pair->m_internalInfo1;
@@ -282,7 +326,7 @@ void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro
int lastPairIndex = m_overlappingPairArray.size() - 1;
if (m_ghostPairCallback)
m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1, dispatcher);
m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
// If the removed pair is the last pair, we are done.
if (lastPairIndex == pairIndex)
@@ -293,8 +337,8 @@ void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro
// Remove the last pair from the hash table.
const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex];
/* missing swap here too, Nat. */
int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_pProxy0->getUid()), static_cast<unsigned int>(last->m_pProxy1->getUid())) & (m_overlappingPairArray.capacity() - 1));
/* missing swap here too, Nat. */
int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_pProxy0->getUid()), static_cast<unsigned int>(last->m_pProxy1->getUid())) & (m_overlappingPairArray.capacity()-1));
index = m_hashTable[lastHash];
btAssert(index != BT_NULL_PAIR);
@@ -328,106 +372,44 @@ void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro
return userData;
}
//#include <stdio.h>
#include "LinearMath/btQuickprof.h"
void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher)
void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
{
BT_PROFILE("btHashedOverlappingPairCache::processAllOverlappingPairs");
int i;
// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
for (i = 0; i < m_overlappingPairArray.size();)
// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
for (i=0;i<m_overlappingPairArray.size();)
{
btBroadphasePair* pair = &m_overlappingPairArray[i];
if (callback->processOverlap(*pair))
{
removeOverlappingPair(pair->m_pProxy0, pair->m_pProxy1, dispatcher);
}
else
removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher);
gOverlappingPairs--;
} else
{
i++;
}
}
}
struct MyPairIndex
{
int m_orgIndex;
int m_uidA0;
int m_uidA1;
};
class MyPairIndeSortPredicate
{
public:
bool operator()(const MyPairIndex& a, const MyPairIndex& b) const
{
const int uidA0 = a.m_uidA0;
const int uidB0 = b.m_uidA0;
const int uidA1 = a.m_uidA1;
const int uidB1 = b.m_uidA1;
return uidA0 > uidB0 || (uidA0 == uidB0 && uidA1 > uidB1);
}
};
void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher, const struct btDispatcherInfo& dispatchInfo)
{
if (dispatchInfo.m_deterministicOverlappingPairs)
{
btBroadphasePairArray& pa = getOverlappingPairArray();
btAlignedObjectArray<MyPairIndex> indices;
{
BT_PROFILE("sortOverlappingPairs");
indices.resize(pa.size());
for (int i = 0; i < indices.size(); i++)
{
const btBroadphasePair& p = pa[i];
const int uidA0 = p.m_pProxy0 ? p.m_pProxy0->m_uniqueId : -1;
const int uidA1 = p.m_pProxy1 ? p.m_pProxy1->m_uniqueId : -1;
indices[i].m_uidA0 = uidA0;
indices[i].m_uidA1 = uidA1;
indices[i].m_orgIndex = i;
}
indices.quickSort(MyPairIndeSortPredicate());
}
{
BT_PROFILE("btHashedOverlappingPairCache::processAllOverlappingPairs");
int i;
for (i = 0; i < indices.size();)
{
btBroadphasePair* pair = &pa[indices[i].m_orgIndex];
if (callback->processOverlap(*pair))
{
removeOverlappingPair(pair->m_pProxy0, pair->m_pProxy1, dispatcher);
}
else
{
i++;
}
}
}
}
else
{
processAllOverlappingPairs(callback, dispatcher);
}
}
void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
{
///need to keep hashmap in sync with pair address, so rebuild all
btBroadphasePairArray tmpPairs;
int i;
for (i = 0; i < m_overlappingPairArray.size(); i++)
for (i=0;i<m_overlappingPairArray.size();i++)
{
tmpPairs.push_back(m_overlappingPairArray[i]);
}
for (i = 0; i < tmpPairs.size(); i++)
for (i=0;i<tmpPairs.size();i++)
{
removeOverlappingPair(tmpPairs[i].m_pProxy0, tmpPairs[i].m_pProxy1, dispatcher);
removeOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1,dispatcher);
}
for (i = 0; i < m_next.size(); i++)
{
m_next[i] = BT_NULL_PAIR;
@@ -435,28 +417,32 @@ void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher
tmpPairs.quickSort(btBroadphasePairSortPredicate());
for (i = 0; i < tmpPairs.size(); i++)
for (i=0;i<tmpPairs.size();i++)
{
addOverlappingPair(tmpPairs[i].m_pProxy0, tmpPairs[i].m_pProxy1);
addOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1);
}
}
void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher)
void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1, btDispatcher* dispatcher )
{
if (!hasDeferredRemoval())
{
btBroadphasePair findPair(*proxy0, *proxy1);
btBroadphasePair findPair(*proxy0,*proxy1);
int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
if (findIndex < m_overlappingPairArray.size())
{
gOverlappingPairs--;
btBroadphasePair& pair = m_overlappingPairArray[findIndex];
void* userData = pair.m_internalInfo1;
cleanOverlappingPair(pair, dispatcher);
cleanOverlappingPair(pair,dispatcher);
if (m_ghostPairCallback)
m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1, dispatcher);
m_overlappingPairArray.swap(findIndex, m_overlappingPairArray.capacity() - 1);
m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1);
m_overlappingPairArray.pop_back();
return userData;
}
@@ -465,73 +451,99 @@ void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro
return 0;
}
btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
//don't add overlap with own
btAssert(proxy0 != proxy1);
if (!needsBroadphaseCollision(proxy0, proxy1))
if (!needsBroadphaseCollision(proxy0,proxy1))
return 0;
void* mem = &m_overlappingPairArray.expandNonInitializing();
btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0, *proxy1);
btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
gOverlappingPairs++;
gAddedPairs++;
if (m_ghostPairCallback)
m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
return pair;
}
///this findPair becomes really slow. Either sort the list to speedup the query, or
///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed.
///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address)
///Also we can use a 2D bitmap, which can be useful for a future GPU implementation
btBroadphasePair* btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
btBroadphasePair* btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
if (!needsBroadphaseCollision(proxy0, proxy1))
if (!needsBroadphaseCollision(proxy0,proxy1))
return 0;
btBroadphasePair tmpPair(*proxy0, *proxy1);
btBroadphasePair tmpPair(*proxy0,*proxy1);
int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
if (findIndex < m_overlappingPairArray.size())
{
//btAssert(it != m_overlappingPairSet.end());
btBroadphasePair* pair = &m_overlappingPairArray[findIndex];
btBroadphasePair* pair = &m_overlappingPairArray[findIndex];
return pair;
}
return 0;
}
//#include <stdio.h>
void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher)
void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
{
int i;
for (i = 0; i < m_overlappingPairArray.size();)
for (i=0;i<m_overlappingPairArray.size();)
{
btBroadphasePair* pair = &m_overlappingPairArray[i];
if (callback->processOverlap(*pair))
{
cleanOverlappingPair(*pair, dispatcher);
cleanOverlappingPair(*pair,dispatcher);
pair->m_pProxy0 = 0;
pair->m_pProxy1 = 0;
m_overlappingPairArray.swap(i, m_overlappingPairArray.size() - 1);
m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
m_overlappingPairArray.pop_back();
}
else
gOverlappingPairs--;
} else
{
i++;
}
}
}
btSortedOverlappingPairCache::btSortedOverlappingPairCache() : m_blockedForChanges(false),
m_hasDeferredRemoval(true),
m_overlapFilterCallback(0),
m_ghostPairCallback(0)
btSortedOverlappingPairCache::btSortedOverlappingPairCache():
m_blockedForChanges(false),
m_hasDeferredRemoval(true),
m_overlapFilterCallback(0),
m_ghostPairCallback(0)
{
int initialAllocatedSize = 2;
int initialAllocatedSize= 2;
m_overlappingPairArray.reserve(initialAllocatedSize);
}
@@ -539,73 +551,82 @@ btSortedOverlappingPairCache::~btSortedOverlappingPairCache()
{
}
void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher)
void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
{
if (pair.m_algorithm)
{
{
pair.m_algorithm->~btCollisionAlgorithm();
dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
pair.m_algorithm = 0;
pair.m_algorithm=0;
gRemovePairs--;
}
}
}
void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
{
class CleanPairCallback : public btOverlapCallback
class CleanPairCallback : public btOverlapCallback
{
btBroadphaseProxy* m_cleanProxy;
btOverlappingPairCache* m_pairCache;
btOverlappingPairCache* m_pairCache;
btDispatcher* m_dispatcher;
public:
CleanPairCallback(btBroadphaseProxy* cleanProxy, btOverlappingPairCache* pairCache, btDispatcher* dispatcher)
: m_cleanProxy(cleanProxy),
m_pairCache(pairCache),
m_dispatcher(dispatcher)
CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
:m_cleanProxy(cleanProxy),
m_pairCache(pairCache),
m_dispatcher(dispatcher)
{
}
virtual bool processOverlap(btBroadphasePair& pair)
virtual bool processOverlap(btBroadphasePair& pair)
{
if ((pair.m_pProxy0 == m_cleanProxy) ||
(pair.m_pProxy1 == m_cleanProxy))
{
m_pairCache->cleanOverlappingPair(pair, m_dispatcher);
m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
}
return false;
}
};
CleanPairCallback cleanPairs(proxy, this, dispatcher);
CleanPairCallback cleanPairs(proxy,this,dispatcher);
processAllOverlappingPairs(&cleanPairs,dispatcher);
processAllOverlappingPairs(&cleanPairs, dispatcher);
}
void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
{
class RemovePairCallback : public btOverlapCallback
class RemovePairCallback : public btOverlapCallback
{
btBroadphaseProxy* m_obsoleteProxy;
public:
RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
: m_obsoleteProxy(obsoleteProxy)
:m_obsoleteProxy(obsoleteProxy)
{
}
virtual bool processOverlap(btBroadphasePair& pair)
virtual bool processOverlap(btBroadphasePair& pair)
{
return ((pair.m_pProxy0 == m_obsoleteProxy) ||
(pair.m_pProxy1 == m_obsoleteProxy));
(pair.m_pProxy1 == m_obsoleteProxy));
}
};
RemovePairCallback removeCallback(proxy);
processAllOverlappingPairs(&removeCallback, dispatcher);
processAllOverlappingPairs(&removeCallback,dispatcher);
}
void btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
void btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
{
//should already be sorted
}

View File

@@ -16,6 +16,7 @@ subject to the following restrictions:
#ifndef BT_OVERLAPPING_PAIR_CACHE_H
#define BT_OVERLAPPING_PAIR_CACHE_H
#include "btBroadphaseInterface.h"
#include "btBroadphaseProxy.h"
#include "btOverlappingPairCallback.h"
@@ -23,164 +24,174 @@ subject to the following restrictions:
#include "LinearMath/btAlignedObjectArray.h"
class btDispatcher;
typedef btAlignedObjectArray<btBroadphasePair> btBroadphasePairArray;
typedef btAlignedObjectArray<btBroadphasePair> btBroadphasePairArray;
struct btOverlapCallback
struct btOverlapCallback
{
virtual ~btOverlapCallback()
{
}
{}
//return true for deletion of the pair
virtual bool processOverlap(btBroadphasePair& pair) = 0;
virtual bool processOverlap(btBroadphasePair& pair) = 0;
};
struct btOverlapFilterCallback
{
virtual ~btOverlapFilterCallback()
{
}
{}
// return true when pairs need collision
virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) const = 0;
virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0;
};
const int BT_NULL_PAIR = 0xffffffff;
extern int gRemovePairs;
extern int gAddedPairs;
extern int gFindPairs;
const int BT_NULL_PAIR=0xffffffff;
///The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases.
///The btHashedOverlappingPairCache and btSortedOverlappingPairCache classes are two implementations.
class btOverlappingPairCache : public btOverlappingPairCallback
{
public:
virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor
virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor
virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0;
virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0;
virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0;
virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0;
virtual btBroadphasePairArray& getOverlappingPairArray() = 0;
virtual btBroadphasePairArray& getOverlappingPairArray() = 0;
virtual void cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher) = 0;
virtual void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0;
virtual int getNumOverlappingPairs() const = 0;
virtual bool needsBroadphaseCollision(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1) const = 0;
virtual btOverlapFilterCallback* getOverlapFilterCallback() = 0;
virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher) = 0;
virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) = 0;
virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher* dispatcher) = 0;
virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0;
virtual void processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher, const struct btDispatcherInfo& /*dispatchInfo*/)
{
processAllOverlappingPairs(callback, dispatcher);
}
virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0;
virtual bool hasDeferredRemoval() = 0;
virtual bool hasDeferredRemoval() = 0;
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)=0;
virtual void sortOverlappingPairs(btDispatcher* dispatcher) = 0;
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback) = 0;
virtual void sortOverlappingPairs(btDispatcher* dispatcher) = 0;
};
/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
ATTRIBUTE_ALIGNED16(class)
btHashedOverlappingPairCache : public btOverlappingPairCache
class btHashedOverlappingPairCache : public btOverlappingPairCache
{
btBroadphasePairArray m_overlappingPairArray;
btBroadphasePairArray m_overlappingPairArray;
btOverlapFilterCallback* m_overlapFilterCallback;
protected:
btAlignedObjectArray<int> m_hashTable;
btAlignedObjectArray<int> m_next;
btOverlappingPairCallback* m_ghostPairCallback;
btAlignedObjectArray<int> m_hashTable;
btAlignedObjectArray<int> m_next;
btOverlappingPairCallback* m_ghostPairCallback;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btHashedOverlappingPairCache();
virtual ~btHashedOverlappingPairCache();
void removeOverlappingPairsContainingProxy(btBroadphaseProxy * proxy, btDispatcher * dispatcher);
void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual void* removeOverlappingPair(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1, btDispatcher * dispatcher);
SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1) const
virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
{
if (m_overlapFilterCallback)
return m_overlapFilterCallback->needBroadphaseCollision(proxy0, proxy1);
return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
return collides;
}
// Add a pair and return the new pair. If the pair already exists,
// no new pair is created and the old one is returned.
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1)
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
if (!needsBroadphaseCollision(proxy0, proxy1))
gAddedPairs++;
if (!needsBroadphaseCollision(proxy0,proxy1))
return 0;
return internalAddPair(proxy0, proxy1);
return internalAddPair(proxy0,proxy1);
}
void cleanProxyFromPairs(btBroadphaseProxy * proxy, btDispatcher * dispatcher);
virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher * dispatcher);
void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual void processAllOverlappingPairs(btOverlapCallback * callback, btDispatcher * dispatcher, const struct btDispatcherInfo& dispatchInfo);
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
virtual btBroadphasePair* getOverlappingPairArrayPtr()
virtual btBroadphasePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
const btBroadphasePair* getOverlappingPairArrayPtr() const
const btBroadphasePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
btBroadphasePairArray& getOverlappingPairArray()
btBroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
const btBroadphasePairArray& getOverlappingPairArray() const
const btBroadphasePairArray& getOverlappingPairArray() const
{
return m_overlappingPairArray;
}
void cleanOverlappingPair(btBroadphasePair & pair, btDispatcher * dispatcher);
void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
btBroadphasePair* findPair(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1);
btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
int GetCount() const { return m_overlappingPairArray.size(); }
// btBroadphasePair* GetPairs() { return m_pairs; }
// btBroadphasePair* GetPairs() { return m_pairs; }
btOverlapFilterCallback* getOverlapFilterCallback()
{
return m_overlapFilterCallback;
}
void setOverlapFilterCallback(btOverlapFilterCallback * callback)
void setOverlapFilterCallback(btOverlapFilterCallback* callback)
{
m_overlapFilterCallback = callback;
}
int getNumOverlappingPairs() const
int getNumOverlappingPairs() const
{
return m_overlappingPairArray.size();
}
private:
btBroadphasePair* internalAddPair(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1);
btBroadphasePair* internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
void growTables();
void growTables();
SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2)
{
{
return pair.m_pProxy0->getUid() == proxyId1 && pair.m_pProxy1->getUid() == proxyId2;
}
@@ -200,37 +211,43 @@ private:
}
*/
SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
{
unsigned int key = proxyId1 | (proxyId2 << 16);
int key = static_cast<int>(((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16));
// Thomas Wang's hash
key += ~(key << 15);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
return key;
key ^= (key >> 16);
return static_cast<unsigned int>(key);
}
SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1, int hash)
SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash)
{
int proxyId1 = proxy0->getUid();
int proxyId2 = proxy1->getUid();
#if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
#if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);
#endif
#endif
int index = m_hashTable[hash];
while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
{
index = m_next[index];
}
if (index == BT_NULL_PAIR)
if ( index == BT_NULL_PAIR )
{
return NULL;
}
@@ -240,136 +257,155 @@ private:
return &m_overlappingPairArray[index];
}
virtual bool hasDeferredRemoval()
virtual bool hasDeferredRemoval()
{
return false;
}
virtual void setInternalGhostPairCallback(btOverlappingPairCallback * ghostPairCallback)
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
{
m_ghostPairCallback = ghostPairCallback;
}
virtual void sortOverlappingPairs(btDispatcher * dispatcher);
virtual void sortOverlappingPairs(btDispatcher* dispatcher);
};
///btSortedOverlappingPairCache maintains the objects with overlapping AABB
///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase
class btSortedOverlappingPairCache : public btOverlappingPairCache
class btSortedOverlappingPairCache : public btOverlappingPairCache
{
protected:
//avoid brute-force finding all the time
btBroadphasePairArray m_overlappingPairArray;
protected:
//avoid brute-force finding all the time
btBroadphasePairArray m_overlappingPairArray;
//during the dispatch, check that user doesn't destroy/create proxy
bool m_blockedForChanges;
//during the dispatch, check that user doesn't destroy/create proxy
bool m_blockedForChanges;
///by default, do the removal during the pair traversal
bool m_hasDeferredRemoval;
///by default, do the removal during the pair traversal
bool m_hasDeferredRemoval;
//if set, use the callback instead of the built in filter in needBroadphaseCollision
btOverlapFilterCallback* m_overlapFilterCallback;
//if set, use the callback instead of the built in filter in needBroadphaseCollision
btOverlapFilterCallback* m_overlapFilterCallback;
btOverlappingPairCallback* m_ghostPairCallback;
btOverlappingPairCallback* m_ghostPairCallback;
public:
btSortedOverlappingPairCache();
virtual ~btSortedOverlappingPairCache();
public:
btSortedOverlappingPairCache();
virtual ~btSortedOverlappingPairCache();
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher* dispatcher);
void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
void* removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher);
void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
void cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher);
btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
void cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
{
if (m_overlapFilterCallback)
return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
return collides;
}
btBroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) const
{
if (m_overlapFilterCallback)
return m_overlapFilterCallback->needBroadphaseCollision(proxy0, proxy1);
const btBroadphasePairArray& getOverlappingPairArray() const
{
return m_overlappingPairArray;
}
bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
return collides;
}
btBroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
btBroadphasePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
const btBroadphasePairArray& getOverlappingPairArray() const
{
return m_overlappingPairArray;
}
const btBroadphasePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
btBroadphasePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
int getNumOverlappingPairs() const
{
return m_overlappingPairArray.size();
}
btOverlapFilterCallback* getOverlapFilterCallback()
{
return m_overlapFilterCallback;
}
const btBroadphasePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
void setOverlapFilterCallback(btOverlapFilterCallback* callback)
{
m_overlapFilterCallback = callback;
}
int getNumOverlappingPairs() const
{
return m_overlappingPairArray.size();
}
virtual bool hasDeferredRemoval()
{
return m_hasDeferredRemoval;
}
btOverlapFilterCallback* getOverlapFilterCallback()
{
return m_overlapFilterCallback;
}
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
{
m_ghostPairCallback = ghostPairCallback;
}
void setOverlapFilterCallback(btOverlapFilterCallback* callback)
{
m_overlapFilterCallback = callback;
}
virtual void sortOverlappingPairs(btDispatcher* dispatcher);
virtual bool hasDeferredRemoval()
{
return m_hasDeferredRemoval;
}
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
{
m_ghostPairCallback = ghostPairCallback;
}
virtual void sortOverlappingPairs(btDispatcher* dispatcher);
};
///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing.
class btNullPairCache : public btOverlappingPairCache
{
btBroadphasePairArray m_overlappingPairArray;
btBroadphasePairArray m_overlappingPairArray;
public:
virtual btBroadphasePair* getOverlappingPairArrayPtr()
virtual btBroadphasePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
const btBroadphasePair* getOverlappingPairArrayPtr() const
const btBroadphasePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
btBroadphasePairArray& getOverlappingPairArray()
btBroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/, btDispatcher* /*dispatcher*/)
virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/)
{
}
virtual int getNumOverlappingPairs() const
@@ -377,23 +413,16 @@ public:
return 0;
}
virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/, btDispatcher* /*dispatcher*/)
virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
{
}
virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
{
}
bool needsBroadphaseCollision(btBroadphaseProxy*, btBroadphaseProxy*) const
{
return true;
}
btOverlapFilterCallback* getOverlapFilterCallback()
{
return 0;
}
virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
{
}
virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher* /*dispatcher*/)
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/)
{
}
@@ -402,33 +431,39 @@ public:
return 0;
}
virtual bool hasDeferredRemoval()
virtual bool hasDeferredRemoval()
{
return true;
}
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */)
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */)
{
}
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/)
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/)
{
return 0;
}
virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/, btDispatcher* /*dispatcher*/)
virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/,btDispatcher* /*dispatcher*/)
{
return 0;
}
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/, btDispatcher* /*dispatcher*/)
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/)
{
}
virtual void sortOverlappingPairs(btDispatcher* dispatcher)
{
(void) dispatcher;
}
virtual void sortOverlappingPairs(btDispatcher* dispatcher)
{
(void)dispatcher;
}
};
#endif //BT_OVERLAPPING_PAIR_CACHE_H
#endif //BT_OVERLAPPING_PAIR_CACHE_H

View File

@@ -18,24 +18,23 @@ subject to the following restrictions:
#define OVERLAPPING_PAIR_CALLBACK_H
class btDispatcher;
struct btBroadphasePair;
struct btBroadphasePair;
///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
class btOverlappingPairCallback
{
protected:
btOverlappingPairCallback() {}
public:
virtual ~btOverlappingPairCallback()
{
}
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0;
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0;
virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) = 0;
virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher) = 0;
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) = 0;
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0, btDispatcher* dispatcher) = 0;
};
#endif //OVERLAPPING_PAIR_CALLBACK_H
#endif //OVERLAPPING_PAIR_CALLBACK_H

File diff suppressed because it is too large Load Diff

View File

@@ -22,11 +22,11 @@ class btSerializer;
#ifdef DEBUG_CHECK_DEQUANTIZATION
#ifdef __SPU__
#define printf spu_printf
#endif //__SPU__
#endif //__SPU__
#include <stdio.h>
#include <stdlib.h>
#endif //DEBUG_CHECK_DEQUANTIZATION
#endif //DEBUG_CHECK_DEQUANTIZATION
#include "LinearMath/btVector3.h"
#include "LinearMath/btAlignedAllocator.h"
@@ -41,10 +41,13 @@ class btSerializer;
#define btQuantizedBvhDataName "btQuantizedBvhFloatData"
#endif
//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
//Note: currently we have 16 bytes per quantized node
#define MAX_SUBTREE_SIZE_IN_BYTES 2048
#define MAX_SUBTREE_SIZE_IN_BYTES 2048
// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
// actually) triangles each (since the sign bit is reserved
@@ -52,16 +55,15 @@ class btSerializer;
///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
ATTRIBUTE_ALIGNED16(struct)
btQuantizedBvhNode
ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode
{
BT_DECLARE_ALIGNED_ALLOCATOR();
//12 bytes
unsigned short int m_quantizedAabbMin[3];
unsigned short int m_quantizedAabbMax[3];
unsigned short int m_quantizedAabbMin[3];
unsigned short int m_quantizedAabbMax[3];
//4 bytes
int m_escapeIndexOrTriangleIndex;
int m_escapeIndexOrTriangleIndex;
bool isLeafNode() const
{
@@ -73,67 +75,68 @@ btQuantizedBvhNode
btAssert(!isLeafNode());
return -m_escapeIndexOrTriangleIndex;
}
int getTriangleIndex() const
int getTriangleIndex() const
{
btAssert(isLeafNode());
unsigned int x = 0;
unsigned int y = (~(x & 0)) << (31 - MAX_NUM_PARTS_IN_BITS);
unsigned int x=0;
unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
// Get only the lower bits where the triangle index is stored
return (m_escapeIndexOrTriangleIndex & ~(y));
return (m_escapeIndexOrTriangleIndex&~(y));
}
int getPartId() const
int getPartId() const
{
btAssert(isLeafNode());
// Get only the highest bits where the part index is stored
return (m_escapeIndexOrTriangleIndex >> (31 - MAX_NUM_PARTS_IN_BITS));
return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
}
};
}
;
/// btOptimizedBvhNode contains both internal and leaf node information.
/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes.
ATTRIBUTE_ALIGNED16(struct)
btOptimizedBvhNode
ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode
{
BT_DECLARE_ALIGNED_ALLOCATOR();
//32 bytes
btVector3 m_aabbMinOrg;
btVector3 m_aabbMaxOrg;
btVector3 m_aabbMinOrg;
btVector3 m_aabbMaxOrg;
//4
int m_escapeIndex;
int m_escapeIndex;
//8
//for child nodes
int m_subPart;
int m_triangleIndex;
int m_subPart;
int m_triangleIndex;
//pad the size to 64 bytes
char m_padding[20];
//pad the size to 64 bytes
char m_padding[20];
};
///btBvhSubtreeInfo provides info to gather a subtree of limited size
ATTRIBUTE_ALIGNED16(class)
btBvhSubtreeInfo
ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo
{
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
//12 bytes
unsigned short int m_quantizedAabbMin[3];
unsigned short int m_quantizedAabbMax[3];
unsigned short int m_quantizedAabbMin[3];
unsigned short int m_quantizedAabbMax[3];
//4 bytes, points to the root of the subtree
int m_rootNodeIndex;
int m_rootNodeIndex;
//4 bytes
int m_subtreeSize;
int m_padding[3];
int m_subtreeSize;
int m_padding[3];
btBvhSubtreeInfo()
{
//memset(&m_padding[0], 0, sizeof(m_padding));
}
void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode)
void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode)
{
m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
@@ -142,12 +145,14 @@ public:
m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
}
};
}
;
class btNodeOverlapCallback
{
public:
virtual ~btNodeOverlapCallback(){};
virtual ~btNodeOverlapCallback() {};
virtual void processNode(int subPart, int triangleIndex) = 0;
};
@@ -155,16 +160,18 @@ public:
#include "LinearMath/btAlignedAllocator.h"
#include "LinearMath/btAlignedObjectArray.h"
///for code readability:
typedef btAlignedObjectArray<btOptimizedBvhNode> NodeArray;
typedef btAlignedObjectArray<btQuantizedBvhNode> QuantizedNodeArray;
typedef btAlignedObjectArray<btBvhSubtreeInfo> BvhSubtreeInfoArray;
typedef btAlignedObjectArray<btOptimizedBvhNode> NodeArray;
typedef btAlignedObjectArray<btQuantizedBvhNode> QuantizedNodeArray;
typedef btAlignedObjectArray<btBvhSubtreeInfo> BvhSubtreeInfoArray;
///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU.
///It is used by the btBvhTriangleMeshShape as midphase.
///It is used by the btBvhTriangleMeshShape as midphase, and by the btMultiSapBroadphase.
///It is recommended to use quantization for better performance and lower memory requirements.
ATTRIBUTE_ALIGNED16(class)
btQuantizedBvh
ATTRIBUTE_ALIGNED16(class) btQuantizedBvh
{
public:
enum btTraversalMode
@@ -175,47 +182,54 @@ public:
};
protected:
btVector3 m_bvhAabbMin;
btVector3 m_bvhAabbMax;
btVector3 m_bvhQuantization;
int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess.
int m_curNodeIndex;
btVector3 m_bvhAabbMin;
btVector3 m_bvhAabbMax;
btVector3 m_bvhQuantization;
int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess.
int m_curNodeIndex;
//quantization data
bool m_useQuantization;
bool m_useQuantization;
NodeArray m_leafNodes;
NodeArray m_contiguousNodes;
QuantizedNodeArray m_quantizedLeafNodes;
QuantizedNodeArray m_quantizedContiguousNodes;
btTraversalMode m_traversalMode;
BvhSubtreeInfoArray m_SubtreeHeaders;
NodeArray m_leafNodes;
NodeArray m_contiguousNodes;
QuantizedNodeArray m_quantizedLeafNodes;
QuantizedNodeArray m_quantizedContiguousNodes;
btTraversalMode m_traversalMode;
BvhSubtreeInfoArray m_SubtreeHeaders;
//This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray
mutable int m_subtreeHeaderCount;
///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!)
///this might be refactored into a virtual, it is usually not calculated at run-time
void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin)
void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin)
{
if (m_useQuantization)
{
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0], aabbMin, 0);
}
else
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0);
} else
{
m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
}
}
void setInternalNodeAabbMax(int nodeIndex, const btVector3& aabbMax)
void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax)
{
if (m_useQuantization)
{
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0], aabbMax, 1);
}
else
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1);
} else
{
m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
}
@@ -229,102 +243,115 @@ protected:
}
//non-quantized
return m_leafNodes[nodeIndex].m_aabbMinOrg;
}
btVector3 getAabbMax(int nodeIndex) const
{
if (m_useQuantization)
{
return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
}
}
//non-quantized
return m_leafNodes[nodeIndex].m_aabbMaxOrg;
}
void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
{
if (m_useQuantization)
{
m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex;
}
}
else
{
m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex;
}
}
void mergeInternalNodeAabb(int nodeIndex, const btVector3& newAabbMin, const btVector3& newAabbMax)
void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax)
{
if (m_useQuantization)
{
unsigned short int quantizedAabbMin[3];
unsigned short int quantizedAabbMax[3];
quantize(quantizedAabbMin, newAabbMin, 0);
quantize(quantizedAabbMax, newAabbMax, 1);
for (int i = 0; i < 3; i++)
quantize(quantizedAabbMin,newAabbMin,0);
quantize(quantizedAabbMax,newAabbMax,1);
for (int i=0;i<3;i++)
{
if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
}
}
else
} else
{
//non-quantized
m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
}
}
void swapLeafNodes(int firstIndex, int secondIndex);
void swapLeafNodes(int firstIndex,int secondIndex);
void assignInternalNodeFromLeafNode(int internalNode, int leafNodeIndex);
void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex);
protected:
void buildTree(int startIndex, int endIndex);
int calcSplittingAxis(int startIndex, int endIndex);
int sortAndCalcSplittingIndex(int startIndex, int endIndex, int splitAxis);
void buildTree (int startIndex,int endIndex);
void walkStacklessTree(btNodeOverlapCallback * nodeCallback, const btVector3& aabbMin, const btVector3& aabbMax) const;
int calcSplittingAxis(int startIndex,int endIndex);
void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex, int endNodeIndex) const;
void walkStacklessQuantizedTree(btNodeOverlapCallback * nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax, int startNodeIndex, int endNodeIndex) const;
void walkStacklessTreeAgainstRay(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex, int endNodeIndex) const;
int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis);
void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const;
void walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
///tree traversal designed for small-memory processors like PS3 SPU
void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback * nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const;
void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode, btNodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const;
void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA, const btQuantizedBvhNode* treeNodeB, btNodeOverlapCallback* nodeCallback) const;
void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const;
void updateSubtreeHeaders(int leftChildNodexIndex, int rightChildNodexIndex);
void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex);
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btQuantizedBvh();
virtual ~btQuantizedBvh();
///***************************************** expert/internal use only *************************
void setQuantizationValues(const btVector3& bvhAabbMin, const btVector3& bvhAabbMax, btScalar quantizationMargin = btScalar(1.0));
QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0));
QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
void buildInternal();
void buildInternal();
///***************************************** expert/internal use only *************************
void reportAabbOverlappingNodex(btNodeOverlapCallback * nodeCallback, const btVector3& aabbMin, const btVector3& aabbMax) const;
void reportRayOverlappingNodex(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
void reportBoxCastOverlappingNodex(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax) const;
void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
void reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
void reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const;
SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point, int isMax) const
SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const
{
btAssert(m_useQuantization);
btAssert(point.getX() <= m_bvhAabbMax.getX());
@@ -341,114 +368,122 @@ public:
///@todo: double-check this
if (isMax)
{
out[0] = (unsigned short)(((unsigned short)(v.getX() + btScalar(1.)) | 1));
out[1] = (unsigned short)(((unsigned short)(v.getY() + btScalar(1.)) | 1));
out[2] = (unsigned short)(((unsigned short)(v.getZ() + btScalar(1.)) | 1));
}
else
out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1));
out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1));
out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1));
} else
{
out[0] = (unsigned short)(((unsigned short)(v.getX()) & 0xfffe));
out[1] = (unsigned short)(((unsigned short)(v.getY()) & 0xfffe));
out[2] = (unsigned short)(((unsigned short)(v.getZ()) & 0xfffe));
out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe));
out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe));
out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe));
}
#ifdef DEBUG_CHECK_DEQUANTIZATION
btVector3 newPoint = unQuantize(out);
if (isMax)
{
if (newPoint.getX() < point.getX())
{
printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n", newPoint.getX() - point.getX(), newPoint.getX(), point.getX());
printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
}
if (newPoint.getY() < point.getY())
{
printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n", newPoint.getY() - point.getY(), newPoint.getY(), point.getY());
printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
}
if (newPoint.getZ() < point.getZ())
{
printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n", newPoint.getZ() - point.getZ(), newPoint.getZ(), point.getZ());
printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
}
}
else
} else
{
if (newPoint.getX() > point.getX())
{
printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n", newPoint.getX() - point.getX(), newPoint.getX(), point.getX());
printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
}
if (newPoint.getY() > point.getY())
{
printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n", newPoint.getY() - point.getY(), newPoint.getY(), point.getY());
printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
}
if (newPoint.getZ() > point.getZ())
{
printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n", newPoint.getZ() - point.getZ(), newPoint.getZ(), point.getZ());
printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
}
}
#endif //DEBUG_CHECK_DEQUANTIZATION
#endif //DEBUG_CHECK_DEQUANTIZATION
}
SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2, int isMax) const
SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const
{
btAssert(m_useQuantization);
btVector3 clampedPoint(point2);
clampedPoint.setMax(m_bvhAabbMin);
clampedPoint.setMin(m_bvhAabbMax);
quantize(out, clampedPoint, isMax);
}
quantize(out,clampedPoint,isMax);
SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const
}
SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const
{
btVector3 vecOut;
vecOut.setValue(
btVector3 vecOut;
vecOut.setValue(
(btScalar)(vecIn[0]) / (m_bvhQuantization.getX()),
(btScalar)(vecIn[1]) / (m_bvhQuantization.getY()),
(btScalar)(vecIn[2]) / (m_bvhQuantization.getZ()));
vecOut += m_bvhAabbMin;
return vecOut;
vecOut += m_bvhAabbMin;
return vecOut;
}
///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees.
void setTraversalMode(btTraversalMode traversalMode)
void setTraversalMode(btTraversalMode traversalMode)
{
m_traversalMode = traversalMode;
}
SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
{
return m_quantizedContiguousNodes;
SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
{
return m_quantizedContiguousNodes;
}
SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
{
return m_SubtreeHeaders;
}
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
/////Calculate space needed to store BVH for serialization
unsigned calculateSerializeBufferSize() const;
/// Data buffer MUST be 16 byte aligned
virtual bool serialize(void* o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
static btQuantizedBvh* deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
static unsigned int getAlignmentSerializationPadding();
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
virtual int calculateSerializeBufferSizeNew() const;
virtual int calculateSerializeBufferSizeNew() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
virtual void deSerializeFloat(struct btQuantizedBvhFloatData & quantizedBvhFloatData);
virtual void deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData);
virtual void deSerializeDouble(struct btQuantizedBvhDoubleData & quantizedBvhDoubleData);
virtual void deSerializeDouble(struct btQuantizedBvhDoubleData& quantizedBvhDoubleData);
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
SIMD_FORCE_INLINE bool isQuantized()
{
@@ -459,37 +494,38 @@ private:
// Special "copy" constructor that allows for in-place deserialization
// Prevents btVector3's default constructor from being called, but doesn't inialize much else
// ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need)
btQuantizedBvh(btQuantizedBvh & other, bool ownsMemory);
};
btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory);
// clang-format off
// parser needs * with the name
struct btBvhSubtreeInfoData
}
;
struct btBvhSubtreeInfoData
{
int m_rootNodeIndex;
int m_subtreeSize;
int m_rootNodeIndex;
int m_subtreeSize;
unsigned short m_quantizedAabbMin[3];
unsigned short m_quantizedAabbMax[3];
};
struct btOptimizedBvhNodeFloatData
{
btVector3FloatData m_aabbMinOrg;
btVector3FloatData m_aabbMaxOrg;
int m_escapeIndex;
int m_subPart;
int m_triangleIndex;
btVector3FloatData m_aabbMinOrg;
btVector3FloatData m_aabbMaxOrg;
int m_escapeIndex;
int m_subPart;
int m_triangleIndex;
char m_pad[4];
};
struct btOptimizedBvhNodeDoubleData
{
btVector3DoubleData m_aabbMinOrg;
btVector3DoubleData m_aabbMaxOrg;
int m_escapeIndex;
int m_subPart;
int m_triangleIndex;
char m_pad[4];
btVector3DoubleData m_aabbMinOrg;
btVector3DoubleData m_aabbMaxOrg;
int m_escapeIndex;
int m_subPart;
int m_triangleIndex;
char m_pad[4];
};
@@ -533,11 +569,13 @@ struct btQuantizedBvhDoubleData
int m_numSubtreeHeaders;
btBvhSubtreeInfoData *m_subTreeInfoPtr;
};
// clang-format on
SIMD_FORCE_INLINE int btQuantizedBvh::calculateSerializeBufferSizeNew() const
SIMD_FORCE_INLINE int btQuantizedBvh::calculateSerializeBufferSizeNew() const
{
return sizeof(btQuantizedBvhData);
}
#endif //BT_QUANTIZED_BVH_H
#endif //BT_QUANTIZED_BVH_H

View File

@@ -24,45 +24,52 @@ subject to the following restrictions:
#include <new>
void btSimpleBroadphase::validate()
extern int gOverlappingPairs;
void btSimpleBroadphase::validate()
{
for (int i = 0; i < m_numHandles; i++)
for (int i=0;i<m_numHandles;i++)
{
for (int j = i + 1; j < m_numHandles; j++)
for (int j=i+1;j<m_numHandles;j++)
{
btAssert(&m_pHandles[i] != &m_pHandles[j]);
}
}
}
btSimpleBroadphase::btSimpleBroadphase(int maxProxies, btOverlappingPairCache* overlappingPairCache)
: m_pairCache(overlappingPairCache),
m_ownsPairCache(false),
m_invalidPair(0)
:m_pairCache(overlappingPairCache),
m_ownsPairCache(false),
m_invalidPair(0)
{
if (!overlappingPairCache)
{
void* mem = btAlignedAlloc(sizeof(btHashedOverlappingPairCache), 16);
m_pairCache = new (mem) btHashedOverlappingPairCache();
void* mem = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16);
m_pairCache = new (mem)btHashedOverlappingPairCache();
m_ownsPairCache = true;
}
// allocate handles buffer and put all handles on free list
m_pHandlesRawPtr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy) * maxProxies, 16);
m_pHandles = new (m_pHandlesRawPtr) btSimpleBroadphaseProxy[maxProxies];
m_pHandlesRawPtr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy)*maxProxies,16);
m_pHandles = new(m_pHandlesRawPtr) btSimpleBroadphaseProxy[maxProxies];
m_maxHandles = maxProxies;
m_numHandles = 0;
m_firstFreeHandle = 0;
m_LastHandleIndex = -1;
{
for (int i = m_firstFreeHandle; i < maxProxies; i++)
{
m_pHandles[i].SetNextFree(i + 1);
m_pHandles[i].m_uniqueId = i + 2; //any UID will do, we just avoid too trivial values (0,1) for debugging purposes
m_pHandles[i].m_uniqueId = i+2;//any UID will do, we just avoid too trivial values (0,1) for debugging purposes
}
m_pHandles[maxProxies - 1].SetNextFree(0);
}
}
btSimpleBroadphase::~btSimpleBroadphase()
@@ -76,25 +83,26 @@ btSimpleBroadphase::~btSimpleBroadphase()
}
}
btBroadphaseProxy* btSimpleBroadphase::createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* /*dispatcher*/)
btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* /*dispatcher*/,void* multiSapProxy)
{
if (m_numHandles >= m_maxHandles)
{
btAssert(0);
return 0; //should never happen, but don't let the game crash ;-)
return 0; //should never happen, but don't let the game crash ;-)
}
btAssert(aabbMin[0] <= aabbMax[0] && aabbMin[1] <= aabbMax[1] && aabbMin[2] <= aabbMax[2]);
btAssert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]);
int newHandleIndex = allocHandle();
btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex]) btSimpleBroadphaseProxy(aabbMin, aabbMax, shapeType, userPtr, collisionFilterGroup, collisionFilterMask);
btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy);
return proxy;
}
class RemovingOverlapCallback : public btOverlapCallback
class RemovingOverlapCallback : public btOverlapCallback
{
protected:
virtual bool processOverlap(btBroadphasePair& pair)
virtual bool processOverlap(btBroadphasePair& pair)
{
(void)pair;
btAssert(0);
@@ -104,13 +112,12 @@ protected:
class RemovePairContainingProxy
{
btBroadphaseProxy* m_targetProxy;
public:
btBroadphaseProxy* m_targetProxy;
public:
virtual ~RemovePairContainingProxy()
{
}
protected:
virtual bool processOverlap(btBroadphasePair& pair)
{
@@ -121,36 +128,38 @@ protected:
};
};
void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg, btDispatcher* dispatcher)
void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* dispatcher)
{
m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg, dispatcher);
btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxyOrg);
freeHandle(proxy0);
btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxyOrg);
freeHandle(proxy0);
m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher);
//validate();
//validate();
}
void btSimpleBroadphase::getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const
void btSimpleBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
{
const btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
aabbMin = sbp->m_aabbMin;
aabbMax = sbp->m_aabbMax;
}
void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* /*dispatcher*/)
void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* /*dispatcher*/)
{
btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
sbp->m_aabbMin = aabbMin;
sbp->m_aabbMax = aabbMax;
}
void btSimpleBroadphase::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin, const btVector3& aabbMax)
void btSimpleBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax)
{
for (int i = 0; i <= m_LastHandleIndex; i++)
for (int i=0; i <= m_LastHandleIndex; i++)
{
btSimpleBroadphaseProxy* proxy = &m_pHandles[i];
if (!proxy->m_clientObject)
if(!proxy->m_clientObject)
{
continue;
}
@@ -158,59 +167,69 @@ void btSimpleBroadphase::rayTest(const btVector3& rayFrom, const btVector3& rayT
}
}
void btSimpleBroadphase::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
void btSimpleBroadphase::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
{
for (int i = 0; i <= m_LastHandleIndex; i++)
for (int i=0; i <= m_LastHandleIndex; i++)
{
btSimpleBroadphaseProxy* proxy = &m_pHandles[i];
if (!proxy->m_clientObject)
if(!proxy->m_clientObject)
{
continue;
}
if (TestAabbAgainstAabb2(aabbMin, aabbMax, proxy->m_aabbMin, proxy->m_aabbMax))
if (TestAabbAgainstAabb2(aabbMin,aabbMax,proxy->m_aabbMin,proxy->m_aabbMax))
{
callback.process(proxy);
}
}
}
bool btSimpleBroadphase::aabbOverlap(btSimpleBroadphaseProxy* proxy0, btSimpleBroadphaseProxy* proxy1)
bool btSimpleBroadphase::aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1)
{
return proxy0->m_aabbMin[0] <= proxy1->m_aabbMax[0] && proxy1->m_aabbMin[0] <= proxy0->m_aabbMax[0] &&
return proxy0->m_aabbMin[0] <= proxy1->m_aabbMax[0] && proxy1->m_aabbMin[0] <= proxy0->m_aabbMax[0] &&
proxy0->m_aabbMin[1] <= proxy1->m_aabbMax[1] && proxy1->m_aabbMin[1] <= proxy0->m_aabbMax[1] &&
proxy0->m_aabbMin[2] <= proxy1->m_aabbMax[2] && proxy1->m_aabbMin[2] <= proxy0->m_aabbMax[2];
}
//then remove non-overlapping ones
class CheckOverlapCallback : public btOverlapCallback
{
public:
virtual bool processOverlap(btBroadphasePair& pair)
{
return (!btSimpleBroadphase::aabbOverlap(static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0), static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1)));
return (!btSimpleBroadphase::aabbOverlap(static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0),static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1)));
}
};
void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
{
//first check for new overlapping pairs
int i, j;
int i,j;
if (m_numHandles >= 0)
{
int new_largest_index = -1;
for (i = 0; i <= m_LastHandleIndex; i++)
for (i=0; i <= m_LastHandleIndex; i++)
{
btSimpleBroadphaseProxy* proxy0 = &m_pHandles[i];
if (!proxy0->m_clientObject)
if(!proxy0->m_clientObject)
{
continue;
}
new_largest_index = i;
for (j = i + 1; j <= m_LastHandleIndex; j++)
for (j=i+1; j <= m_LastHandleIndex; j++)
{
btSimpleBroadphaseProxy* proxy1 = &m_pHandles[j];
btAssert(proxy0 != proxy1);
if (!proxy1->m_clientObject)
if(!proxy1->m_clientObject)
{
continue;
}
@@ -218,20 +237,19 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
if (aabbOverlap(p0, p1))
if (aabbOverlap(p0,p1))
{
if (!m_pairCache->findPair(proxy0, proxy1))
if ( !m_pairCache->findPair(proxy0,proxy1))
{
m_pairCache->addOverlappingPair(proxy0, proxy1);
m_pairCache->addOverlappingPair(proxy0,proxy1);
}
}
else
} else
{
if (!m_pairCache->hasDeferredRemoval())
{
if (m_pairCache->findPair(proxy0, proxy1))
if ( m_pairCache->findPair(proxy0,proxy1))
{
m_pairCache->removeOverlappingPair(proxy0, proxy1, dispatcher);
m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher);
}
}
}
@@ -242,7 +260,8 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
if (m_ownsPairCache && m_pairCache->hasDeferredRemoval())
{
btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
@@ -250,13 +269,16 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
btBroadphasePair previousPair;
previousPair.m_pProxy0 = 0;
previousPair.m_pProxy1 = 0;
previousPair.m_algorithm = 0;
for (i = 0; i < overlappingPairArray.size(); i++)
for (i=0;i<overlappingPairArray.size();i++)
{
btBroadphasePair& pair = overlappingPairArray[i];
bool isDuplicate = (pair == previousPair);
@@ -267,18 +289,16 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
if (!isDuplicate)
{
bool hasOverlap = testAabbOverlap(pair.m_pProxy0, pair.m_pProxy1);
bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
if (hasOverlap)
{
needsRemoval = false; //callback->processOverlap(pair);
}
else
needsRemoval = false;//callback->processOverlap(pair);
} else
{
needsRemoval = true;
}
}
else
} else
{
//remove duplicate
needsRemoval = true;
@@ -288,14 +308,16 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
if (needsRemoval)
{
m_pairCache->cleanOverlappingPair(pair, dispatcher);
m_pairCache->cleanOverlappingPair(pair,dispatcher);
// m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
// m_overlappingPairArray.pop_back();
pair.m_pProxy0 = 0;
pair.m_pProxy1 = 0;
m_invalidPair++;
}
gOverlappingPairs--;
}
}
///if you don't like to skip the invalid pairs in the array, execute following code:
@@ -307,19 +329,21 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
#endif //CLEAN_INVALID_PAIRS
#endif//CLEAN_INVALID_PAIRS
}
}
}
bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
return aabbOverlap(p0, p1);
return aabbOverlap(p0,p1);
}
void btSimpleBroadphase::resetPool(btDispatcher* dispatcher)
void btSimpleBroadphase::resetPool(btDispatcher* dispatcher)
{
//not yet
}

View File

@@ -16,47 +16,57 @@ subject to the following restrictions:
#ifndef BT_SIMPLE_BROADPHASE_H
#define BT_SIMPLE_BROADPHASE_H
#include "btOverlappingPairCache.h"
struct btSimpleBroadphaseProxy : public btBroadphaseProxy
{
int m_nextFree;
int m_nextFree;
// int m_handleId;
// int m_handleId;
btSimpleBroadphaseProxy() {};
btSimpleBroadphaseProxy(){};
btSimpleBroadphaseProxy(const btVector3& minpt, const btVector3& maxpt, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask)
: btBroadphaseProxy(minpt, maxpt, userPtr, collisionFilterGroup, collisionFilterMask)
btSimpleBroadphaseProxy(const btVector3& minpt,const btVector3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,void* multiSapProxy)
:btBroadphaseProxy(minpt,maxpt,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy)
{
(void)shapeType;
}
SIMD_FORCE_INLINE void SetNextFree(int next) {m_nextFree = next;}
SIMD_FORCE_INLINE int GetNextFree() const {return m_nextFree;}
SIMD_FORCE_INLINE void SetNextFree(int next) { m_nextFree = next; }
SIMD_FORCE_INLINE int GetNextFree() const { return m_nextFree; }
};
///The SimpleBroadphase is just a unit-test for btAxisSweep3, bt32BitAxisSweep3, or btDbvtBroadphase, so use those classes instead.
///It is a brute force aabb culling broadphase based on O(n^2) aabb checks
class btSimpleBroadphase : public btBroadphaseInterface
{
protected:
int m_numHandles; // number of active handles
int m_maxHandles; // max number of handles
int m_LastHandleIndex;
btSimpleBroadphaseProxy* m_pHandles; // handles pool
protected:
int m_numHandles; // number of active handles
int m_maxHandles; // max number of handles
int m_LastHandleIndex;
btSimpleBroadphaseProxy* m_pHandles; // handles pool
void* m_pHandlesRawPtr;
int m_firstFreeHandle; // free handles list
int m_firstFreeHandle; // free handles list
int allocHandle()
{
btAssert(m_numHandles < m_maxHandles);
int freeHandle = m_firstFreeHandle;
m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree();
m_numHandles++;
if (freeHandle > m_LastHandleIndex)
if(freeHandle > m_LastHandleIndex)
{
m_LastHandleIndex = freeHandle;
}
@@ -65,9 +75,9 @@ protected:
void freeHandle(btSimpleBroadphaseProxy* proxy)
{
int handle = int(proxy - m_pHandles);
int handle = int(proxy-m_pHandles);
btAssert(handle >= 0 && handle < m_maxHandles);
if (handle == m_LastHandleIndex)
if(handle == m_LastHandleIndex)
{
m_LastHandleIndex--;
}
@@ -79,18 +89,20 @@ protected:
m_numHandles--;
}
btOverlappingPairCache* m_pairCache;
bool m_ownsPairCache;
btOverlappingPairCache* m_pairCache;
bool m_ownsPairCache;
int m_invalidPair;
int m_invalidPair;
inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy)
inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy)
{
btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxy);
return proxy0;
}
inline const btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy) const
inline const btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy) const
{
const btSimpleBroadphaseProxy* proxy0 = static_cast<const btSimpleBroadphaseProxy*>(proxy);
return proxy0;
@@ -99,50 +111,61 @@ protected:
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(btDispatcher* dispatcher);
void validate();
void validate();
protected:
public:
btSimpleBroadphase(int maxProxies = 16384, btOverlappingPairCache* overlappingPairCache = 0);
btSimpleBroadphase(int maxProxies=16384,btOverlappingPairCache* overlappingPairCache=0);
virtual ~btSimpleBroadphase();
static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0, btSimpleBroadphaseProxy* proxy1);
virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1);
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy);
virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0));
virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
btOverlappingPairCache* getOverlappingPairCache()
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0));
virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
btOverlappingPairCache* getOverlappingPairCache()
{
return m_pairCache;
}
const btOverlappingPairCache* getOverlappingPairCache() const
const btOverlappingPairCache* getOverlappingPairCache() const
{
return m_pairCache;
}
bool testAabbOverlap(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
///will add some transform later
virtual void getBroadphaseAabb(btVector3& aabbMin, btVector3& aabbMax) const
virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
{
aabbMin.setValue(-BT_LARGE_FLOAT, -BT_LARGE_FLOAT, -BT_LARGE_FLOAT);
aabbMax.setValue(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT);
aabbMin.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT);
aabbMax.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT);
}
virtual void printStats()
virtual void printStats()
{
// printf("btSimpleBroadphase.h\n");
// printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
// printf("btSimpleBroadphase.h\n");
// printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
}
};
#endif //BT_SIMPLE_BROADPHASE_H
#endif //BT_SIMPLE_BROADPHASE_H

View File

@@ -18,162 +18,145 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere, btTriangleShape* triangle, btScalar contactBreakingThreshold)
: m_sphere(sphere),
m_triangle(triangle),
m_contactBreakingThreshold(contactBreakingThreshold)
SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle,btScalar contactBreakingThreshold)
:m_sphere(sphere),
m_triangle(triangle),
m_contactBreakingThreshold(contactBreakingThreshold)
{
}
void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults)
void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults)
{
(void)debugDraw;
const btTransform& transformA = input.m_transformA;
const btTransform& transformB = input.m_transformB;
btVector3 point, normal;
btVector3 point,normal;
btScalar timeOfImpact = btScalar(1.);
btScalar depth = btScalar(0.);
// output.m_distance = btScalar(BT_LARGE_FLOAT);
// output.m_distance = btScalar(BT_LARGE_FLOAT);
//move sphere into triangle space
btTransform sphereInTr = transformB.inverseTimes(transformA);
btTransform sphereInTr = transformB.inverseTimes(transformA);
if (collide(sphereInTr.getOrigin(), point, normal, depth, timeOfImpact, m_contactBreakingThreshold))
if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact,m_contactBreakingThreshold))
{
if (swapResults)
{
btVector3 normalOnB = transformB.getBasis() * normal;
btVector3 normalOnB = transformB.getBasis()*normal;
btVector3 normalOnA = -normalOnB;
btVector3 pointOnA = transformB * point + normalOnB * depth;
output.addContactPoint(normalOnA, pointOnA, depth);
}
else
btVector3 pointOnA = transformB*point+normalOnB*depth;
output.addContactPoint(normalOnA,pointOnA,depth);
} else
{
output.addContactPoint(transformB.getBasis() * normal, transformB * point, depth);
output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth);
}
}
}
// See also geometrictools.com
// Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv
btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to, const btVector3& p, btVector3& nearest);
btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest);
btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to, const btVector3& p, btVector3& nearest)
{
btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) {
btVector3 diff = p - from;
btVector3 v = to - from;
btScalar t = v.dot(diff);
if (t > 0)
{
if (t > 0) {
btScalar dotVV = v.dot(v);
if (t < dotVV)
{
if (t < dotVV) {
t /= dotVV;
diff -= t * v;
}
else
{
diff -= t*v;
} else {
t = 1;
diff -= v;
}
}
else
} else
t = 0;
nearest = from + t * v;
return diff.dot(diff);
nearest = from + t*v;
return diff.dot(diff);
}
bool SphereTriangleDetector::facecontains(const btVector3& p, const btVector3* vertices, btVector3& normal)
{
bool SphereTriangleDetector::facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal) {
btVector3 lp(p);
btVector3 lnormal(normal);
return pointInTriangle(vertices, lnormal, &lp);
}
bool SphereTriangleDetector::collide(const btVector3& sphereCenter, btVector3& point, btVector3& resultNormal, btScalar& depth, btScalar& timeOfImpact, btScalar contactBreakingThreshold)
bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar contactBreakingThreshold)
{
const btVector3* vertices = &m_triangle->getVertexPtr(0);
const btVector3* vertices = &m_triangle->getVertexPtr(0);
btScalar radius = m_sphere->getRadius();
btScalar radiusWithThreshold = radius + contactBreakingThreshold;
btVector3 normal = (vertices[1] - vertices[0]).cross(vertices[2] - vertices[0]);
btVector3 normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
normal.normalize();
btVector3 p1ToCentre = sphereCenter - vertices[0];
btScalar distanceFromPlane = p1ToCentre.dot(normal);
btScalar l2 = normal.length2();
if (distanceFromPlane < btScalar(0.))
{
//triangle facing the other way
distanceFromPlane *= btScalar(-1.);
normal *= btScalar(-1.);
}
bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold;
// Check for contact / intersection
bool hasContact = false;
btVector3 contactPoint;
if (isInsideContactPlane) {
if (facecontains(sphereCenter,vertices,normal)) {
// Inside the contact wedge - touches a point on the shell plane
hasContact = true;
contactPoint = sphereCenter - normal*distanceFromPlane;
} else {
// Could be inside one of the contact capsules
btScalar contactCapsuleRadiusSqr = radiusWithThreshold*radiusWithThreshold;
btVector3 nearestOnEdge;
for (int i = 0; i < m_triangle->getNumEdges(); i++) {
btVector3 pa;
btVector3 pb;
m_triangle->getEdge(i,pa,pb);
if (l2 >= SIMD_EPSILON * SIMD_EPSILON)
{
normal /= btSqrt(l2);
btVector3 p1ToCentre = sphereCenter - vertices[0];
btScalar distanceFromPlane = p1ToCentre.dot(normal);
if (distanceFromPlane < btScalar(0.))
{
//triangle facing the other way
distanceFromPlane *= btScalar(-1.);
normal *= btScalar(-1.);
}
bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold;
// Check for contact / intersection
if (isInsideContactPlane)
{
if (facecontains(sphereCenter, vertices, normal))
{
// Inside the contact wedge - touches a point on the shell plane
hasContact = true;
contactPoint = sphereCenter - normal * distanceFromPlane;
}
else
{
// Could be inside one of the contact capsules
btScalar contactCapsuleRadiusSqr = radiusWithThreshold * radiusWithThreshold;
btScalar minDistSqr = contactCapsuleRadiusSqr;
btVector3 nearestOnEdge;
for (int i = 0; i < m_triangle->getNumEdges(); i++)
{
btVector3 pa;
btVector3 pb;
m_triangle->getEdge(i, pa, pb);
btScalar distanceSqr = SegmentSqrDistance(pa, pb, sphereCenter, nearestOnEdge);
if (distanceSqr < minDistSqr)
{
// Yep, we're inside a capsule, and record the capsule with smallest distance
minDistSqr = distanceSqr;
hasContact = true;
contactPoint = nearestOnEdge;
}
btScalar distanceSqr = SegmentSqrDistance(pa,pb,sphereCenter, nearestOnEdge);
if (distanceSqr < contactCapsuleRadiusSqr) {
// Yep, we're inside a capsule
hasContact = true;
contactPoint = nearestOnEdge;
}
}
}
}
if (hasContact)
{
if (hasContact) {
btVector3 contactToCentre = sphereCenter - contactPoint;
btScalar distanceSqr = contactToCentre.length2();
if (distanceSqr < radiusWithThreshold * radiusWithThreshold)
if (distanceSqr < radiusWithThreshold*radiusWithThreshold)
{
if (distanceSqr > SIMD_EPSILON)
if (distanceSqr>SIMD_EPSILON)
{
btScalar distance = btSqrt(distanceSqr);
resultNormal = contactToCentre;
resultNormal.normalize();
point = contactPoint;
depth = -(radius - distance);
}
else
depth = -(radius-distance);
} else
{
resultNormal = normal;
point = contactPoint;
@@ -182,34 +165,36 @@ bool SphereTriangleDetector::collide(const btVector3& sphereCenter, btVector3& p
return true;
}
}
return false;
}
bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3& normal, btVector3* p)
bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p )
{
const btVector3* p1 = &vertices[0];
const btVector3* p2 = &vertices[1];
const btVector3* p3 = &vertices[2];
btVector3 edge1(*p2 - *p1);
btVector3 edge2(*p3 - *p2);
btVector3 edge3(*p1 - *p3);
btVector3 edge1( *p2 - *p1 );
btVector3 edge2( *p3 - *p2 );
btVector3 edge3( *p1 - *p3 );
btVector3 p1_to_p(*p - *p1);
btVector3 p2_to_p(*p - *p2);
btVector3 p3_to_p(*p - *p3);
btVector3 edge1_normal(edge1.cross(normal));
btVector3 edge2_normal(edge2.cross(normal));
btVector3 edge3_normal(edge3.cross(normal));
btVector3 p1_to_p( *p - *p1 );
btVector3 p2_to_p( *p - *p2 );
btVector3 p3_to_p( *p - *p3 );
btVector3 edge1_normal( edge1.cross(normal));
btVector3 edge2_normal( edge2.cross(normal));
btVector3 edge3_normal( edge3.cross(normal));
btScalar r1, r2, r3;
r1 = edge1_normal.dot(p1_to_p);
r2 = edge2_normal.dot(p2_to_p);
r3 = edge3_normal.dot(p3_to_p);
if ((r1 > 0 && r2 > 0 && r3 > 0) ||
(r1 <= 0 && r2 <= 0 && r3 <= 0))
r1 = edge1_normal.dot( p1_to_p );
r2 = edge2_normal.dot( p2_to_p );
r3 = edge3_normal.dot( p3_to_p );
if ( ( r1 > 0 && r2 > 0 && r3 > 0 ) ||
( r1 <= 0 && r2 <= 0 && r3 <= 0 ) )
return true;
return false;
}

View File

@@ -18,26 +18,34 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
class btSphereShape;
class btTriangleShape;
/// sphere-triangle to match the btDiscreteCollisionDetectorInterface
struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface
{
virtual void getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults = false);
virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
SphereTriangleDetector(btSphereShape* sphere, btTriangleShape* triangle, btScalar contactBreakingThreshold);
SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle, btScalar contactBreakingThreshold);
virtual ~SphereTriangleDetector(){};
virtual ~SphereTriangleDetector() {};
bool collide(const btVector3& sphereCenter, btVector3& point, btVector3& resultNormal, btScalar& depth, btScalar& timeOfImpact, btScalar contactBreakingThreshold);
bool collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar contactBreakingThreshold);
private:
bool pointInTriangle(const btVector3 vertices[], const btVector3& normal, btVector3* p);
bool facecontains(const btVector3& p, const btVector3* vertices, btVector3& normal);
bool pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p );
bool facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal);
btSphereShape* m_sphere;
btTriangleShape* m_triangle;
btScalar m_contactBreakingThreshold;
btScalar m_contactBreakingThreshold;
};
#endif //BT_SPHERE_TRIANGLE_DETECTOR_H
#endif //BT_SPHERE_TRIANGLE_DETECTOR_H

View File

@@ -17,31 +17,31 @@ subject to the following restrictions:
#include "btCollisionDispatcher.h"
#include "btCollisionObject.h"
btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btCollisionAlgorithm(ci)
btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci)
:btCollisionAlgorithm(ci)
//,
//m_colObj0(0),
//m_colObj1(0)
{
}
btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper*, const btCollisionObjectWrapper*)
: btCollisionAlgorithm(ci)
btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* ,const btCollisionObjectWrapper* )
:btCollisionAlgorithm(ci)
//,
//m_colObj0(0),
//m_colObj1(0)
{
// if (ci.m_dispatcher1->needsCollision(colObj0,colObj1))
// {
// m_colObj0 = colObj0;
// m_colObj1 = colObj1;
//
// m_colObj0->activate();
// m_colObj1->activate();
// }
// if (ci.m_dispatcher1->needsCollision(colObj0,colObj1))
// {
// m_colObj0 = colObj0;
// m_colObj1 = colObj1;
//
// m_colObj0->activate();
// m_colObj1->activate();
// }
}
btActivatingCollisionAlgorithm::~btActivatingCollisionAlgorithm()
{
// m_colObj0->activate();
// m_colObj1->activate();
// m_colObj0->activate();
// m_colObj1->activate();
}

View File

@@ -21,15 +21,16 @@ subject to the following restrictions:
///This class is not enabled yet (work-in-progress) to more aggressively activate objects.
class btActivatingCollisionAlgorithm : public btCollisionAlgorithm
{
// btCollisionObject* m_colObj0;
// btCollisionObject* m_colObj1;
protected:
btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
// btCollisionObject* m_colObj0;
// btCollisionObject* m_colObj1;
public:
btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci);
btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
virtual ~btActivatingCollisionAlgorithm();
};
#endif //__BT_ACTIVATING_COLLISION_ALGORITHM_H
#endif //__BT_ACTIVATING_COLLISION_ALGORITHM_H

View File

@@ -26,55 +26,61 @@ subject to the following restrictions:
#define USE_PERSISTENT_CONTACTS 1
btBox2dBox2dCollisionAlgorithm::btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* obj0Wrap, const btCollisionObjectWrapper* obj1Wrap)
: btActivatingCollisionAlgorithm(ci, obj0Wrap, obj1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf)
btBox2dBox2dCollisionAlgorithm::btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* obj0Wrap,const btCollisionObjectWrapper* obj1Wrap)
: btActivatingCollisionAlgorithm(ci,obj0Wrap,obj1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf)
{
if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0Wrap->getCollisionObject(), obj1Wrap->getCollisionObject()))
if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0Wrap->getCollisionObject(),obj1Wrap->getCollisionObject()))
{
m_manifoldPtr = m_dispatcher->getNewManifold(obj0Wrap->getCollisionObject(), obj1Wrap->getCollisionObject());
m_manifoldPtr = m_dispatcher->getNewManifold(obj0Wrap->getCollisionObject(),obj1Wrap->getCollisionObject());
m_ownManifold = true;
}
}
btBox2dBox2dCollisionAlgorithm::~btBox2dBox2dCollisionAlgorithm()
{
if (m_ownManifold)
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}
}
void b2CollidePolygons(btManifoldResult* manifold, const btBox2dShape* polyA, const btTransform& xfA, const btBox2dShape* polyB, const btTransform& xfB);
void b2CollidePolygons(btManifoldResult* manifold, const btBox2dShape* polyA, const btTransform& xfA, const btBox2dShape* polyB, const btTransform& xfB);
//#include <stdio.h>
void btBox2dBox2dCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btBox2dBox2dCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
return;
const btBox2dShape* box0 = (const btBox2dShape*)body0Wrap->getCollisionShape();
const btBox2dShape* box1 = (const btBox2dShape*)body1Wrap->getCollisionShape();
resultOut->setPersistentManifold(m_manifoldPtr);
b2CollidePolygons(resultOut, box0, body0Wrap->getWorldTransform(), box1, body1Wrap->getWorldTransform());
b2CollidePolygons(resultOut,box0,body0Wrap->getWorldTransform(),box1,body1Wrap->getWorldTransform());
// refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
if (m_ownManifold)
{
resultOut->refreshContactPoints();
}
}
btScalar btBox2dBox2dCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/, btCollisionObject* /*body1*/, const btDispatcherInfo& /*dispatchInfo*/, btManifoldResult* /*resultOut*/)
btScalar btBox2dBox2dCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
{
//not yet
return 1.f;
}
struct ClipVertex
{
btVector3 v;
@@ -83,16 +89,16 @@ struct ClipVertex
//b2ContactID id;
};
#define b2Dot(a, b) (a).dot(b)
#define b2Mul(a, b) (a) * (b)
#define b2MulT(a, b) (a).transpose() * (b)
#define b2Cross(a, b) (a).cross(b)
#define btCrossS(a, s) btVector3(s* a.getY(), -s* a.getX(), 0.f)
#define b2Dot(a,b) (a).dot(b)
#define b2Mul(a,b) (a)*(b)
#define b2MulT(a,b) (a).transpose()*(b)
#define b2Cross(a,b) (a).cross(b)
#define btCrossS(a,s) btVector3(s * a.getY(), -s * a.getX(),0.f)
int b2_maxManifoldPoints = 2;
int b2_maxManifoldPoints =2;
static int ClipSegmentToLine(ClipVertex vOut[2], ClipVertex vIn[2],
const btVector3& normal, btScalar offset)
const btVector3& normal, btScalar offset)
{
// Start with no output points
int numOut = 0;
@@ -127,7 +133,7 @@ static int ClipSegmentToLine(ClipVertex vOut[2], ClipVertex vIn[2],
// Find the separation between poly1 and poly2 for a give edge normal on poly1.
static btScalar EdgeSeparation(const btBox2dShape* poly1, const btTransform& xf1, int edge1,
const btBox2dShape* poly2, const btTransform& xf2)
const btBox2dShape* poly2, const btTransform& xf2)
{
const btVector3* vertices1 = poly1->getVertices();
const btVector3* normals1 = poly1->getNormals();
@@ -145,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]);
@@ -156,8 +162,8 @@ static btScalar EdgeSeparation(const btBox2dShape* poly1, const btTransform& xf1
// Find the max separation between poly1 and poly2 using edge normals from poly1.
static btScalar FindMaxSeparation(int* edgeIndex,
const btBox2dShape* poly1, const btTransform& xf1,
const btBox2dShape* poly2, const btTransform& xf2)
const btBox2dShape* poly1, const btTransform& xf1,
const btBox2dShape* poly2, const btTransform& xf2)
{
int count1 = poly1->getVertexCount();
const btVector3* normals1 = poly1->getNormals();
@@ -169,8 +175,8 @@ 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);
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);
@@ -218,7 +224,7 @@ static btScalar FindMaxSeparation(int* edgeIndex,
}
// Perform a local search for the best edge normal.
for (;;)
for ( ; ; )
{
if (increment == -1)
edge = bestEdge - 1 >= 0 ? bestEdge - 1 : count1 - 1;
@@ -279,14 +285,14 @@ static void FindIncidentEdge(ClipVertex c[2],
int i2 = i1 + 1 < count2 ? i1 + 1 : 0;
c[0].v = b2Mul(xf2, vertices2[i1]);
// c[0].id.features.referenceEdge = (unsigned char)edge1;
// c[0].id.features.incidentEdge = (unsigned char)i1;
// c[0].id.features.incidentVertex = 0;
// c[0].id.features.referenceEdge = (unsigned char)edge1;
// c[0].id.features.incidentEdge = (unsigned char)i1;
// c[0].id.features.incidentVertex = 0;
c[1].v = b2Mul(xf2, vertices2[i2]);
// c[1].id.features.referenceEdge = (unsigned char)edge1;
// c[1].id.features.incidentEdge = (unsigned char)i2;
// c[1].id.features.incidentVertex = 1;
// c[1].id.features.referenceEdge = (unsigned char)edge1;
// c[1].id.features.incidentEdge = (unsigned char)i2;
// c[1].id.features.incidentVertex = 1;
}
// Find edge normal of max separation on A - return if separating axis is found
@@ -297,9 +303,10 @@ static void FindIncidentEdge(ClipVertex c[2],
// The normal points from 1 to 2
void b2CollidePolygons(btManifoldResult* manifold,
const btBox2dShape* polyA, const btTransform& xfA,
const btBox2dShape* polyB, const btTransform& xfB)
const btBox2dShape* polyA, const btTransform& xfA,
const btBox2dShape* polyB, const btTransform& xfB)
{
int edgeA = 0;
btScalar separationA = FindMaxSeparation(&edgeA, polyA, xfA, polyB, xfB);
if (separationA > 0.0f)
@@ -310,10 +317,10 @@ void b2CollidePolygons(btManifoldResult* manifold,
if (separationB > 0.0f)
return;
const btBox2dShape* poly1; // reference poly
const btBox2dShape* poly2; // incident poly
const btBox2dShape* poly1; // reference poly
const btBox2dShape* poly2; // incident poly
btTransform xf1, xf2;
int edge1; // reference edge
int edge1; // reference edge
unsigned char flip;
const btScalar k_relativeTol = 0.98f;
const btScalar k_absoluteTol = 0.001f;
@@ -345,13 +352,14 @@ void b2CollidePolygons(btManifoldResult* manifold,
const btVector3* vertices1 = poly1->getVertices();
btVector3 v11 = vertices1[edge1];
btVector3 v12 = edge1 + 1 < count1 ? vertices1[edge1 + 1] : vertices1[0];
btVector3 v12 = edge1 + 1 < count1 ? vertices1[edge1+1] : vertices1[0];
//btVector3 dv = v12 - v11;
btVector3 sideNormal = b2Mul(xf1.getBasis(), v12 - v11);
sideNormal.normalize();
btVector3 frontNormal = btCrossS(sideNormal, 1.0f);
v11 = b2Mul(xf1, v11);
v12 = b2Mul(xf1, v12);
@@ -361,12 +369,13 @@ void b2CollidePolygons(btManifoldResult* manifold,
// Clip incident edge against extruded edge1 side edges.
ClipVertex clipPoints1[2];
clipPoints1[0].v.setValue(0, 0, 0);
clipPoints1[1].v.setValue(0, 0, 0);
clipPoints1[0].v.setValue(0,0,0);
clipPoints1[1].v.setValue(0,0,0);
ClipVertex clipPoints2[2];
clipPoints2[0].v.setValue(0, 0, 0);
clipPoints2[1].v.setValue(0, 0, 0);
clipPoints2[0].v.setValue(0,0,0);
clipPoints2[1].v.setValue(0,0,0);
int np;
@@ -377,7 +386,7 @@ void b2CollidePolygons(btManifoldResult* manifold,
return;
// Clip to negative box side 1
np = ClipSegmentToLine(clipPoints2, clipPoints1, sideNormal, sideOffset2);
np = ClipSegmentToLine(clipPoints2, clipPoints1, sideNormal, sideOffset2);
if (np < 2)
{
@@ -394,18 +403,19 @@ void b2CollidePolygons(btManifoldResult* manifold,
if (separation <= 0.0f)
{
//b2ManifoldPoint* cp = manifold->points + pointCount;
//btScalar separation = separation;
//cp->localPoint1 = b2MulT(xfA, clipPoints2[i].v);
//cp->localPoint2 = b2MulT(xfB, clipPoints2[i].v);
manifold->addContactPoint(-manifoldNormal, clipPoints2[i].v, separation);
manifold->addContactPoint(-manifoldNormal,clipPoints2[i].v,separation);
// cp->id = clipPoints2[i].id;
// cp->id.features.flip = flip;
// cp->id = clipPoints2[i].id;
// cp->id.features.flip = flip;
++pointCount;
}
}
// manifold->pointCount = pointCount;}
// manifold->pointCount = pointCount;}
}

View File

@@ -26,22 +26,22 @@ class btPersistentManifold;
///box-box collision detection
class btBox2dBox2dCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
public:
btBox2dBox2dCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
virtual ~btBox2dBox2dCollisionAlgorithm();
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
@@ -49,15 +49,18 @@ public:
}
}
struct CreateFunc : public btCollisionAlgorithmCreateFunc
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
int bbsize = sizeof(btBox2dBox2dCollisionAlgorithm);
void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
return new (ptr) btBox2dBox2dCollisionAlgorithm(0, ci, body0Wrap, body1Wrap);
return new(ptr) btBox2dBox2dCollisionAlgorithm(0,ci,body0Wrap,body1Wrap);
}
};
};
#endif //BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H
#endif //BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H

View File

@@ -21,14 +21,14 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
#define USE_PERSISTENT_CONTACTS 1
btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
: btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf)
btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf)
{
if (!m_manifoldPtr && m_dispatcher->needsCollision(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject()))
if (!m_manifoldPtr && m_dispatcher->needsCollision(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject()))
{
m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
m_ownManifold = true;
}
}
@@ -42,27 +42,30 @@ btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm()
}
}
void btBoxBoxCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btBoxBoxCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
return;
const btBoxShape* box0 = (btBoxShape*)body0Wrap->getCollisionShape();
const btBoxShape* box1 = (btBoxShape*)body1Wrap->getCollisionShape();
/// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->setPersistentManifold(m_manifoldPtr);
#ifndef USE_PERSISTENT_CONTACTS
#ifndef USE_PERSISTENT_CONTACTS
m_manifoldPtr->clearManifold();
#endif //USE_PERSISTENT_CONTACTS
#endif //USE_PERSISTENT_CONTACTS
btDiscreteCollisionDetectorInterface::ClosestPointInput input;
input.m_maximumDistanceSquared = BT_LARGE_FLOAT;
input.m_transformA = body0Wrap->getWorldTransform();
input.m_transformB = body1Wrap->getWorldTransform();
btBoxBoxDetector detector(box0, box1);
detector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw);
btBoxBoxDetector detector(box0,box1);
detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
#ifdef USE_PERSISTENT_CONTACTS
// refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
@@ -70,10 +73,11 @@ void btBoxBoxCollisionAlgorithm::processCollision(const btCollisionObjectWrapper
{
resultOut->refreshContactPoints();
}
#endif //USE_PERSISTENT_CONTACTS
#endif //USE_PERSISTENT_CONTACTS
}
btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/, btCollisionObject* /*body1*/, const btDispatcherInfo& /*dispatchInfo*/, btManifoldResult* /*resultOut*/)
btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
{
//not yet
return 1.f;

View File

@@ -26,22 +26,22 @@ class btPersistentManifold;
///box-box collision detection
class btBoxBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
public:
btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
btBoxBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
virtual ~btBoxBoxCollisionAlgorithm();
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
@@ -49,15 +49,18 @@ public:
}
}
struct CreateFunc : public btCollisionAlgorithmCreateFunc
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
int bbsize = sizeof(btBoxBoxCollisionAlgorithm);
void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
return new (ptr) btBoxBoxCollisionAlgorithm(0, ci, body0Wrap, body1Wrap);
return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0Wrap,body1Wrap);
}
};
};
#endif //BT_BOX_BOX__COLLISION_ALGORITHM_H
#endif //BT_BOX_BOX__COLLISION_ALGORITHM_H

File diff suppressed because it is too large Load Diff

View File

@@ -19,9 +19,11 @@ subject to the following restrictions:
#ifndef BT_BOX_BOX_DETECTOR_H
#define BT_BOX_BOX_DETECTOR_H
class btBoxShape;
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
/// btBoxBoxDetector wraps the ODE box-box collision detector
/// re-distributed under the Zlib license with permission from Russell L. Smith
struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface
@@ -30,11 +32,13 @@ struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface
const btBoxShape* m_box2;
public:
btBoxBoxDetector(const btBoxShape* box1, const btBoxShape* box2);
virtual ~btBoxBoxDetector(){};
btBoxBoxDetector(const btBoxShape* box1,const btBoxShape* box2);
virtual ~btBoxBoxDetector() {};
virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
virtual void getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults = false);
};
#endif //BT_BOX_BOX_DETECTOR_H
#endif //BT_BOX_BOX_DETECTOR_H

View File

@@ -23,9 +23,11 @@ class btPoolAllocator;
///btCollisionConfiguration allows to configure Bullet collision detection
///stack allocator size, default collision algorithms and persistent manifold pool size
///@todo: describe the meaning
class btCollisionConfiguration
class btCollisionConfiguration
{
public:
virtual ~btCollisionConfiguration()
{
}
@@ -35,9 +37,10 @@ public:
virtual btPoolAllocator* getCollisionAlgorithmPool() = 0;
virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1) = 0;
virtual btCollisionAlgorithmCreateFunc* getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1) = 0;
virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0;
};
#endif //BT_COLLISION_CONFIGURATION
#endif //BT_COLLISION_CONFIGURATION

View File

@@ -26,18 +26,20 @@ struct btCollisionAlgorithmConstructionInfo;
struct btCollisionAlgorithmCreateFunc
{
bool m_swapped;
btCollisionAlgorithmCreateFunc()
: m_swapped(false)
:m_swapped(false)
{
}
virtual ~btCollisionAlgorithmCreateFunc(){};
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo&, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& , const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
(void)body0Wrap;
(void)body1Wrap;
return 0;
}
};
#endif //BT_COLLISION_CREATE_FUNC
#endif //BT_COLLISION_CREATE_FUNC

View File

@@ -13,8 +13,10 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "btCollisionDispatcher.h"
#include "LinearMath/btQuickprof.h"
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
@@ -25,73 +27,82 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
int gNumManifold = 0;
#ifdef BT_DEBUG
#include <stdio.h>
#endif
btCollisionDispatcher::btCollisionDispatcher(btCollisionConfiguration* collisionConfiguration) : m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD),
m_collisionConfiguration(collisionConfiguration)
btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration):
m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD),
m_collisionConfiguration(collisionConfiguration)
{
int i;
setNearCallback(defaultNearCallback);
m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool();
m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool();
for (i = 0; i < MAX_BROADPHASE_COLLISION_TYPES; i++)
for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
{
for (int j = 0; j < MAX_BROADPHASE_COLLISION_TYPES; j++)
for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
{
m_doubleDispatchContactPoints[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i, j);
btAssert(m_doubleDispatchContactPoints[i][j]);
m_doubleDispatchClosestPoints[i][j] = m_collisionConfiguration->getClosestPointsAlgorithmCreateFunc(i, j);
m_doubleDispatch[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i,j);
btAssert(m_doubleDispatch[i][j]);
}
}
}
void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc)
{
m_doubleDispatchContactPoints[proxyType0][proxyType1] = createFunc;
}
void btCollisionDispatcher::registerClosestPointsCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc)
void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
{
m_doubleDispatchClosestPoints[proxyType0][proxyType1] = createFunc;
m_doubleDispatch[proxyType0][proxyType1] = createFunc;
}
btCollisionDispatcher::~btCollisionDispatcher()
{
}
btPersistentManifold* btCollisionDispatcher::getNewManifold(const btCollisionObject* body0, const btCollisionObject* body1)
{
btPersistentManifold* btCollisionDispatcher::getNewManifold(const btCollisionObject* body0,const btCollisionObject* body1)
{
gNumManifold++;
//btAssert(gNumManifold < 65535);
//optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
btScalar contactBreakingThreshold = (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ?
btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold) , body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
: gContactBreakingThreshold ;
btScalar contactBreakingThreshold = (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ? btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold), body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
: gContactBreakingThreshold;
btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(), body1->getContactProcessingThreshold());
void* mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
if (NULL == mem)
btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(),body1->getContactProcessingThreshold());
void* mem = 0;
if (m_persistentManifoldPoolAllocator->getFreeCount())
{
mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
} else
{
//we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
if ((m_dispatcherFlags & CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION) == 0)
if ((m_dispatcherFlags&CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION)==0)
{
mem = btAlignedAlloc(sizeof(btPersistentManifold), 16);
}
else
mem = btAlignedAlloc(sizeof(btPersistentManifold),16);
} else
{
btAssert(0);
//make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
return 0;
}
}
btPersistentManifold* manifold = new (mem) btPersistentManifold(body0, body1, 0, contactBreakingThreshold, contactProcessingThreshold);
btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0,contactBreakingThreshold,contactProcessingThreshold);
manifold->m_index1a = m_manifoldsPtr.size();
m_manifoldsPtr.push_back(manifold);
@@ -103,14 +114,18 @@ void btCollisionDispatcher::clearManifold(btPersistentManifold* manifold)
manifold->clearManifold();
}
void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
{
gNumManifold--;
//printf("releaseManifold: gNumManifold %d\n",gNumManifold);
clearManifold(manifold);
int findIndex = manifold->m_index1a;
btAssert(findIndex < m_manifoldsPtr.size());
m_manifoldsPtr.swap(findIndex, m_manifoldsPtr.size() - 1);
m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1);
m_manifoldsPtr[findIndex]->m_index1a = findIndex;
m_manifoldsPtr.pop_back();
@@ -118,44 +133,42 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
if (m_persistentManifoldPoolAllocator->validPtr(manifold))
{
m_persistentManifoldPoolAllocator->freeMemory(manifold);
}
else
} else
{
btAlignedFree(manifold);
}
}
btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btPersistentManifold* sharedManifold, ebtDispatcherQueryType algoType)
btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold)
{
btCollisionAlgorithmConstructionInfo ci;
ci.m_dispatcher1 = this;
ci.m_manifold = sharedManifold;
btCollisionAlgorithm* algo = 0;
if (algoType == BT_CONTACT_POINT_ALGORITHMS)
{
algo = m_doubleDispatchContactPoints[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci, body0Wrap, body1Wrap);
}
else
{
algo = m_doubleDispatchClosestPoints[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci, body0Wrap, body1Wrap);
}
btCollisionAlgorithm* algo = m_doubleDispatch[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0Wrap,body1Wrap);
return algo;
}
bool btCollisionDispatcher::needsResponse(const btCollisionObject* body0, const btCollisionObject* body1)
bool btCollisionDispatcher::needsResponse(const btCollisionObject* body0,const btCollisionObject* body1)
{
//here you can do filtering
bool hasResponse =
bool hasResponse =
(body0->hasContactResponse() && body1->hasContactResponse());
//no response between two static/kinematic bodies:
hasResponse = hasResponse &&
((!body0->isStaticOrKinematicObject()) || (!body1->isStaticOrKinematicObject()));
((!body0->isStaticOrKinematicObject()) ||(! body1->isStaticOrKinematicObject()));
return hasResponse;
}
bool btCollisionDispatcher::needsCollision(const btCollisionObject* body0, const btCollisionObject* body1)
bool btCollisionDispatcher::needsCollision(const btCollisionObject* body0,const btCollisionObject* body1)
{
btAssert(body0);
btAssert(body1);
@@ -172,27 +185,31 @@ bool btCollisionDispatcher::needsCollision(const btCollisionObject* body0, const
printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
}
}
#endif //BT_DEBUG
#endif //BT_DEBUG
if ((!body0->isActive()) && (!body1->isActive()))
needsCollision = false;
else if ((!body0->checkCollideWith(body1)) || (!body1->checkCollideWith(body0)))
needsCollision = false;
return needsCollision ;
return needsCollision;
}
///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc)
///this is useful for the collision dispatcher.
class btCollisionPairCallback : public btOverlapCallback
{
const btDispatcherInfo& m_dispatchInfo;
btCollisionDispatcher* m_dispatcher;
btCollisionDispatcher* m_dispatcher;
public:
btCollisionPairCallback(const btDispatcherInfo& dispatchInfo, btCollisionDispatcher* dispatcher)
: m_dispatchInfo(dispatchInfo),
m_dispatcher(dispatcher)
btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher)
:m_dispatchInfo(dispatchInfo),
m_dispatcher(dispatcher)
{
}
@@ -204,76 +221,85 @@ public:
}
*/
virtual ~btCollisionPairCallback() {}
virtual bool processOverlap(btBroadphasePair& pair)
virtual bool processOverlap(btBroadphasePair& pair)
{
(*m_dispatcher->getNearCallback())(pair, *m_dispatcher, m_dispatchInfo);
(*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo);
return false;
}
};
void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher)
void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)
{
//m_blockedForChanges = true;
btCollisionPairCallback collisionCallback(dispatchInfo, this);
btCollisionPairCallback collisionCallback(dispatchInfo,this);
{
BT_PROFILE("processAllOverlappingPairs");
pairCache->processAllOverlappingPairs(&collisionCallback, dispatcher, dispatchInfo);
}
pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
//m_blockedForChanges = false;
}
//by default, Bullet will use this near callback
void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
{
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
if (dispatcher.needsCollision(colObj0, colObj1))
{
btCollisionObjectWrapper obj0Wrap(0, colObj0->getCollisionShape(), colObj0, colObj0->getWorldTransform(), -1, -1);
btCollisionObjectWrapper obj1Wrap(0, colObj1->getCollisionShape(), colObj1, colObj1->getWorldTransform(), -1, -1);
//dispatcher will keep algorithms persistent in the collision pair
if (!collisionPair.m_algorithm)
if (dispatcher.needsCollision(colObj0,colObj1))
{
collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap, &obj1Wrap, 0, BT_CONTACT_POINT_ALGORITHMS);
}
btCollisionObjectWrapper obj0Wrap(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1);
btCollisionObjectWrapper obj1Wrap(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1);
if (collisionPair.m_algorithm)
{
btManifoldResult contactPointResult(&obj0Wrap, &obj1Wrap);
if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
//dispatcher will keep algorithms persistent in the collision pair
if (!collisionPair.m_algorithm)
{
//discrete collision detection query
collisionPair.m_algorithm->processCollision(&obj0Wrap, &obj1Wrap, dispatchInfo, &contactPointResult);
collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap,&obj1Wrap);
}
else
if (collisionPair.m_algorithm)
{
//continuous collision detection query, time of impact (toi)
btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0, colObj1, dispatchInfo, &contactPointResult);
if (dispatchInfo.m_timeOfImpact > toi)
dispatchInfo.m_timeOfImpact = toi;
btManifoldResult contactPointResult(&obj0Wrap,&obj1Wrap);
if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
{
//discrete collision detection query
collisionPair.m_algorithm->processCollision(&obj0Wrap,&obj1Wrap,dispatchInfo,&contactPointResult);
} else
{
//continuous collision detection query, time of impact (toi)
btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
if (dispatchInfo.m_timeOfImpact > toi)
dispatchInfo.m_timeOfImpact = toi;
}
}
}
}
}
void* btCollisionDispatcher::allocateCollisionAlgorithm(int size)
{
void* mem = m_collisionAlgorithmPoolAllocator->allocate(size);
if (NULL == mem)
if (m_collisionAlgorithmPoolAllocator->getFreeCount())
{
//warn user for overflow?
return btAlignedAlloc(static_cast<size_t>(size), 16);
return m_collisionAlgorithmPoolAllocator->allocate(size);
}
return mem;
//warn user for overflow?
return btAlignedAlloc(static_cast<size_t>(size), 16);
}
void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
@@ -281,8 +307,7 @@ void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
{
m_collisionAlgorithmPoolAllocator->freeMemory(ptr);
}
else
} else
{
btAlignedFree(ptr);
}

View File

@@ -37,28 +37,33 @@ class btCollisionDispatcher;
///user can override this nearcallback for collision filtering and more finegrained control over collision detection
typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs.
///Time of Impact, Closest Points and Penetration Depth.
class btCollisionDispatcher : public btDispatcher
{
protected:
int m_dispatcherFlags;
btAlignedObjectArray<btPersistentManifold*> m_manifoldsPtr;
int m_dispatcherFlags;
btNearCallback m_nearCallback;
btAlignedObjectArray<btPersistentManifold*> m_manifoldsPtr;
btPoolAllocator* m_collisionAlgorithmPoolAllocator;
btManifoldResult m_defaultManifoldResult;
btPoolAllocator* m_persistentManifoldPoolAllocator;
btNearCallback m_nearCallback;
btPoolAllocator* m_collisionAlgorithmPoolAllocator;
btCollisionAlgorithmCreateFunc* m_doubleDispatchContactPoints[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
btPoolAllocator* m_persistentManifoldPoolAllocator;
btCollisionAlgorithmCreateFunc* m_doubleDispatchClosestPoints[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
btCollisionConfiguration* m_collisionConfiguration;
btCollisionConfiguration* m_collisionConfiguration;
public:
enum DispatcherFlags
{
CD_STATIC_STATIC_REPORTED = 1,
@@ -66,104 +71,101 @@ public:
CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION = 4
};
int getDispatcherFlags() const
int getDispatcherFlags() const
{
return m_dispatcherFlags;
}
void setDispatcherFlags(int flags)
void setDispatcherFlags(int flags)
{
m_dispatcherFlags = flags;
}
///registerCollisionCreateFunc allows registration of custom/alternative collision create functions
void registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc);
void registerCollisionCreateFunc(int proxyType0,int proxyType1, btCollisionAlgorithmCreateFunc* createFunc);
void registerClosestPointsCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc);
int getNumManifolds() const
{
return int(m_manifoldsPtr.size());
int getNumManifolds() const
{
return int( m_manifoldsPtr.size());
}
btPersistentManifold** getInternalManifoldPointer()
btPersistentManifold** getInternalManifoldPointer()
{
return m_manifoldsPtr.size() ? &m_manifoldsPtr[0] : 0;
return m_manifoldsPtr.size()? &m_manifoldsPtr[0] : 0;
}
btPersistentManifold* getManifoldByIndexInternal(int index)
btPersistentManifold* getManifoldByIndexInternal(int index)
{
btAssert(index>=0);
btAssert(index<m_manifoldsPtr.size());
return m_manifoldsPtr[index];
}
const btPersistentManifold* getManifoldByIndexInternal(int index) const
const btPersistentManifold* getManifoldByIndexInternal(int index) const
{
btAssert(index>=0);
btAssert(index<m_manifoldsPtr.size());
return m_manifoldsPtr[index];
}
btCollisionDispatcher(btCollisionConfiguration* collisionConfiguration);
btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration);
virtual ~btCollisionDispatcher();
virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0, const btCollisionObject* b1);
virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0,const btCollisionObject* b1);
virtual void releaseManifold(btPersistentManifold* manifold);
virtual void clearManifold(btPersistentManifold* manifold);
btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btPersistentManifold* sharedManifold, ebtDispatcherQueryType queryType);
btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold = 0);
virtual bool needsCollision(const btCollisionObject* body0,const btCollisionObject* body1);
virtual bool needsResponse(const btCollisionObject* body0,const btCollisionObject* body1);
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ;
virtual bool needsCollision(const btCollisionObject* body0, const btCollisionObject* body1);
virtual bool needsResponse(const btCollisionObject* body0, const btCollisionObject* body1);
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher);
void setNearCallback(btNearCallback nearCallback)
void setNearCallback(btNearCallback nearCallback)
{
m_nearCallback = nearCallback;
m_nearCallback = nearCallback;
}
btNearCallback getNearCallback() const
btNearCallback getNearCallback() const
{
return m_nearCallback;
}
//by default, Bullet will use this near callback
static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
virtual void* allocateCollisionAlgorithm(int size);
virtual void* allocateCollisionAlgorithm(int size);
virtual void freeCollisionAlgorithm(void* ptr);
virtual void freeCollisionAlgorithm(void* ptr);
btCollisionConfiguration* getCollisionConfiguration()
btCollisionConfiguration* getCollisionConfiguration()
{
return m_collisionConfiguration;
}
const btCollisionConfiguration* getCollisionConfiguration() const
const btCollisionConfiguration* getCollisionConfiguration() const
{
return m_collisionConfiguration;
}
void setCollisionConfiguration(btCollisionConfiguration* config)
void setCollisionConfiguration(btCollisionConfiguration* config)
{
m_collisionConfiguration = config;
}
virtual btPoolAllocator* getInternalManifoldPool()
virtual btPoolAllocator* getInternalManifoldPool()
{
return m_persistentManifoldPoolAllocator;
}
virtual const btPoolAllocator* getInternalManifoldPool() const
virtual const btPoolAllocator* getInternalManifoldPool() const
{
return m_persistentManifoldPoolAllocator;
}
};
#endif //BT_COLLISION__DISPATCHER_H
#endif //BT_COLLISION__DISPATCHER_H

View File

@@ -1,162 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btCollisionDispatcherMt.h"
#include "LinearMath/btQuickprof.h"
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
#include "LinearMath/btPoolAllocator.h"
#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
btCollisionDispatcherMt::btCollisionDispatcherMt(btCollisionConfiguration* config, int grainSize)
: btCollisionDispatcher(config)
{
m_batchManifoldsPtr.resize(btGetTaskScheduler()->getNumThreads());
m_batchUpdating = false;
m_grainSize = grainSize; // iterations per task
}
btPersistentManifold* btCollisionDispatcherMt::getNewManifold(const btCollisionObject* body0, const btCollisionObject* body1)
{
//optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
btScalar contactBreakingThreshold = (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ? btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold), body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
: gContactBreakingThreshold;
btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(), body1->getContactProcessingThreshold());
void* mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
if (NULL == mem)
{
//we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
if ((m_dispatcherFlags & CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION) == 0)
{
mem = btAlignedAlloc(sizeof(btPersistentManifold), 16);
}
else
{
btAssert(0);
//make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
return 0;
}
}
btPersistentManifold* manifold = new (mem) btPersistentManifold(body0, body1, 0, contactBreakingThreshold, contactProcessingThreshold);
if (!m_batchUpdating)
{
// batch updater will update manifold pointers array after finishing, so
// only need to update array when not batch-updating
//btAssert( !btThreadsAreRunning() );
manifold->m_index1a = m_manifoldsPtr.size();
m_manifoldsPtr.push_back(manifold);
}
else
{
m_batchManifoldsPtr[btGetCurrentThreadIndex()].push_back(manifold);
}
return manifold;
}
void btCollisionDispatcherMt::releaseManifold(btPersistentManifold* manifold)
{
clearManifold(manifold);
//btAssert( !btThreadsAreRunning() );
if (!m_batchUpdating)
{
// batch updater will update manifold pointers array after finishing, so
// only need to update array when not batch-updating
int findIndex = manifold->m_index1a;
btAssert(findIndex < m_manifoldsPtr.size());
m_manifoldsPtr.swap(findIndex, m_manifoldsPtr.size() - 1);
m_manifoldsPtr[findIndex]->m_index1a = findIndex;
m_manifoldsPtr.pop_back();
}
manifold->~btPersistentManifold();
if (m_persistentManifoldPoolAllocator->validPtr(manifold))
{
m_persistentManifoldPoolAllocator->freeMemory(manifold);
}
else
{
btAlignedFree(manifold);
}
}
struct CollisionDispatcherUpdater : public btIParallelForBody
{
btBroadphasePair* mPairArray;
btNearCallback mCallback;
btCollisionDispatcher* mDispatcher;
const btDispatcherInfo* mInfo;
CollisionDispatcherUpdater()
{
mPairArray = NULL;
mCallback = NULL;
mDispatcher = NULL;
mInfo = NULL;
}
void forLoop(int iBegin, int iEnd) const
{
for (int i = iBegin; i < iEnd; ++i)
{
btBroadphasePair* pair = &mPairArray[i];
mCallback(*pair, *mDispatcher, *mInfo);
}
}
};
void btCollisionDispatcherMt::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher)
{
const int pairCount = pairCache->getNumOverlappingPairs();
if (pairCount == 0)
{
return;
}
CollisionDispatcherUpdater updater;
updater.mCallback = getNearCallback();
updater.mPairArray = pairCache->getOverlappingPairArrayPtr();
updater.mDispatcher = this;
updater.mInfo = &info;
m_batchUpdating = true;
btParallelFor(0, pairCount, m_grainSize, updater);
m_batchUpdating = false;
// merge new manifolds, if any
for (int i = 0; i < m_batchManifoldsPtr.size(); ++i)
{
btAlignedObjectArray<btPersistentManifold*>& batchManifoldsPtr = m_batchManifoldsPtr[i];
for (int j = 0; j < batchManifoldsPtr.size(); ++j)
{
m_manifoldsPtr.push_back(batchManifoldsPtr[j]);
}
batchManifoldsPtr.resizeNoInitialize(0);
}
// update the indices (used when releasing manifolds)
for (int i = 0; i < m_manifoldsPtr.size(); ++i)
{
m_manifoldsPtr[i]->m_index1a = i;
}
}

View File

@@ -1,38 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_COLLISION_DISPATCHER_MT_H
#define BT_COLLISION_DISPATCHER_MT_H
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "LinearMath/btThreads.h"
class btCollisionDispatcherMt : public btCollisionDispatcher
{
public:
btCollisionDispatcherMt(btCollisionConfiguration* config, int grainSize = 40);
virtual btPersistentManifold* getNewManifold(const btCollisionObject* body0, const btCollisionObject* body1) BT_OVERRIDE;
virtual void releaseManifold(btPersistentManifold* manifold) BT_OVERRIDE;
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher) BT_OVERRIDE;
protected:
btAlignedObjectArray<btAlignedObjectArray<btPersistentManifold*> > m_batchManifoldsPtr;
bool m_batchUpdating;
int m_grainSize;
};
#endif //BT_COLLISION_DISPATCHER_MT_H

View File

@@ -13,45 +13,36 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "btCollisionObject.h"
#include "LinearMath/btSerializer.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
btCollisionObject::btCollisionObject()
: m_interpolationLinearVelocity(0.f, 0.f, 0.f),
m_interpolationAngularVelocity(0.f, 0.f, 0.f),
m_anisotropicFriction(1.f, 1.f, 1.f),
m_hasAnisotropicFriction(false),
m_contactProcessingThreshold(BT_LARGE_FLOAT),
m_broadphaseHandle(0),
m_collisionShape(0),
m_extensionPointer(0),
m_rootCollisionShape(0),
m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT),
m_islandTag1(-1),
m_companionId(-1),
m_worldArrayIndex(-1),
m_activationState1(1),
m_deactivationTime(btScalar(0.)),
m_friction(btScalar(0.5)),
m_restitution(btScalar(0.)),
m_rollingFriction(0.0f),
m_spinningFriction(0.f),
m_contactDamping(.1),
m_contactStiffness(BT_LARGE_FLOAT),
m_internalType(CO_COLLISION_OBJECT),
m_userObjectPointer(0),
m_userIndex2(-1),
m_userIndex(-1),
m_userIndex3(-1),
m_hitFraction(btScalar(1.)),
m_ccdSweptSphereRadius(btScalar(0.)),
m_ccdMotionThreshold(btScalar(0.)),
m_checkCollideWith(false),
m_updateRevision(0)
: m_anisotropicFriction(1.f,1.f,1.f),
m_hasAnisotropicFriction(false),
m_contactProcessingThreshold(BT_LARGE_FLOAT),
m_broadphaseHandle(0),
m_collisionShape(0),
m_extensionPointer(0),
m_rootCollisionShape(0),
m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT),
m_islandTag1(-1),
m_companionId(-1),
m_activationState1(1),
m_deactivationTime(btScalar(0.)),
m_friction(btScalar(0.5)),
m_restitution(btScalar(0.)),
m_rollingFriction(0.0f),
m_internalType(CO_COLLISION_OBJECT),
m_userObjectPointer(0),
m_userIndex(-1),
m_hitFraction(btScalar(1.)),
m_ccdSweptSphereRadius(btScalar(0.)),
m_ccdMotionThreshold(btScalar(0.)),
m_checkCollideWith(false),
m_updateRevision(0)
{
m_worldTransform.setIdentity();
m_interpolationWorldTransform.setIdentity();
}
btCollisionObject::~btCollisionObject()
@@ -59,8 +50,8 @@ btCollisionObject::~btCollisionObject()
}
void btCollisionObject::setActivationState(int newState) const
{
if ((m_activationState1 != DISABLE_DEACTIVATION) && (m_activationState1 != DISABLE_SIMULATION))
{
if ( (m_activationState1 != DISABLE_DEACTIVATION) && (m_activationState1 != DISABLE_SIMULATION))
m_activationState1 = newState;
}
@@ -71,7 +62,7 @@ void btCollisionObject::forceActivationState(int newState) const
void btCollisionObject::activate(bool forceActivation) const
{
if (forceActivation || !(m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT)))
if (forceActivation || !(m_collisionFlags & (CF_STATIC_OBJECT|CF_KINEMATIC_OBJECT)))
{
setActivationState(ACTIVE_TAG);
m_deactivationTime = btScalar(0.);
@@ -80,6 +71,7 @@ void btCollisionObject::activate(bool forceActivation) const
const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* serializer) const
{
btCollisionObjectData* dataOut = (btCollisionObjectData*)dataBuffer;
m_worldTransform.serialize(dataOut->m_worldTransform);
@@ -91,7 +83,7 @@ const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* seriali
dataOut->m_contactProcessingThreshold = m_contactProcessingThreshold;
dataOut->m_broadphaseHandle = 0;
dataOut->m_collisionShape = serializer->getUniquePointer(m_collisionShape);
dataOut->m_rootCollisionShape = 0; //@todo
dataOut->m_rootCollisionShape = 0;//@todo
dataOut->m_collisionFlags = m_collisionFlags;
dataOut->m_islandTag1 = m_islandTag1;
dataOut->m_companionId = m_companionId;
@@ -99,12 +91,10 @@ const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* seriali
dataOut->m_deactivationTime = m_deactivationTime;
dataOut->m_friction = m_friction;
dataOut->m_rollingFriction = m_rollingFriction;
dataOut->m_contactDamping = m_contactDamping;
dataOut->m_contactStiffness = m_contactStiffness;
dataOut->m_restitution = m_restitution;
dataOut->m_internalType = m_internalType;
char* name = (char*)serializer->findNameForPointer(this);
char* name = (char*) serializer->findNameForPointer(this);
dataOut->m_name = (char*)serializer->getUniquePointer(name);
if (dataOut->m_name)
{
@@ -114,25 +104,15 @@ const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* seriali
dataOut->m_ccdSweptSphereRadius = m_ccdSweptSphereRadius;
dataOut->m_ccdMotionThreshold = m_ccdMotionThreshold;
dataOut->m_checkCollideWith = m_checkCollideWith;
if (m_broadphaseHandle)
{
dataOut->m_collisionFilterGroup = m_broadphaseHandle->m_collisionFilterGroup;
dataOut->m_collisionFilterMask = m_broadphaseHandle->m_collisionFilterMask;
dataOut->m_uniqueId = m_broadphaseHandle->m_uniqueId;
}
else
{
dataOut->m_collisionFilterGroup = 0;
dataOut->m_collisionFilterMask = 0;
dataOut->m_uniqueId = -1;
}
return btCollisionObjectDataName;
}
void btCollisionObject::serializeSingleObject(class btSerializer* serializer) const
{
int len = calculateSerializeBufferSize();
btChunk* chunk = serializer->allocate(len, 1);
btChunk* chunk = serializer->allocate(len,1);
const char* structType = serialize(chunk->m_oldPtr, serializer);
serializer->finalizeChunk(chunk, structType, BT_COLLISIONOBJECT_CODE, (void*)this);
serializer->finalizeChunk(chunk,structType,BT_COLLISIONOBJECT_CODE,(void*)this);
}

View File

@@ -25,8 +25,8 @@ subject to the following restrictions:
#define DISABLE_DEACTIVATION 4
#define DISABLE_SIMULATION 5
struct btBroadphaseProxy;
class btCollisionShape;
struct btBroadphaseProxy;
class btCollisionShape;
struct btCollisionShapeData;
#include "LinearMath/btMotionState.h"
#include "LinearMath/btAlignedAllocator.h"
@@ -42,120 +42,110 @@ typedef btAlignedObjectArray<class btCollisionObject*> btCollisionObjectArray;
#define btCollisionObjectDataName "btCollisionObjectFloatData"
#endif
/// btCollisionObject can be used to manage collision detection objects.
/// btCollisionObject can be used to manage collision detection objects.
/// btCollisionObject maintains all information that is needed for a collision detection: Shape, Transform and AABB proxy.
/// They can be added to the btCollisionWorld.
ATTRIBUTE_ALIGNED16(class)
btCollisionObject
ATTRIBUTE_ALIGNED16(class) btCollisionObject
{
protected:
btTransform m_worldTransform;
btTransform m_worldTransform;
///m_interpolationWorldTransform is used for CCD and interpolation
///it can be either previous or future (predicted) transform
btTransform m_interpolationWorldTransform;
//those two are experimental: just added for bullet time effect, so you can still apply impulses (directly modifying velocities)
btTransform m_interpolationWorldTransform;
//those two are experimental: just added for bullet time effect, so you can still apply impulses (directly modifying velocities)
//without destroying the continuous interpolated motion (which uses this interpolation velocities)
btVector3 m_interpolationLinearVelocity;
btVector3 m_interpolationAngularVelocity;
btVector3 m_interpolationLinearVelocity;
btVector3 m_interpolationAngularVelocity;
btVector3 m_anisotropicFriction;
int m_hasAnisotropicFriction;
btScalar m_contactProcessingThreshold;
btVector3 m_anisotropicFriction;
int m_hasAnisotropicFriction;
btScalar m_contactProcessingThreshold;
btBroadphaseProxy* m_broadphaseHandle;
btCollisionShape* m_collisionShape;
btBroadphaseProxy* m_broadphaseHandle;
btCollisionShape* m_collisionShape;
///m_extensionPointer is used by some internal low-level Bullet extensions.
void* m_extensionPointer;
void* m_extensionPointer;
///m_rootCollisionShape is temporarily used to store the original collision shape
///The m_collisionShape might be temporarily replaced by a child collision shape during collision detection purposes
///If it is NULL, the m_collisionShape is not temporarily replaced.
btCollisionShape* m_rootCollisionShape;
btCollisionShape* m_rootCollisionShape;
int m_collisionFlags;
int m_collisionFlags;
int m_islandTag1;
int m_companionId;
int m_worldArrayIndex; // index of object in world's collisionObjects array
int m_islandTag1;
int m_companionId;
mutable int m_activationState1;
mutable btScalar m_deactivationTime;
mutable int m_activationState1;
mutable btScalar m_deactivationTime;
btScalar m_friction;
btScalar m_restitution;
btScalar m_rollingFriction; //torsional friction orthogonal to contact normal (useful to stop spheres rolling forever)
btScalar m_spinningFriction; // torsional friction around the contact normal (useful for grasping)
btScalar m_contactDamping;
btScalar m_contactStiffness;
btScalar m_friction;
btScalar m_restitution;
btScalar m_rollingFriction;
///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody, btGhostObject etc.
///do not assign your own m_internalType unless you write a new dynamics object class.
int m_internalType;
int m_internalType;
///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer
void* m_userObjectPointer;
int m_userIndex2;
int m_userIndex;
int m_userIndex3;
void* m_userObjectPointer;
int m_userIndex;
///time of impact calculation
btScalar m_hitFraction;
btScalar m_hitFraction;
///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
btScalar m_ccdSweptSphereRadius;
btScalar m_ccdSweptSphereRadius;
/// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
btScalar m_ccdMotionThreshold;
btScalar m_ccdMotionThreshold;
/// If some object should have elaborate collision filtering by sub-classes
int m_checkCollideWith;
int m_checkCollideWith;
btAlignedObjectArray<const btCollisionObject*> m_objectsWithoutCollisionCheck;
///internal update revision number. It will be increased when the object changes. This allows some subsystems to perform lazy evaluation.
int m_updateRevision;
int m_updateRevision;
btVector3 m_customDebugColorRGB;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
enum CollisionFlags
{
CF_STATIC_OBJECT = 1,
CF_KINEMATIC_OBJECT = 2,
CF_STATIC_OBJECT= 1,
CF_KINEMATIC_OBJECT= 2,
CF_NO_CONTACT_RESPONSE = 4,
CF_CUSTOM_MATERIAL_CALLBACK = 8, //this allows per-triangle material (friction/restitution)
CF_CUSTOM_MATERIAL_CALLBACK = 8,//this allows per-triangle material (friction/restitution)
CF_CHARACTER_OBJECT = 16,
CF_DISABLE_VISUALIZE_OBJECT = 32, //disable debug drawing
CF_DISABLE_SPU_COLLISION_PROCESSING = 64, //disable parallel/SPU processing
CF_HAS_CONTACT_STIFFNESS_DAMPING = 128,
CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR = 256,
CF_HAS_FRICTION_ANCHOR = 512,
CF_HAS_COLLISION_SOUND_TRIGGER = 1024
CF_DISABLE_VISUALIZE_OBJECT = 32, //disable debug drawing
CF_DISABLE_SPU_COLLISION_PROCESSING = 64//disable parallel/SPU processing
};
enum CollisionObjectTypes
enum CollisionObjectTypes
{
CO_COLLISION_OBJECT = 1,
CO_RIGID_BODY = 2,
CO_COLLISION_OBJECT =1,
CO_RIGID_BODY=2,
///CO_GHOST_OBJECT keeps track of all objects overlapping its AABB and that pass its collision filter
///It is useful for collision sensors, explosion objects, character controller etc.
CO_GHOST_OBJECT = 4,
CO_SOFT_BODY = 8,
CO_HF_FLUID = 16,
CO_USER_TYPE = 32,
CO_FEATHERSTONE_LINK = 64
CO_GHOST_OBJECT=4,
CO_SOFT_BODY=8,
CO_HF_FLUID=16,
CO_USER_TYPE=32,
CO_FEATHERSTONE_LINK=64
};
enum AnisotropicFrictionFlags
{
CF_ANISOTROPIC_FRICTION_DISABLED = 0,
CF_ANISOTROPIC_FRICTION_DISABLED=0,
CF_ANISOTROPIC_FRICTION = 1,
CF_ANISOTROPIC_ROLLING_FRICTION = 2
};
@@ -163,77 +153,76 @@ public:
SIMD_FORCE_INLINE bool mergesSimulationIslands() const
{
///static objects, kinematic and object without contact response don't merge islands
return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE)) == 0);
return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE) )==0);
}
const btVector3& getAnisotropicFriction() const
{
return m_anisotropicFriction;
}
void setAnisotropicFriction(const btVector3& anisotropicFriction, int frictionMode = CF_ANISOTROPIC_FRICTION)
void setAnisotropicFriction(const btVector3& anisotropicFriction, int frictionMode = CF_ANISOTROPIC_FRICTION)
{
m_anisotropicFriction = anisotropicFriction;
bool isUnity = (anisotropicFriction[0] != 1.f) || (anisotropicFriction[1] != 1.f) || (anisotropicFriction[2] != 1.f);
m_hasAnisotropicFriction = isUnity ? frictionMode : 0;
bool isUnity = (anisotropicFriction[0]!=1.f) || (anisotropicFriction[1]!=1.f) || (anisotropicFriction[2]!=1.f);
m_hasAnisotropicFriction = isUnity?frictionMode : 0;
}
bool hasAnisotropicFriction(int frictionMode = CF_ANISOTROPIC_FRICTION) const
bool hasAnisotropicFriction(int frictionMode = CF_ANISOTROPIC_FRICTION) const
{
return (m_hasAnisotropicFriction & frictionMode) != 0;
return (m_hasAnisotropicFriction&frictionMode)!=0;
}
///the constraint solver can discard solving contacts, if the distance is above this threshold. 0 by default.
///Note that using contacts with positive distance can improve stability. It increases, however, the chance of colliding with degerate contacts, such as 'interior' triangle edges
void setContactProcessingThreshold(btScalar contactProcessingThreshold)
void setContactProcessingThreshold( btScalar contactProcessingThreshold)
{
m_contactProcessingThreshold = contactProcessingThreshold;
}
btScalar getContactProcessingThreshold() const
btScalar getContactProcessingThreshold() const
{
return m_contactProcessingThreshold;
}
SIMD_FORCE_INLINE bool isStaticObject() const
{
SIMD_FORCE_INLINE bool isStaticObject() const {
return (m_collisionFlags & CF_STATIC_OBJECT) != 0;
}
SIMD_FORCE_INLINE bool isKinematicObject() const
SIMD_FORCE_INLINE bool isKinematicObject() const
{
return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0;
}
SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const
SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const
{
return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0;
return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0 ;
}
SIMD_FORCE_INLINE bool hasContactResponse() const
{
return (m_collisionFlags & CF_NO_CONTACT_RESPONSE) == 0;
SIMD_FORCE_INLINE bool hasContactResponse() const {
return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0;
}
btCollisionObject();
virtual ~btCollisionObject();
virtual void setCollisionShape(btCollisionShape * collisionShape)
virtual void setCollisionShape(btCollisionShape* collisionShape)
{
m_updateRevision++;
m_collisionShape = collisionShape;
m_rootCollisionShape = collisionShape;
}
SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const
SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const
{
return m_collisionShape;
}
SIMD_FORCE_INLINE btCollisionShape* getCollisionShape()
SIMD_FORCE_INLINE btCollisionShape* getCollisionShape()
{
return m_collisionShape;
}
void setIgnoreCollisionCheck(const btCollisionObject* co, bool ignoreCollisionCheck)
void setIgnoreCollisionCheck(const btCollisionObject* co, bool ignoreCollisionCheck)
{
if (ignoreCollisionCheck)
{
@@ -251,17 +240,7 @@ public:
m_checkCollideWith = m_objectsWithoutCollisionCheck.size() > 0;
}
int getNumObjectsWithoutCollision() const
{
return m_objectsWithoutCollisionCheck.size();
}
const btCollisionObject* getObjectWithoutCollision(int index)
{
return m_objectsWithoutCollisionCheck[index];
}
virtual bool checkCollideWithOverride(const btCollisionObject* co) const
virtual bool checkCollideWithOverride(const btCollisionObject* co) const
{
int index = m_objectsWithoutCollisionCheck.findLinearSearch(co);
if (index < m_objectsWithoutCollisionCheck.size())
@@ -271,325 +250,249 @@ public:
return true;
}
///Avoid using this internal API call, the extension pointer is used by some Bullet extensions.
///Avoid using this internal API call, the extension pointer is used by some Bullet extensions.
///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead.
void* internalGetExtensionPointer() const
void* internalGetExtensionPointer() const
{
return m_extensionPointer;
}
///Avoid using this internal API call, the extension pointer is used by some Bullet extensions
///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead.
void internalSetExtensionPointer(void* pointer)
void internalSetExtensionPointer(void* pointer)
{
m_extensionPointer = pointer;
}
SIMD_FORCE_INLINE int getActivationState() const { return m_activationState1; }
SIMD_FORCE_INLINE int getActivationState() const { return m_activationState1;}
void setActivationState(int newState) const;
void setDeactivationTime(btScalar time)
void setDeactivationTime(btScalar time)
{
m_deactivationTime = time;
}
btScalar getDeactivationTime() const
btScalar getDeactivationTime() const
{
return m_deactivationTime;
}
void forceActivationState(int newState) const;
void activate(bool forceActivation = false) const;
void activate(bool forceActivation = false) const;
SIMD_FORCE_INLINE bool isActive() const
{
return ((getActivationState() != ISLAND_SLEEPING) && (getActivationState() != DISABLE_SIMULATION));
}
void setRestitution(btScalar rest)
void setRestitution(btScalar rest)
{
m_updateRevision++;
m_restitution = rest;
}
btScalar getRestitution() const
btScalar getRestitution() const
{
return m_restitution;
}
void setFriction(btScalar frict)
void setFriction(btScalar frict)
{
m_updateRevision++;
m_friction = frict;
}
btScalar getFriction() const
btScalar getFriction() const
{
return m_friction;
}
void setRollingFriction(btScalar frict)
void setRollingFriction(btScalar frict)
{
m_updateRevision++;
m_rollingFriction = frict;
}
btScalar getRollingFriction() const
btScalar getRollingFriction() const
{
return m_rollingFriction;
}
void setSpinningFriction(btScalar frict)
{
m_updateRevision++;
m_spinningFriction = frict;
}
btScalar getSpinningFriction() const
{
return m_spinningFriction;
}
void setContactStiffnessAndDamping(btScalar stiffness, btScalar damping)
{
m_updateRevision++;
m_contactStiffness = stiffness;
m_contactDamping = damping;
m_collisionFlags |= CF_HAS_CONTACT_STIFFNESS_DAMPING;
//avoid divisions by zero...
if (m_contactStiffness < SIMD_EPSILON)
{
m_contactStiffness = SIMD_EPSILON;
}
}
btScalar getContactStiffness() const
{
return m_contactStiffness;
}
btScalar getContactDamping() const
{
return m_contactDamping;
}
///reserved for Bullet internal usage
int getInternalType() const
int getInternalType() const
{
return m_internalType;
}
btTransform& getWorldTransform()
btTransform& getWorldTransform()
{
return m_worldTransform;
}
const btTransform& getWorldTransform() const
const btTransform& getWorldTransform() const
{
return m_worldTransform;
}
void setWorldTransform(const btTransform& worldTrans)
void setWorldTransform(const btTransform& worldTrans)
{
m_updateRevision++;
m_worldTransform = worldTrans;
}
SIMD_FORCE_INLINE btBroadphaseProxy* getBroadphaseHandle()
SIMD_FORCE_INLINE btBroadphaseProxy* getBroadphaseHandle()
{
return m_broadphaseHandle;
}
SIMD_FORCE_INLINE const btBroadphaseProxy* getBroadphaseHandle() const
SIMD_FORCE_INLINE const btBroadphaseProxy* getBroadphaseHandle() const
{
return m_broadphaseHandle;
}
void setBroadphaseHandle(btBroadphaseProxy * handle)
void setBroadphaseHandle(btBroadphaseProxy* handle)
{
m_broadphaseHandle = handle;
}
const btTransform& getInterpolationWorldTransform() const
const btTransform& getInterpolationWorldTransform() const
{
return m_interpolationWorldTransform;
}
btTransform& getInterpolationWorldTransform()
btTransform& getInterpolationWorldTransform()
{
return m_interpolationWorldTransform;
}
void setInterpolationWorldTransform(const btTransform& trans)
void setInterpolationWorldTransform(const btTransform& trans)
{
m_updateRevision++;
m_interpolationWorldTransform = trans;
}
void setInterpolationLinearVelocity(const btVector3& linvel)
void setInterpolationLinearVelocity(const btVector3& linvel)
{
m_updateRevision++;
m_interpolationLinearVelocity = linvel;
}
void setInterpolationAngularVelocity(const btVector3& angvel)
void setInterpolationAngularVelocity(const btVector3& angvel)
{
m_updateRevision++;
m_interpolationAngularVelocity = angvel;
}
const btVector3& getInterpolationLinearVelocity() const
const btVector3& getInterpolationLinearVelocity() const
{
return m_interpolationLinearVelocity;
}
const btVector3& getInterpolationAngularVelocity() const
const btVector3& getInterpolationAngularVelocity() const
{
return m_interpolationAngularVelocity;
}
SIMD_FORCE_INLINE int getIslandTag() const
{
return m_islandTag1;
return m_islandTag1;
}
void setIslandTag(int tag)
void setIslandTag(int tag)
{
m_islandTag1 = tag;
}
SIMD_FORCE_INLINE int getCompanionId() const
{
return m_companionId;
return m_companionId;
}
void setCompanionId(int id)
void setCompanionId(int id)
{
m_companionId = id;
}
SIMD_FORCE_INLINE int getWorldArrayIndex() const
SIMD_FORCE_INLINE btScalar getHitFraction() const
{
return m_worldArrayIndex;
return m_hitFraction;
}
// only should be called by CollisionWorld
void setWorldArrayIndex(int ix)
{
m_worldArrayIndex = ix;
}
SIMD_FORCE_INLINE btScalar getHitFraction() const
{
return m_hitFraction;
}
void setHitFraction(btScalar hitFraction)
void setHitFraction(btScalar hitFraction)
{
m_hitFraction = hitFraction;
}
SIMD_FORCE_INLINE int getCollisionFlags() const
SIMD_FORCE_INLINE int getCollisionFlags() const
{
return m_collisionFlags;
}
void setCollisionFlags(int flags)
void setCollisionFlags(int flags)
{
m_collisionFlags = flags;
}
///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
btScalar getCcdSweptSphereRadius() const
btScalar getCcdSweptSphereRadius() const
{
return m_ccdSweptSphereRadius;
}
///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
void setCcdSweptSphereRadius(btScalar radius)
void setCcdSweptSphereRadius(btScalar radius)
{
m_ccdSweptSphereRadius = radius;
}
btScalar getCcdMotionThreshold() const
btScalar getCcdMotionThreshold() const
{
return m_ccdMotionThreshold;
}
btScalar getCcdSquareMotionThreshold() const
btScalar getCcdSquareMotionThreshold() const
{
return m_ccdMotionThreshold * m_ccdMotionThreshold;
return m_ccdMotionThreshold*m_ccdMotionThreshold;
}
/// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
void setCcdMotionThreshold(btScalar ccdMotionThreshold)
void setCcdMotionThreshold(btScalar ccdMotionThreshold)
{
m_ccdMotionThreshold = ccdMotionThreshold;
}
///users can point to their objects, userPointer is not used by Bullet
void* getUserPointer() const
void* getUserPointer() const
{
return m_userObjectPointer;
}
int getUserIndex() const
int getUserIndex() const
{
return m_userIndex;
}
int getUserIndex2() const
{
return m_userIndex2;
}
int getUserIndex3() const
{
return m_userIndex3;
}
///users can point to their objects, userPointer is not used by Bullet
void setUserPointer(void* userPointer)
void setUserPointer(void* userPointer)
{
m_userObjectPointer = userPointer;
}
///users can point to their objects, userPointer is not used by Bullet
void setUserIndex(int index)
void setUserIndex(int index)
{
m_userIndex = index;
}
void setUserIndex2(int index)
{
m_userIndex2 = index;
}
void setUserIndex3(int index)
{
m_userIndex3 = index;
}
int getUpdateRevisionInternal() const
int getUpdateRevisionInternal() const
{
return m_updateRevision;
}
void setCustomDebugColor(const btVector3& colorRGB)
{
m_customDebugColorRGB = colorRGB;
m_collisionFlags |= CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR;
}
void removeCustomDebugColor()
{
m_collisionFlags &= ~CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR;
}
bool getCustomDebugColor(btVector3 & colorRGB) const
{
bool hasCustomColor = (0 != (m_collisionFlags & CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR));
if (hasCustomColor)
{
colorRGB = m_customDebugColorRGB;
}
return hasCustomColor;
}
inline bool checkCollideWith(const btCollisionObject* co) const
{
@@ -599,16 +502,15 @@ public:
return true;
}
virtual int calculateSerializeBufferSize() const;
virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
virtual void serializeSingleObject(class btSerializer* serializer) const;
virtual void serializeSingleObject(class btSerializer * serializer) const;
};
// clang-format off
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
struct btCollisionObjectDoubleData
{
@@ -626,12 +528,11 @@ struct btCollisionObjectDoubleData
double m_deactivationTime;
double m_friction;
double m_rollingFriction;
double m_contactDamping;
double m_contactStiffness;
double m_restitution;
double m_hitFraction;
double m_ccdSweptSphereRadius;
double m_ccdMotionThreshold;
int m_hasAnisotropicFriction;
int m_collisionFlags;
int m_islandTag1;
@@ -639,9 +540,8 @@ struct btCollisionObjectDoubleData
int m_activationState1;
int m_internalType;
int m_checkCollideWith;
int m_collisionFilterGroup;
int m_collisionFilterMask;
int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
char m_padding[4];
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
@@ -661,12 +561,12 @@ struct btCollisionObjectFloatData
float m_deactivationTime;
float m_friction;
float m_rollingFriction;
float m_contactDamping;
float m_contactStiffness;
float m_restitution;
float m_hitFraction;
float m_ccdSweptSphereRadius;
float m_ccdMotionThreshold;
int m_hasAnisotropicFriction;
int m_collisionFlags;
int m_islandTag1;
@@ -674,15 +574,16 @@ struct btCollisionObjectFloatData
int m_activationState1;
int m_internalType;
int m_checkCollideWith;
int m_collisionFilterGroup;
int m_collisionFilterMask;
int m_uniqueId;
char m_padding[4];
};
// clang-format on
SIMD_FORCE_INLINE int btCollisionObject::calculateSerializeBufferSize() const
SIMD_FORCE_INLINE int btCollisionObject::calculateSerializeBufferSize() const
{
return sizeof(btCollisionObjectData);
}
#endif //BT_COLLISION_OBJECT_H
#endif //BT_COLLISION_OBJECT_H

View File

@@ -1,25 +1,25 @@
#ifndef BT_COLLISION_OBJECT_WRAPPER_H
#define BT_COLLISION_OBJECT_WRAPPER_H
///btCollisionObjectWrapperis an internal data structure.
///btCollisionObjectWrapperis an internal data structure.
///Most users can ignore this and use btCollisionObject and btCollisionShape instead
class btCollisionShape;
class btCollisionObject;
class btTransform;
#include "LinearMath/btScalar.h" // for SIMD_FORCE_INLINE definition
#include "LinearMath/btScalar.h" // for SIMD_FORCE_INLINE definition
#define BT_DECLARE_STACK_ONLY_OBJECT \
private: \
void* operator new(size_t size); \
void operator delete(void*);
private: \
void* operator new(size_t size); \
void operator delete(void*);
struct btCollisionObjectWrapper;
struct btCollisionObjectWrapper
{
BT_DECLARE_STACK_ONLY_OBJECT
BT_DECLARE_STACK_ONLY_OBJECT
private:
btCollisionObjectWrapper(const btCollisionObjectWrapper&); // not implemented. Not allowed.
btCollisionObjectWrapper(const btCollisionObjectWrapper&); // not implemented. Not allowed.
btCollisionObjectWrapper* operator=(const btCollisionObjectWrapper&);
public:
@@ -27,23 +27,17 @@ public:
const btCollisionShape* m_shape;
const btCollisionObject* m_collisionObject;
const btTransform& m_worldTransform;
const btTransform* m_preTransform;
int m_partId;
int m_index;
int m_partId;
int m_index;
btCollisionObjectWrapper(const btCollisionObjectWrapper* parent, const btCollisionShape* shape, const btCollisionObject* collisionObject, const btTransform& worldTransform, int partId, int index)
: m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform), m_preTransform(NULL), m_partId(partId), m_index(index)
{
}
btCollisionObjectWrapper(const btCollisionObjectWrapper* parent, const btCollisionShape* shape, const btCollisionObject* collisionObject, const btTransform& worldTransform, const btTransform& preTransform, int partId, int index)
: m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform), m_preTransform(&preTransform), m_partId(partId), m_index(index)
{
}
: m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform),
m_partId(partId), m_index(index)
{}
SIMD_FORCE_INLINE const btTransform& getWorldTransform() const { return m_worldTransform; }
SIMD_FORCE_INLINE const btCollisionObject* getCollisionObject() const { return m_collisionObject; }
SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { return m_shape; }
};
#endif //BT_COLLISION_OBJECT_WRAPPER_H
#endif //BT_COLLISION_OBJECT_WRAPPER_H

File diff suppressed because it is too large Load Diff

View File

@@ -13,8 +13,9 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
/**
* @mainpage Bullet Documentation
* @page Bullet Documentation
*
* @section intro_sec Introduction
* Bullet is a Collision Detection and Rigid Body Dynamics Library. The Library is Open Source and free for commercial use, under the ZLib license ( http://opensource.org/licenses/zlib-license.php ).
@@ -65,6 +66,8 @@ subject to the following restrictions:
* For up-to-data information and copyright and contributors list check out the Bullet_User_Manual.pdf
*
*/
#ifndef BT_COLLISION_WORLD_H
#define BT_COLLISION_WORLD_H
@@ -84,138 +87,144 @@ class btSerializer;
///CollisionWorld is interface and container for the collision detection
class btCollisionWorld
{
protected:
btAlignedObjectArray<btCollisionObject*> m_collisionObjects;
btDispatcher* m_dispatcher1;
btAlignedObjectArray<btCollisionObject*> m_collisionObjects;
btDispatcher* m_dispatcher1;
btDispatcherInfo m_dispatchInfo;
btDispatcherInfo m_dispatchInfo;
btBroadphaseInterface* m_broadphasePairCache;
btBroadphaseInterface* m_broadphasePairCache;
btIDebugDraw* m_debugDrawer;
btIDebugDraw* m_debugDrawer;
///m_forceUpdateAllAabbs can be set to false as an optimization to only update active object AABBs
///it is true by default, because it is error-prone (setting the position of static objects wouldn't update their AABB)
bool m_forceUpdateAllAabbs;
void serializeCollisionObjects(btSerializer* serializer);
void serializeContactManifolds(btSerializer* serializer);
void serializeCollisionObjects(btSerializer* serializer);
public:
//this constructor doesn't own the dispatcher and paircache/broadphase
btCollisionWorld(btDispatcher* dispatcher, btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration);
btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration);
virtual ~btCollisionWorld();
void setBroadphase(btBroadphaseInterface* pairCache)
void setBroadphase(btBroadphaseInterface* pairCache)
{
m_broadphasePairCache = pairCache;
}
const btBroadphaseInterface* getBroadphase() const
const btBroadphaseInterface* getBroadphase() const
{
return m_broadphasePairCache;
}
btBroadphaseInterface* getBroadphase()
btBroadphaseInterface* getBroadphase()
{
return m_broadphasePairCache;
}
btOverlappingPairCache* getPairCache()
btOverlappingPairCache* getPairCache()
{
return m_broadphasePairCache->getOverlappingPairCache();
}
btDispatcher* getDispatcher()
btDispatcher* getDispatcher()
{
return m_dispatcher1;
}
const btDispatcher* getDispatcher() const
const btDispatcher* getDispatcher() const
{
return m_dispatcher1;
}
void updateSingleAabb(btCollisionObject* colObj);
void updateSingleAabb(btCollisionObject* colObj);
virtual void updateAabbs();
virtual void updateAabbs();
///the computeOverlappingPairs is usually already called by performDiscreteCollisionDetection (or stepSimulation)
///it can be useful to use if you perform ray tests without collision detection/simulation
virtual void computeOverlappingPairs();
virtual void computeOverlappingPairs();
virtual void setDebugDrawer(btIDebugDraw* debugDrawer)
virtual void setDebugDrawer(btIDebugDraw* debugDrawer)
{
m_debugDrawer = debugDrawer;
m_debugDrawer = debugDrawer;
}
virtual btIDebugDraw* getDebugDrawer()
virtual btIDebugDraw* getDebugDrawer()
{
return m_debugDrawer;
}
virtual void debugDrawWorld();
virtual void debugDrawWorld();
virtual void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color);
///LocalShapeInfo gives extra information for complex shapes
///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart
struct LocalShapeInfo
struct LocalShapeInfo
{
int m_shapePart;
int m_triangleIndex;
int m_shapePart;
int m_triangleIndex;
//const btCollisionShape* m_shapeTemp;
//const btTransform* m_shapeLocalTransform;
};
struct LocalRayResult
struct LocalRayResult
{
LocalRayResult(const btCollisionObject* collisionObject,
LocalShapeInfo* localShapeInfo,
const btVector3& hitNormalLocal,
btScalar hitFraction)
: m_collisionObject(collisionObject),
m_localShapeInfo(localShapeInfo),
m_hitNormalLocal(hitNormalLocal),
m_hitFraction(hitFraction)
LocalRayResult(const btCollisionObject* collisionObject,
LocalShapeInfo* localShapeInfo,
const btVector3& hitNormalLocal,
btScalar hitFraction)
:m_collisionObject(collisionObject),
m_localShapeInfo(localShapeInfo),
m_hitNormalLocal(hitNormalLocal),
m_hitFraction(hitFraction)
{
}
const btCollisionObject* m_collisionObject;
LocalShapeInfo* m_localShapeInfo;
btVector3 m_hitNormalLocal;
btScalar m_hitFraction;
const btCollisionObject* m_collisionObject;
LocalShapeInfo* m_localShapeInfo;
btVector3 m_hitNormalLocal;
btScalar m_hitFraction;
};
///RayResultCallback is used to report new raycast results
struct RayResultCallback
struct RayResultCallback
{
btScalar m_closestHitFraction;
const btCollisionObject* m_collisionObject;
int m_collisionFilterGroup;
int m_collisionFilterMask;
btScalar m_closestHitFraction;
const btCollisionObject* m_collisionObject;
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
//@BP Mod - Custom flags, currently used to enable backface culling on tri-meshes, see btRaycastCallback.h. Apply any of the EFlags defined there on m_flags here to invoke.
unsigned int m_flags;
virtual ~RayResultCallback()
{
}
bool hasHit() const
bool hasHit() const
{
return (m_collisionObject != 0);
}
RayResultCallback()
: m_closestHitFraction(btScalar(1.)),
m_collisionObject(0),
m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
m_collisionFilterMask(btBroadphaseProxy::AllFilter),
//@BP Mod
m_flags(0)
:m_closestHitFraction(btScalar(1.)),
m_collisionObject(0),
m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
m_collisionFilterMask(btBroadphaseProxy::AllFilter),
//@BP Mod
m_flags(0)
{
}
@@ -226,62 +235,62 @@ public:
return collides;
}
virtual btScalar addSingleResult(LocalRayResult& rayResult, bool normalInWorldSpace) = 0;
virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0;
};
struct ClosestRayResultCallback : public RayResultCallback
struct ClosestRayResultCallback : public RayResultCallback
{
ClosestRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld)
: m_rayFromWorld(rayFromWorld),
m_rayToWorld(rayToWorld)
ClosestRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld)
:m_rayFromWorld(rayFromWorld),
m_rayToWorld(rayToWorld)
{
}
btVector3 m_rayFromWorld; //used to calculate hitPointWorld from hitFraction
btVector3 m_rayToWorld;
btVector3 m_rayFromWorld;//used to calculate hitPointWorld from hitFraction
btVector3 m_rayToWorld;
btVector3 m_hitNormalWorld;
btVector3 m_hitPointWorld;
virtual btScalar addSingleResult(LocalRayResult& rayResult, bool normalInWorldSpace)
btVector3 m_hitNormalWorld;
btVector3 m_hitPointWorld;
virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace)
{
//caller already does the filter on the m_closestHitFraction
btAssert(rayResult.m_hitFraction <= m_closestHitFraction);
m_closestHitFraction = rayResult.m_hitFraction;
m_collisionObject = rayResult.m_collisionObject;
if (normalInWorldSpace)
{
m_hitNormalWorld = rayResult.m_hitNormalLocal;
}
else
} else
{
///need to transform normal into worldspace
m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis() * rayResult.m_hitNormalLocal;
m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal;
}
m_hitPointWorld.setInterpolate3(m_rayFromWorld, m_rayToWorld, rayResult.m_hitFraction);
m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction);
return rayResult.m_hitFraction;
}
};
struct AllHitsRayResultCallback : public RayResultCallback
struct AllHitsRayResultCallback : public RayResultCallback
{
AllHitsRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld)
: m_rayFromWorld(rayFromWorld),
m_rayToWorld(rayToWorld)
AllHitsRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld)
:m_rayFromWorld(rayFromWorld),
m_rayToWorld(rayToWorld)
{
}
btAlignedObjectArray<const btCollisionObject*> m_collisionObjects;
btAlignedObjectArray<const btCollisionObject*> m_collisionObjects;
btVector3 m_rayFromWorld; //used to calculate hitPointWorld from hitFraction
btVector3 m_rayToWorld;
btVector3 m_rayFromWorld;//used to calculate hitPointWorld from hitFraction
btVector3 m_rayToWorld;
btAlignedObjectArray<btVector3> m_hitNormalWorld;
btAlignedObjectArray<btVector3> m_hitPointWorld;
btAlignedObjectArray<btVector3> m_hitNormalWorld;
btAlignedObjectArray<btVector3> m_hitPointWorld;
btAlignedObjectArray<btScalar> m_hitFractions;
virtual btScalar addSingleResult(LocalRayResult& rayResult, bool normalInWorldSpace)
virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace)
{
m_collisionObject = rayResult.m_collisionObject;
m_collisionObjects.push_back(rayResult.m_collisionObject);
@@ -289,66 +298,69 @@ public:
if (normalInWorldSpace)
{
hitNormalWorld = rayResult.m_hitNormalLocal;
}
else
} else
{
///need to transform normal into worldspace
hitNormalWorld = m_collisionObject->getWorldTransform().getBasis() * rayResult.m_hitNormalLocal;
hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal;
}
m_hitNormalWorld.push_back(hitNormalWorld);
btVector3 hitPointWorld;
hitPointWorld.setInterpolate3(m_rayFromWorld, m_rayToWorld, rayResult.m_hitFraction);
hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction);
m_hitPointWorld.push_back(hitPointWorld);
m_hitFractions.push_back(rayResult.m_hitFraction);
return m_closestHitFraction;
}
};
struct LocalConvexResult
{
LocalConvexResult(const btCollisionObject* hitCollisionObject,
LocalShapeInfo* localShapeInfo,
const btVector3& hitNormalLocal,
const btVector3& hitPointLocal,
btScalar hitFraction)
: m_hitCollisionObject(hitCollisionObject),
m_localShapeInfo(localShapeInfo),
m_hitNormalLocal(hitNormalLocal),
m_hitPointLocal(hitPointLocal),
m_hitFraction(hitFraction)
LocalConvexResult(const btCollisionObject* hitCollisionObject,
LocalShapeInfo* localShapeInfo,
const btVector3& hitNormalLocal,
const btVector3& hitPointLocal,
btScalar hitFraction
)
:m_hitCollisionObject(hitCollisionObject),
m_localShapeInfo(localShapeInfo),
m_hitNormalLocal(hitNormalLocal),
m_hitPointLocal(hitPointLocal),
m_hitFraction(hitFraction)
{
}
const btCollisionObject* m_hitCollisionObject;
LocalShapeInfo* m_localShapeInfo;
btVector3 m_hitNormalLocal;
btVector3 m_hitPointLocal;
btScalar m_hitFraction;
const btCollisionObject* m_hitCollisionObject;
LocalShapeInfo* m_localShapeInfo;
btVector3 m_hitNormalLocal;
btVector3 m_hitPointLocal;
btScalar m_hitFraction;
};
///RayResultCallback is used to report new raycast results
struct ConvexResultCallback
struct ConvexResultCallback
{
btScalar m_closestHitFraction;
int m_collisionFilterGroup;
int m_collisionFilterMask;
btScalar m_closestHitFraction;
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
ConvexResultCallback()
: m_closestHitFraction(btScalar(1.)),
m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
m_collisionFilterMask(btBroadphaseProxy::AllFilter)
:m_closestHitFraction(btScalar(1.)),
m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
m_collisionFilterMask(btBroadphaseProxy::AllFilter)
{
}
virtual ~ConvexResultCallback()
{
}
bool hasHit() const
bool hasHit() const
{
return (m_closestHitFraction < btScalar(1.));
}
virtual bool needsCollision(btBroadphaseProxy* proxy0) const
{
bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
@@ -356,40 +368,39 @@ public:
return collides;
}
virtual btScalar addSingleResult(LocalConvexResult& convexResult, bool normalInWorldSpace) = 0;
virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) = 0;
};
struct ClosestConvexResultCallback : public ConvexResultCallback
struct ClosestConvexResultCallback : public ConvexResultCallback
{
ClosestConvexResultCallback(const btVector3& convexFromWorld, const btVector3& convexToWorld)
: m_convexFromWorld(convexFromWorld),
m_convexToWorld(convexToWorld),
m_hitCollisionObject(0)
ClosestConvexResultCallback(const btVector3& convexFromWorld,const btVector3& convexToWorld)
:m_convexFromWorld(convexFromWorld),
m_convexToWorld(convexToWorld),
m_hitCollisionObject(0)
{
}
btVector3 m_convexFromWorld; //used to calculate hitPointWorld from hitFraction
btVector3 m_convexToWorld;
btVector3 m_convexFromWorld;//used to calculate hitPointWorld from hitFraction
btVector3 m_convexToWorld;
btVector3 m_hitNormalWorld;
btVector3 m_hitPointWorld;
const btCollisionObject* m_hitCollisionObject;
virtual btScalar addSingleResult(LocalConvexResult& convexResult, bool normalInWorldSpace)
btVector3 m_hitNormalWorld;
btVector3 m_hitPointWorld;
const btCollisionObject* m_hitCollisionObject;
virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace)
{
//caller already does the filter on the m_closestHitFraction
//caller already does the filter on the m_closestHitFraction
btAssert(convexResult.m_hitFraction <= m_closestHitFraction);
m_closestHitFraction = convexResult.m_hitFraction;
m_hitCollisionObject = convexResult.m_hitCollisionObject;
if (normalInWorldSpace)
{
m_hitNormalWorld = convexResult.m_hitNormalLocal;
}
else
} else
{
///need to transform normal into worldspace
m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis() * convexResult.m_hitNormalLocal;
m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
}
m_hitPointWorld = convexResult.m_hitPointLocal;
return convexResult.m_hitFraction;
@@ -397,23 +408,21 @@ public:
};
///ContactResultCallback is used to report contact points
struct ContactResultCallback
struct ContactResultCallback
{
int m_collisionFilterGroup;
int m_collisionFilterMask;
btScalar m_closestDistanceThreshold;
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
ContactResultCallback()
: m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
m_collisionFilterMask(btBroadphaseProxy::AllFilter),
m_closestDistanceThreshold(0)
:m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
m_collisionFilterMask(btBroadphaseProxy::AllFilter)
{
}
virtual ~ContactResultCallback()
{
}
virtual bool needsCollision(btBroadphaseProxy* proxy0) const
{
bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
@@ -421,57 +430,58 @@ public:
return collides;
}
virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper* colObj1Wrap, int partId1, int index1) = 0;
virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1) = 0;
};
int getNumCollisionObjects() const
int getNumCollisionObjects() const
{
return int(m_collisionObjects.size());
}
/// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback
/// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback.
virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;
virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;
/// convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultCallback
/// This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback.
void convexSweepTest(const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = btScalar(0.)) const;
void convexSweepTest (const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = btScalar(0.)) const;
///contactTest performs a discrete collision test between colObj against all objects in the btCollisionWorld, and calls the resultCallback.
///it reports one or more contact points for every overlapping object (including the one with deepest penetration)
void contactTest(btCollisionObject* colObj, ContactResultCallback& resultCallback);
void contactTest(btCollisionObject* colObj, ContactResultCallback& resultCallback);
///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected.
///it reports one or more contact points (including the one with deepest penetration)
void contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback);
void contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback);
/// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
/// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape.
/// This allows more customization.
static void rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
RayResultCallback& resultCallback);
static void rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
RayResultCallback& resultCallback);
static void rayTestSingleInternal(const btTransform& rayFromTrans, const btTransform& rayToTrans,
const btCollisionObjectWrapper* collisionObjectWrap,
RayResultCallback& resultCallback);
static void rayTestSingleInternal(const btTransform& rayFromTrans,const btTransform& rayToTrans,
const btCollisionObjectWrapper* collisionObjectWrap,
RayResultCallback& resultCallback);
/// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest.
static void objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans, const btTransform& rayToTrans,
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
ConvexResultCallback& resultCallback, btScalar allowedPenetration);
static void objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans,const btTransform& rayToTrans,
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
ConvexResultCallback& resultCallback, btScalar allowedPenetration);
static void objectQuerySingleInternal(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans,
const btCollisionObjectWrapper* colObjWrap,
ConvexResultCallback& resultCallback, btScalar allowedPenetration);
static void objectQuerySingleInternal(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
const btCollisionObjectWrapper* colObjWrap,
ConvexResultCallback& resultCallback, btScalar allowedPenetration);
virtual void addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup = btBroadphaseProxy::DefaultFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter);
virtual void refreshBroadphaseProxy(btCollisionObject* collisionObject);
virtual void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter);
btCollisionObjectArray& getCollisionObjectArray()
{
@@ -483,9 +493,10 @@ public:
return m_collisionObjects;
}
virtual void removeCollisionObject(btCollisionObject* collisionObject);
virtual void performDiscreteCollisionDetection();
virtual void removeCollisionObject(btCollisionObject* collisionObject);
virtual void performDiscreteCollisionDetection();
btDispatcherInfo& getDispatchInfo()
{
@@ -496,18 +507,20 @@ public:
{
return m_dispatchInfo;
}
bool getForceUpdateAllAabbs() const
bool getForceUpdateAllAabbs() const
{
return m_forceUpdateAllAabbs;
}
void setForceUpdateAllAabbs(bool forceUpdateAllAabbs)
void setForceUpdateAllAabbs( bool forceUpdateAllAabbs)
{
m_forceUpdateAllAabbs = forceUpdateAllAabbs;
}
///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (Bullet/Demos/SerializeDemo)
virtual void serialize(btSerializer* serializer);
virtual void serialize(btSerializer* serializer);
};
#endif //BT_COLLISION_WORLD_H
#endif //BT_COLLISION_WORLD_H

View File

@@ -13,6 +13,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_COLLISION_WORLD_IMPORTER_H
#define BT_COLLISION_WORLD_IMPORTER_H
@@ -25,6 +26,7 @@ class btCollisionShape;
class btCollisionObject;
struct btBulletSerializedArrays;
struct ConstraintInput;
class btCollisionWorld;
struct btCollisionShapeData;
@@ -44,6 +46,9 @@ class btSliderConstraint;
class btGearConstraint;
struct btContactSolverInfo;
class btCollisionWorldImporter
{
protected:
@@ -51,53 +56,60 @@ protected:
int m_verboseMode;
btAlignedObjectArray<btCollisionShape*> m_allocatedCollisionShapes;
btAlignedObjectArray<btCollisionShape*> m_allocatedCollisionShapes;
btAlignedObjectArray<btCollisionObject*> m_allocatedRigidBodies;
btAlignedObjectArray<btOptimizedBvh*> m_allocatedBvhs;
btAlignedObjectArray<btOptimizedBvh*> m_allocatedBvhs;
btAlignedObjectArray<btTriangleInfoMap*> m_allocatedTriangleInfoMaps;
btAlignedObjectArray<btTriangleIndexVertexArray*> m_allocatedTriangleIndexArrays;
btAlignedObjectArray<btStridingMeshInterfaceData*> m_allocatedbtStridingMeshInterfaceDatas;
btAlignedObjectArray<btCollisionObject*> m_allocatedCollisionObjects;
btAlignedObjectArray<char*> m_allocatedNames;
btAlignedObjectArray<int*> m_indexArrays;
btAlignedObjectArray<short int*> m_shortIndexArrays;
btAlignedObjectArray<unsigned char*> m_charIndexArrays;
btAlignedObjectArray<char*> m_allocatedNames;
btAlignedObjectArray<btVector3FloatData*> m_floatVertexArrays;
btAlignedObjectArray<btVector3DoubleData*> m_doubleVertexArrays;
btAlignedObjectArray<int*> m_indexArrays;
btAlignedObjectArray<short int*> m_shortIndexArrays;
btAlignedObjectArray<unsigned char*> m_charIndexArrays;
btHashMap<btHashPtr, btOptimizedBvh*> m_bvhMap;
btHashMap<btHashPtr, btTriangleInfoMap*> m_timMap;
btAlignedObjectArray<btVector3FloatData*> m_floatVertexArrays;
btAlignedObjectArray<btVector3DoubleData*> m_doubleVertexArrays;
btHashMap<btHashString, btCollisionShape*> m_nameShapeMap;
btHashMap<btHashString, btCollisionObject*> m_nameColObjMap;
btHashMap<btHashPtr, const char*> m_objectNameMap;
btHashMap<btHashPtr,btOptimizedBvh*> m_bvhMap;
btHashMap<btHashPtr,btTriangleInfoMap*> m_timMap;
btHashMap<btHashString,btCollisionShape*> m_nameShapeMap;
btHashMap<btHashString,btCollisionObject*> m_nameColObjMap;
btHashMap<btHashPtr,const char*> m_objectNameMap;
btHashMap<btHashPtr,btCollisionShape*> m_shapeMap;
btHashMap<btHashPtr,btCollisionObject*> m_bodyMap;
btHashMap<btHashPtr, btCollisionShape*> m_shapeMap;
btHashMap<btHashPtr, btCollisionObject*> m_bodyMap;
//methods
char* duplicateName(const char* name);
btCollisionShape* convertCollisionShape(btCollisionShapeData* shapeData);
char* duplicateName(const char* name);
btCollisionShape* convertCollisionShape( btCollisionShapeData* shapeData );
public:
btCollisionWorldImporter(btCollisionWorld* world);
virtual ~btCollisionWorldImporter();
bool convertAllObjects(btBulletSerializedArrays* arrays);
bool convertAllObjects( btBulletSerializedArrays* arrays);
///delete all memory collision shapes, rigid bodies, constraints etc. allocated during the load.
///delete all memory collision shapes, rigid bodies, constraints etc. allocated during the load.
///make sure you don't use the dynamics world containing objects after you call this method
virtual void deleteAllData();
void setVerboseMode(int verboseMode)
void setVerboseMode(int verboseMode)
{
m_verboseMode = verboseMode;
}
@@ -107,14 +119,15 @@ public:
return m_verboseMode;
}
// query for data
int getNumCollisionShapes() const;
// query for data
int getNumCollisionShapes() const;
btCollisionShape* getCollisionShapeByIndex(int index);
int getNumRigidBodies() const;
btCollisionObject* getRigidBodyByIndex(int index) const;
int getNumConstraints() const;
int getNumBvhs() const;
btOptimizedBvh* getBvhByIndex(int index) const;
btOptimizedBvh* getBvhByIndex(int index) const;
int getNumTriangleInfoMaps() const;
btTriangleInfoMap* getTriangleInfoMapByIndex(int index) const;
@@ -122,48 +135,56 @@ public:
btCollisionShape* getCollisionShapeByName(const char* name);
btCollisionObject* getCollisionObjectByName(const char* name);
const char* getNameForPointer(const void* ptr) const;
const char* getNameForPointer(const void* ptr) const;
///those virtuals are called by load and can be overridden by the user
//bodies
virtual btCollisionObject* createCollisionObject(const btTransform& startTransform, btCollisionShape* shape, const char* bodyName);
virtual btCollisionObject* createCollisionObject( const btTransform& startTransform, btCollisionShape* shape,const char* bodyName);
///shapes
virtual btCollisionShape* createPlaneShape(const btVector3& planeNormal, btScalar planeConstant);
virtual btCollisionShape* createPlaneShape(const btVector3& planeNormal,btScalar planeConstant);
virtual btCollisionShape* createBoxShape(const btVector3& halfExtents);
virtual btCollisionShape* createSphereShape(btScalar radius);
virtual btCollisionShape* createCapsuleShapeX(btScalar radius, btScalar height);
virtual btCollisionShape* createCapsuleShapeY(btScalar radius, btScalar height);
virtual btCollisionShape* createCapsuleShapeZ(btScalar radius, btScalar height);
virtual btCollisionShape* createCylinderShapeX(btScalar radius, btScalar height);
virtual btCollisionShape* createCylinderShapeY(btScalar radius, btScalar height);
virtual btCollisionShape* createCylinderShapeZ(btScalar radius, btScalar height);
virtual btCollisionShape* createConeShapeX(btScalar radius, btScalar height);
virtual btCollisionShape* createConeShapeY(btScalar radius, btScalar height);
virtual btCollisionShape* createConeShapeZ(btScalar radius, btScalar height);
virtual class btTriangleIndexVertexArray* createTriangleMeshContainer();
virtual btBvhTriangleMeshShape* createBvhTriangleMeshShape(btStridingMeshInterface* trimesh, btOptimizedBvh* bvh);
virtual btCollisionShape* createCylinderShapeX(btScalar radius,btScalar height);
virtual btCollisionShape* createCylinderShapeY(btScalar radius,btScalar height);
virtual btCollisionShape* createCylinderShapeZ(btScalar radius,btScalar height);
virtual btCollisionShape* createConeShapeX(btScalar radius,btScalar height);
virtual btCollisionShape* createConeShapeY(btScalar radius,btScalar height);
virtual btCollisionShape* createConeShapeZ(btScalar radius,btScalar height);
virtual class btTriangleIndexVertexArray* createTriangleMeshContainer();
virtual btBvhTriangleMeshShape* createBvhTriangleMeshShape(btStridingMeshInterface* trimesh, btOptimizedBvh* bvh);
virtual btCollisionShape* createConvexTriangleMeshShape(btStridingMeshInterface* trimesh);
#ifdef SUPPORT_GIMPACT_SHAPE_IMPORT
virtual btGImpactMeshShape* createGimpactShape(btStridingMeshInterface* trimesh);
#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
virtual btStridingMeshInterfaceData* createStridingMeshInterfaceData(btStridingMeshInterfaceData* interfaceData);
virtual class btConvexHullShape* createConvexHullShape();
virtual class btCompoundShape* createCompoundShape();
virtual class btScaledBvhTriangleMeshShape* createScaledTrangleMeshShape(btBvhTriangleMeshShape* meshShape, const btVector3& localScalingbtBvhTriangleMeshShape);
virtual class btScaledBvhTriangleMeshShape* createScaledTrangleMeshShape(btBvhTriangleMeshShape* meshShape,const btVector3& localScalingbtBvhTriangleMeshShape);
virtual class btMultiSphereShape* createMultiSphereShape(const btVector3* positions, const btScalar* radi, int numSpheres);
virtual class btMultiSphereShape* createMultiSphereShape(const btVector3* positions,const btScalar* radi,int numSpheres);
virtual btTriangleIndexVertexArray* createMeshInterface(btStridingMeshInterfaceData& meshData);
///acceleration and connectivity structures
virtual btOptimizedBvh* createOptimizedBvh();
virtual btOptimizedBvh* createOptimizedBvh();
virtual btTriangleInfoMap* createTriangleInfoMap();
};
#endif //BT_WORLD_IMPORTER_H
#endif //BT_WORLD_IMPORTER_H

View File

@@ -25,58 +25,56 @@ subject to the following restrictions:
btShapePairCallback gCompoundChildShapePairCallback = 0;
btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped)
: btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
m_isSwapped(isSwapped),
m_sharedManifold(ci.m_manifold)
btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped)
:btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
m_isSwapped(isSwapped),
m_sharedManifold(ci.m_manifold)
{
m_ownsManifold = false;
const btCollisionObjectWrapper* colObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
btAssert(colObjWrap->getCollisionShape()->isCompound());
const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
btAssert (colObjWrap->getCollisionShape()->isCompound());
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
m_compoundShapeRevision = compoundShape->getUpdateRevision();
preallocateChildAlgorithms(body0Wrap, body1Wrap);
preallocateChildAlgorithms(body0Wrap,body1Wrap);
}
void btCompoundCollisionAlgorithm::preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
void btCompoundCollisionAlgorithm::preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
const btCollisionObjectWrapper* colObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* otherObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
btAssert(colObjWrap->getCollisionShape()->isCompound());
const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* otherObjWrap = m_isSwapped? body0Wrap : body1Wrap;
btAssert (colObjWrap->getCollisionShape()->isCompound());
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
int numChildren = compoundShape->getNumChildShapes();
int i;
m_childCollisionAlgorithms.resize(numChildren);
for (i = 0; i < numChildren; i++)
for (i=0;i<numChildren;i++)
{
if (compoundShape->getDynamicAabbTree())
{
m_childCollisionAlgorithms[i] = 0;
}
else
} else
{
const btCollisionShape* childShape = compoundShape->getChildShape(i);
btCollisionObjectWrapper childWrap(colObjWrap, childShape, colObjWrap->getCollisionObject(), colObjWrap->getWorldTransform(), -1, i); //wrong child trans, but unused (hopefully)
m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(&childWrap, otherObjWrap, m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS);
btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithmsContact;
btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithmsClosestPoints;
btCollisionObjectWrapper childWrap(colObjWrap,childShape,colObjWrap->getCollisionObject(),colObjWrap->getWorldTransform(),-1,i);//wrong child trans, but unused (hopefully)
m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(&childWrap,otherObjWrap,m_sharedManifold);
}
}
}
void btCompoundCollisionAlgorithm::removeChildAlgorithms()
void btCompoundCollisionAlgorithm::removeChildAlgorithms()
{
int numChildren = m_childCollisionAlgorithms.size();
int i;
for (i = 0; i < numChildren; i++)
for (i=0;i<numChildren;i++)
{
if (m_childCollisionAlgorithms[i])
{
@@ -91,27 +89,48 @@ btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm()
removeChildAlgorithms();
}
struct btCompoundLeafCallback : btDbvt::ICollide
struct btCompoundLeafCallback : btDbvt::ICollide
{
public:
const btCollisionObjectWrapper* m_compoundColObjWrap;
const btCollisionObjectWrapper* m_otherObjWrap;
btDispatcher* m_dispatcher;
const btDispatcherInfo& m_dispatchInfo;
btManifoldResult* m_resultOut;
btCollisionAlgorithm** m_childCollisionAlgorithms;
btPersistentManifold* m_sharedManifold;
btCompoundLeafCallback(const btCollisionObjectWrapper* compoundObjWrap, const btCollisionObjectWrapper* otherObjWrap, btDispatcher* dispatcher, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut, btCollisionAlgorithm** childCollisionAlgorithms, btPersistentManifold* sharedManifold)
: m_compoundColObjWrap(compoundObjWrap), m_otherObjWrap(otherObjWrap), m_dispatcher(dispatcher), m_dispatchInfo(dispatchInfo), m_resultOut(resultOut), m_childCollisionAlgorithms(childCollisionAlgorithms), m_sharedManifold(sharedManifold)
btManifoldResult* m_resultOut;
btCollisionAlgorithm** m_childCollisionAlgorithms;
btPersistentManifold* m_sharedManifold;
btCompoundLeafCallback (const btCollisionObjectWrapper* compoundObjWrap,const btCollisionObjectWrapper* otherObjWrap,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut,btCollisionAlgorithm** childCollisionAlgorithms,btPersistentManifold* sharedManifold)
:m_compoundColObjWrap(compoundObjWrap),m_otherObjWrap(otherObjWrap),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
m_childCollisionAlgorithms(childCollisionAlgorithms),
m_sharedManifold(sharedManifold)
{
}
void ProcessChildShape(const btCollisionShape* childShape, int index)
void ProcessChildShape(const btCollisionShape* childShape,int index)
{
btAssert(index >= 0);
btAssert(index>=0);
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(m_compoundColObjWrap->getCollisionShape());
btAssert(index < compoundShape->getNumChildShapes());
btAssert(index<compoundShape->getNumChildShapes());
//backup
btTransform orgTrans = m_compoundColObjWrap->getWorldTransform();
const btTransform& childTrans = compoundShape->getChildTransform(index);
btTransform newChildWorldTrans = orgTrans*childTrans ;
//perform an AABB check first
btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
m_otherObjWrap->getCollisionShape()->getAabb(m_otherObjWrap->getWorldTransform(),aabbMin1,aabbMax1);
if (gCompoundChildShapePairCallback)
{
@@ -119,51 +138,17 @@ public:
return;
}
//backup
btTransform orgTrans = m_compoundColObjWrap->getWorldTransform();
const btTransform& childTrans = compoundShape->getChildTransform(index);
btTransform newChildWorldTrans = orgTrans * childTrans;
//perform an AABB check first
btVector3 aabbMin0, aabbMax0;
childShape->getAabb(newChildWorldTrans, aabbMin0, aabbMax0);
btVector3 extendAabb(m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold);
aabbMin0 -= extendAabb;
aabbMax0 += extendAabb;
btVector3 aabbMin1, aabbMax1;
m_otherObjWrap->getCollisionShape()->getAabb(m_otherObjWrap->getWorldTransform(), aabbMin1, aabbMax1);
if (TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
{
btTransform preTransform = childTrans;
if (this->m_compoundColObjWrap->m_preTransform)
{
preTransform = preTransform *(*(this->m_compoundColObjWrap->m_preTransform));
}
btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap, childShape, m_compoundColObjWrap->getCollisionObject(), newChildWorldTrans, preTransform, -1, index);
btCollisionAlgorithm* algo = 0;
bool allocatedAlgorithm = false;
btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap,childShape,m_compoundColObjWrap->getCollisionObject(),newChildWorldTrans,-1,index);
if (m_resultOut->m_closestPointDistanceThreshold > 0)
{
algo = m_dispatcher->findAlgorithm(&compoundWrap, m_otherObjWrap, 0, BT_CLOSEST_POINT_ALGORITHMS);
allocatedAlgorithm = true;
}
else
{
//the contactpoint is still projected back using the original inverted worldtrans
if (!m_childCollisionAlgorithms[index])
{
m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(&compoundWrap, m_otherObjWrap, m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS);
}
algo = m_childCollisionAlgorithms[index];
}
//the contactpoint is still projected back using the original inverted worldtrans
if (!m_childCollisionAlgorithms[index])
m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(&compoundWrap,m_otherObjWrap,m_sharedManifold);
const btCollisionObjectWrapper* tmpWrap = 0;
///detect swapping case
@@ -171,16 +156,16 @@ public:
{
tmpWrap = m_resultOut->getBody0Wrap();
m_resultOut->setBody0Wrap(&compoundWrap);
m_resultOut->setShapeIdentifiersA(-1, index);
}
else
m_resultOut->setShapeIdentifiersA(-1,index);
} else
{
tmpWrap = m_resultOut->getBody1Wrap();
m_resultOut->setBody1Wrap(&compoundWrap);
m_resultOut->setShapeIdentifiersB(-1, index);
m_resultOut->setShapeIdentifiersB(-1,index);
}
algo->processCollision(&compoundWrap, m_otherObjWrap, m_dispatchInfo, m_resultOut);
m_childCollisionAlgorithms[index]->processCollision(&compoundWrap,m_otherObjWrap,m_dispatchInfo,m_resultOut);
#if 0
if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
@@ -194,19 +179,14 @@ public:
if (m_resultOut->getBody0Internal() == m_compoundColObjWrap->getCollisionObject())
{
m_resultOut->setBody0Wrap(tmpWrap);
}
else
} else
{
m_resultOut->setBody1Wrap(tmpWrap);
}
if (allocatedAlgorithm)
{
algo->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(algo);
}
}
}
void Process(const btDbvtNode* leaf)
void Process(const btDbvtNode* leaf)
{
int index = leaf->dataAsInt;
@@ -223,16 +203,22 @@ public:
}
#endif
ProcessChildShape(childShape, index);
ProcessChildShape(childShape,index);
}
};
void btCompoundCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
const btCollisionObjectWrapper* colObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* otherObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
btAssert(colObjWrap->getCollisionShape()->isCompound());
void btCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* otherObjWrap = m_isSwapped? body0Wrap : body1Wrap;
btAssert (colObjWrap->getCollisionShape()->isCompound());
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
///btCompoundShape might have changed:
@@ -241,36 +227,36 @@ void btCompoundCollisionAlgorithm::processCollision(const btCollisionObjectWrapp
{
///clear and update all
removeChildAlgorithms();
preallocateChildAlgorithms(body0Wrap, body1Wrap);
preallocateChildAlgorithms(body0Wrap,body1Wrap);
m_compoundShapeRevision = compoundShape->getUpdateRevision();
}
if (m_childCollisionAlgorithms.size() == 0)
if (m_childCollisionAlgorithms.size()==0)
return;
const btDbvt* tree = compoundShape->getDynamicAabbTree();
//use a dynamic aabb tree to cull potential child-overlaps
btCompoundLeafCallback callback(colObjWrap, otherObjWrap, m_dispatcher, dispatchInfo, resultOut, &m_childCollisionAlgorithms[0], m_sharedManifold);
btCompoundLeafCallback callback(colObjWrap,otherObjWrap,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);
///we need to refresh all contact manifolds
///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep
///so we should add a 'refreshManifolds' in the btCollisionAlgorithm
{
int i;
manifoldArray.resize(0);
for (i = 0; i < m_childCollisionAlgorithms.size(); i++)
btManifoldArray manifoldArray;
for (i=0;i<m_childCollisionAlgorithms.size();i++)
{
if (m_childCollisionAlgorithms[i])
{
m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
for (int m = 0; m < manifoldArray.size(); m++)
for (int m=0;m<manifoldArray.size();m++)
{
if (manifoldArray[m]->getNumContacts())
{
resultOut->setPersistentManifold(manifoldArray[m]);
resultOut->refreshContactPoints();
resultOut->setPersistentManifold(0); //??necessary?
resultOut->setPersistentManifold(0);//??necessary?
}
}
manifoldArray.resize(0);
@@ -280,56 +266,54 @@ void btCompoundCollisionAlgorithm::processCollision(const btCollisionObjectWrapp
if (tree)
{
btVector3 localAabbMin, localAabbMax;
btVector3 localAabbMin,localAabbMax;
btTransform otherInCompoundSpace;
otherInCompoundSpace = colObjWrap->getWorldTransform().inverse() * otherObjWrap->getWorldTransform();
otherObjWrap->getCollisionShape()->getAabb(otherInCompoundSpace, localAabbMin, localAabbMax);
btVector3 extraExtends(resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold);
localAabbMin -= extraExtends;
localAabbMax += extraExtends;
otherObjWrap->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax);
const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(localAabbMin, localAabbMax);
const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
//process all children, that overlap with the given AABB bounds
tree->collideTVNoStackAlloc(tree->m_root, bounds, stack2, callback);
}
else
tree->collideTV(tree->m_root,bounds,callback);
} else
{
//iterate over all children, perform an AABB check inside ProcessChildShape
int numChildren = m_childCollisionAlgorithms.size();
int i;
for (i = 0; i < numChildren; i++)
for (i=0;i<numChildren;i++)
{
callback.ProcessChildShape(compoundShape->getChildShape(i), i);
callback.ProcessChildShape(compoundShape->getChildShape(i),i);
}
}
{
//iterate over all children, perform an AABB check inside ProcessChildShape
//iterate over all children, perform an AABB check inside ProcessChildShape
int numChildren = m_childCollisionAlgorithms.size();
int i;
manifoldArray.resize(0);
const btCollisionShape* childShape = 0;
btTransform orgTrans;
btTransform newChildWorldTrans;
btVector3 aabbMin0, aabbMax0, aabbMin1, aabbMax1;
for (i = 0; i < numChildren; i++)
btManifoldArray manifoldArray;
const btCollisionShape* childShape = 0;
btTransform orgTrans;
btTransform newChildWorldTrans;
btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
for (i=0;i<numChildren;i++)
{
if (m_childCollisionAlgorithms[i])
{
childShape = compoundShape->getChildShape(i);
//if not longer overlapping, remove the algorithm
//if not longer overlapping, remove the algorithm
orgTrans = colObjWrap->getWorldTransform();
const btTransform& childTrans = compoundShape->getChildTransform(i);
newChildWorldTrans = orgTrans * childTrans;
newChildWorldTrans = orgTrans*childTrans ;
//perform an AABB check first
childShape->getAabb(newChildWorldTrans, aabbMin0, aabbMax0);
otherObjWrap->getCollisionShape()->getAabb(otherObjWrap->getWorldTransform(), aabbMin1, aabbMax1);
childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
otherObjWrap->getCollisionShape()->getAabb(otherObjWrap->getWorldTransform(),aabbMin1,aabbMax1);
if (!TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
{
m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
@@ -340,15 +324,15 @@ void btCompoundCollisionAlgorithm::processCollision(const btCollisionObjectWrapp
}
}
btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
btAssert(0);
//needs to be fixed, using btCollisionObjectWrapper and NOT modifying internal data structures
btCollisionObject* colObj = m_isSwapped ? body1 : body0;
btCollisionObject* otherObj = m_isSwapped ? body0 : body1;
btAssert(colObj->getCollisionShape()->isCompound());
btCollisionObject* colObj = m_isSwapped? body1 : body0;
btCollisionObject* otherObj = m_isSwapped? body0 : body1;
btAssert (colObj->getCollisionShape()->isCompound());
btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
//We will use the OptimizedBVH, AABB tree to cull potential child-overlaps
@@ -362,29 +346,33 @@ btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject*
int numChildren = m_childCollisionAlgorithms.size();
int i;
btTransform orgTrans;
btScalar frac;
for (i = 0; i < numChildren; i++)
btTransform orgTrans;
btScalar frac;
for (i=0;i<numChildren;i++)
{
//btCollisionShape* childShape = compoundShape->getChildShape(i);
//backup
orgTrans = colObj->getWorldTransform();
orgTrans = colObj->getWorldTransform();
const btTransform& childTrans = compoundShape->getChildTransform(i);
//btTransform newChildWorldTrans = orgTrans*childTrans ;
colObj->setWorldTransform(orgTrans * childTrans);
colObj->setWorldTransform( orgTrans*childTrans );
//btCollisionShape* tmpShape = colObj->getCollisionShape();
//colObj->internalSetTemporaryCollisionShape( childShape );
frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj, otherObj, dispatchInfo, resultOut);
if (frac < hitFraction)
frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut);
if (frac<hitFraction)
{
hitFraction = frac;
}
//revert back
//colObj->internalSetTemporaryCollisionShape( tmpShape);
colObj->setWorldTransform(orgTrans);
colObj->setWorldTransform( orgTrans);
}
return hitFraction;
}

View File

@@ -26,7 +26,6 @@ class btDispatcher;
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "btCollisionCreateFunc.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "BulletCollision/BroadphaseCollision/btDbvt.h"
class btDispatcher;
class btCollisionObject;
@@ -35,65 +34,67 @@ typedef bool (*btShapePairCallback)(const btCollisionShape* pShape0, const btCol
extern btShapePairCallback gCompoundChildShapePairCallback;
/// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes
class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm
class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
btNodeStack stack2;
btManifoldArray manifoldArray;
protected:
btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithms;
bool m_isSwapped;
class btPersistentManifold* m_sharedManifold;
bool m_ownsManifold;
class btPersistentManifold* m_sharedManifold;
bool m_ownsManifold;
int m_compoundShapeRevision; //to keep track of changes, so that childAlgorithm array can be updated
void removeChildAlgorithms();
void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
int m_compoundShapeRevision;//to keep track of changes, so that childAlgorithm array can be updated
void removeChildAlgorithms();
void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
public:
btCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
virtual ~btCompoundCollisionAlgorithm();
btCollisionAlgorithm* getChildAlgorithm(int n) const
btCollisionAlgorithm* getChildAlgorithm (int n) const
{
return m_childCollisionAlgorithms[n];
}
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
int i;
for (i = 0; i < m_childCollisionAlgorithms.size(); i++)
for (i=0;i<m_childCollisionAlgorithms.size();i++)
{
if (m_childCollisionAlgorithms[i])
m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
}
}
struct CreateFunc : public btCollisionAlgorithmCreateFunc
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
return new (mem) btCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, false);
return new(mem) btCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,false);
}
};
struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc
struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
return new (mem) btCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, true);
return new(mem) btCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,true);
}
};
};
#endif //BT_COMPOUND_COLLISION_ALGORITHM_H
#endif //BT_COMPOUND_COLLISION_ALGORITHM_H

View File

@@ -15,7 +15,6 @@ subject to the following restrictions:
*/
#include "btCompoundCompoundCollisionAlgorithm.h"
#include "LinearMath/btQuickprof.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "BulletCollision/BroadphaseCollision/btDbvt.h"
@@ -24,30 +23,32 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
//USE_LOCAL_STACK will avoid most (often all) dynamic memory allocations due to resizing in processCollision and MycollideTT
#define USE_LOCAL_STACK 1
btShapePairCallback gCompoundCompoundChildShapePairCallback = 0;
btCompoundCompoundCollisionAlgorithm::btCompoundCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped)
: btCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, isSwapped)
btCompoundCompoundCollisionAlgorithm::btCompoundCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped)
:btCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,isSwapped)
{
void* ptr = btAlignedAlloc(sizeof(btHashedSimplePairCache), 16);
m_childCollisionAlgorithmCache = new (ptr) btHashedSimplePairCache();
void* ptr = btAlignedAlloc(sizeof(btHashedSimplePairCache),16);
m_childCollisionAlgorithmCache= new(ptr) btHashedSimplePairCache();
const btCollisionObjectWrapper* col0ObjWrap = body0Wrap;
btAssert(col0ObjWrap->getCollisionShape()->isCompound());
btAssert (col0ObjWrap->getCollisionShape()->isCompound());
const btCollisionObjectWrapper* col1ObjWrap = body1Wrap;
btAssert(col1ObjWrap->getCollisionShape()->isCompound());
btAssert (col1ObjWrap->getCollisionShape()->isCompound());
const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(col0ObjWrap->getCollisionShape());
m_compoundShapeRevision0 = compoundShape0->getUpdateRevision();
const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(col1ObjWrap->getCollisionShape());
m_compoundShapeRevision1 = compoundShape1->getUpdateRevision();
}
btCompoundCompoundCollisionAlgorithm::~btCompoundCompoundCollisionAlgorithm()
{
removeChildAlgorithms();
@@ -55,30 +56,32 @@ btCompoundCompoundCollisionAlgorithm::~btCompoundCompoundCollisionAlgorithm()
btAlignedFree(m_childCollisionAlgorithmCache);
}
void btCompoundCompoundCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
void btCompoundCompoundCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
{
int i;
btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
for (i = 0; i < pairs.size(); i++)
for (i=0;i<pairs.size();i++)
{
if (pairs[i].m_userPointer)
{
((btCollisionAlgorithm*)pairs[i].m_userPointer)->getAllContactManifolds(manifoldArray);
}
}
}
void btCompoundCompoundCollisionAlgorithm::removeChildAlgorithms()
void btCompoundCompoundCollisionAlgorithm::removeChildAlgorithms()
{
btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
int numChildren = pairs.size();
int i;
for (i = 0; i < numChildren; i++)
for (i=0;i<numChildren;i++)
{
if (pairs[i].m_userPointer)
{
btCollisionAlgorithm* algo = (btCollisionAlgorithm*)pairs[i].m_userPointer;
btCollisionAlgorithm* algo = (btCollisionAlgorithm*) pairs[i].m_userPointer;
algo->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(algo);
}
@@ -86,106 +89,106 @@ void btCompoundCompoundCollisionAlgorithm::removeChildAlgorithms()
m_childCollisionAlgorithmCache->removeAllPairs();
}
struct btCompoundCompoundLeafCallback : btDbvt::ICollide
struct btCompoundCompoundLeafCallback : btDbvt::ICollide
{
int m_numOverlapPairs;
const btCollisionObjectWrapper* m_compound0ColObjWrap;
const btCollisionObjectWrapper* m_compound1ColObjWrap;
btDispatcher* m_dispatcher;
const btDispatcherInfo& m_dispatchInfo;
btManifoldResult* m_resultOut;
class btHashedSimplePairCache* m_childCollisionAlgorithmCache;
btPersistentManifold* m_sharedManifold;
btCompoundCompoundLeafCallback(const btCollisionObjectWrapper* compound1ObjWrap,
const btCollisionObjectWrapper* compound0ObjWrap,
btDispatcher* dispatcher,
const btDispatcherInfo& dispatchInfo,
btManifoldResult* resultOut,
btHashedSimplePairCache* childAlgorithmsCache,
btPersistentManifold* sharedManifold)
: m_numOverlapPairs(0), m_compound0ColObjWrap(compound1ObjWrap), m_compound1ColObjWrap(compound0ObjWrap), m_dispatcher(dispatcher), m_dispatchInfo(dispatchInfo), m_resultOut(resultOut), m_childCollisionAlgorithmCache(childAlgorithmsCache), m_sharedManifold(sharedManifold)
btManifoldResult* m_resultOut;
class btHashedSimplePairCache* m_childCollisionAlgorithmCache;
btPersistentManifold* m_sharedManifold;
btCompoundCompoundLeafCallback (const btCollisionObjectWrapper* compound1ObjWrap,
const btCollisionObjectWrapper* compound0ObjWrap,
btDispatcher* dispatcher,
const btDispatcherInfo& dispatchInfo,
btManifoldResult* resultOut,
btHashedSimplePairCache* childAlgorithmsCache,
btPersistentManifold* sharedManifold)
:m_numOverlapPairs(0),m_compound0ColObjWrap(compound1ObjWrap),m_compound1ColObjWrap(compound0ObjWrap),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
m_childCollisionAlgorithmCache(childAlgorithmsCache),
m_sharedManifold(sharedManifold)
{
}
void Process(const btDbvtNode* leaf0, const btDbvtNode* leaf1)
void Process(const btDbvtNode* leaf0,const btDbvtNode* leaf1)
{
BT_PROFILE("btCompoundCompoundLeafCallback::Process");
m_numOverlapPairs++;
int childIndex0 = leaf0->dataAsInt;
int childIndex1 = leaf1->dataAsInt;
btAssert(childIndex0>=0);
btAssert(childIndex1>=0);
btAssert(childIndex0 >= 0);
btAssert(childIndex1 >= 0);
const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(m_compound0ColObjWrap->getCollisionShape());
btAssert(childIndex0 < compoundShape0->getNumChildShapes());
btAssert(childIndex0<compoundShape0->getNumChildShapes());
const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(m_compound1ColObjWrap->getCollisionShape());
btAssert(childIndex1 < compoundShape1->getNumChildShapes());
btAssert(childIndex1<compoundShape1->getNumChildShapes());
const btCollisionShape* childShape0 = compoundShape0->getChildShape(childIndex0);
const btCollisionShape* childShape1 = compoundShape1->getChildShape(childIndex1);
//backup
btTransform orgTrans0 = m_compound0ColObjWrap->getWorldTransform();
btTransform orgTrans0 = m_compound0ColObjWrap->getWorldTransform();
const btTransform& childTrans0 = compoundShape0->getChildTransform(childIndex0);
btTransform newChildWorldTrans0 = orgTrans0 * childTrans0;
btTransform orgTrans1 = m_compound1ColObjWrap->getWorldTransform();
btTransform newChildWorldTrans0 = orgTrans0*childTrans0 ;
btTransform orgTrans1 = m_compound1ColObjWrap->getWorldTransform();
const btTransform& childTrans1 = compoundShape1->getChildTransform(childIndex1);
btTransform newChildWorldTrans1 = orgTrans1 * childTrans1;
btTransform newChildWorldTrans1 = orgTrans1*childTrans1 ;
//perform an AABB check first
btVector3 aabbMin0, aabbMax0, aabbMin1, aabbMax1;
childShape0->getAabb(newChildWorldTrans0, aabbMin0, aabbMax0);
childShape1->getAabb(newChildWorldTrans1, aabbMin1, aabbMax1);
btVector3 thresholdVec(m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold);
aabbMin0 -= thresholdVec;
aabbMax0 += thresholdVec;
btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
childShape0->getAabb(newChildWorldTrans0,aabbMin0,aabbMax0);
childShape1->getAabb(newChildWorldTrans1,aabbMin1,aabbMax1);
if (gCompoundCompoundChildShapePairCallback)
{
if (!gCompoundCompoundChildShapePairCallback(childShape0, childShape1))
if (!gCompoundCompoundChildShapePairCallback(childShape0,childShape1))
return;
}
if (TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
{
btCollisionObjectWrapper compoundWrap0(this->m_compound0ColObjWrap, childShape0, m_compound0ColObjWrap->getCollisionObject(), newChildWorldTrans0, -1, childIndex0);
btCollisionObjectWrapper compoundWrap1(this->m_compound1ColObjWrap, childShape1, m_compound1ColObjWrap->getCollisionObject(), newChildWorldTrans1, -1, childIndex1);
btCollisionObjectWrapper compoundWrap0(this->m_compound0ColObjWrap,childShape0, m_compound0ColObjWrap->getCollisionObject(),newChildWorldTrans0,-1,childIndex0);
btCollisionObjectWrapper compoundWrap1(this->m_compound1ColObjWrap,childShape1,m_compound1ColObjWrap->getCollisionObject(),newChildWorldTrans1,-1,childIndex1);
btSimplePair* pair = m_childCollisionAlgorithmCache->findPair(childIndex0,childIndex1);
btSimplePair* pair = m_childCollisionAlgorithmCache->findPair(childIndex0, childIndex1);
bool removePair = false;
btCollisionAlgorithm* colAlgo = 0;
if (m_resultOut->m_closestPointDistanceThreshold > 0)
if (pair)
{
colAlgo = m_dispatcher->findAlgorithm(&compoundWrap0, &compoundWrap1, 0, BT_CLOSEST_POINT_ALGORITHMS);
removePair = true;
}
else
colAlgo = (btCollisionAlgorithm*)pair->m_userPointer;
} else
{
if (pair)
{
colAlgo = (btCollisionAlgorithm*)pair->m_userPointer;
}
else
{
colAlgo = m_dispatcher->findAlgorithm(&compoundWrap0, &compoundWrap1, m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS);
pair = m_childCollisionAlgorithmCache->addOverlappingPair(childIndex0, childIndex1);
btAssert(pair);
pair->m_userPointer = colAlgo;
}
colAlgo = m_dispatcher->findAlgorithm(&compoundWrap0,&compoundWrap1,m_sharedManifold);
pair = m_childCollisionAlgorithmCache->addOverlappingPair(childIndex0,childIndex1);
btAssert(pair);
pair->m_userPointer = colAlgo;
}
btAssert(colAlgo);
const btCollisionObjectWrapper* tmpWrap0 = 0;
const btCollisionObjectWrapper* tmpWrap1 = 0;
@@ -195,100 +198,94 @@ struct btCompoundCompoundLeafCallback : btDbvt::ICollide
m_resultOut->setBody0Wrap(&compoundWrap0);
m_resultOut->setBody1Wrap(&compoundWrap1);
m_resultOut->setShapeIdentifiersA(-1, childIndex0);
m_resultOut->setShapeIdentifiersB(-1, childIndex1);
m_resultOut->setShapeIdentifiersA(-1,childIndex0);
m_resultOut->setShapeIdentifiersB(-1,childIndex1);
colAlgo->processCollision(&compoundWrap0, &compoundWrap1, m_dispatchInfo, m_resultOut);
colAlgo->processCollision(&compoundWrap0,&compoundWrap1,m_dispatchInfo,m_resultOut);
m_resultOut->setBody0Wrap(tmpWrap0);
m_resultOut->setBody1Wrap(tmpWrap1);
if (removePair)
{
colAlgo->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(colAlgo);
}
}
}
};
static DBVT_INLINE bool MyIntersect(const btDbvtAabbMm& a,
const btDbvtAabbMm& b, const btTransform& xform, btScalar distanceThreshold)
static DBVT_INLINE bool MyIntersect( const btDbvtAabbMm& a,
const btDbvtAabbMm& b, const btTransform& xform)
{
btVector3 newmin, newmax;
btTransformAabb(b.Mins(), b.Maxs(), 0.f, xform, newmin, newmax);
newmin -= btVector3(distanceThreshold, distanceThreshold, distanceThreshold);
newmax += btVector3(distanceThreshold, distanceThreshold, distanceThreshold);
btDbvtAabbMm newb = btDbvtAabbMm::FromMM(newmin, newmax);
return Intersect(a, newb);
btVector3 newmin,newmax;
btTransformAabb(b.Mins(),b.Maxs(),0.f,xform,newmin,newmax);
btDbvtAabbMm newb = btDbvtAabbMm::FromMM(newmin,newmax);
return Intersect(a,newb);
}
static inline void MycollideTT(const btDbvtNode* root0,
const btDbvtNode* root1,
const btTransform& xform,
btCompoundCompoundLeafCallback* callback, btScalar distanceThreshold)
static inline void MycollideTT( const btDbvtNode* root0,
const btDbvtNode* root1,
const btTransform& xform,
btCompoundCompoundLeafCallback* callback)
{
if (root0 && root1)
{
int depth = 1;
int treshold = btDbvt::DOUBLE_STACKSIZE - 4;
btAlignedObjectArray<btDbvt::sStkNN> stkStack;
#ifdef USE_LOCAL_STACK
ATTRIBUTE_ALIGNED16(btDbvt::sStkNN localStack[btDbvt::DOUBLE_STACKSIZE]);
stkStack.initializeFromBuffer(&localStack, btDbvt::DOUBLE_STACKSIZE, btDbvt::DOUBLE_STACKSIZE);
#else
stkStack.resize(btDbvt::DOUBLE_STACKSIZE);
#endif
stkStack[0] = btDbvt::sStkNN(root0, root1);
do
if(root0&&root1)
{
btDbvt::sStkNN p = stkStack[--depth];
if (MyIntersect(p.a->volume, p.b->volume, xform, distanceThreshold))
{
if (depth > treshold)
int depth=1;
int treshold=btDbvt::DOUBLE_STACKSIZE-4;
btAlignedObjectArray<btDbvt::sStkNN> stkStack;
stkStack.resize(btDbvt::DOUBLE_STACKSIZE);
stkStack[0]=btDbvt::sStkNN(root0,root1);
do {
btDbvt::sStkNN p=stkStack[--depth];
if(MyIntersect(p.a->volume,p.b->volume,xform))
{
stkStack.resize(stkStack.size() * 2);
treshold = stkStack.size() - 4;
}
if (p.a->isinternal())
{
if (p.b->isinternal())
if(depth>treshold)
{
stkStack[depth++] = btDbvt::sStkNN(p.a->childs[0], p.b->childs[0]);
stkStack[depth++] = btDbvt::sStkNN(p.a->childs[1], p.b->childs[0]);
stkStack[depth++] = btDbvt::sStkNN(p.a->childs[0], p.b->childs[1]);
stkStack[depth++] = btDbvt::sStkNN(p.a->childs[1], p.b->childs[1]);
stkStack.resize(stkStack.size()*2);
treshold=stkStack.size()-4;
}
if(p.a->isinternal())
{
if(p.b->isinternal())
{
stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b->childs[0]);
stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b->childs[0]);
stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b->childs[1]);
stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b->childs[1]);
}
else
{
stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b);
stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b);
}
}
else
{
stkStack[depth++] = btDbvt::sStkNN(p.a->childs[0], p.b);
stkStack[depth++] = btDbvt::sStkNN(p.a->childs[1], p.b);
if(p.b->isinternal())
{
stkStack[depth++]=btDbvt::sStkNN(p.a,p.b->childs[0]);
stkStack[depth++]=btDbvt::sStkNN(p.a,p.b->childs[1]);
}
else
{
callback->Process(p.a,p.b);
}
}
}
else
{
if (p.b->isinternal())
{
stkStack[depth++] = btDbvt::sStkNN(p.a, p.b->childs[0]);
stkStack[depth++] = btDbvt::sStkNN(p.a, p.b->childs[1]);
}
else
{
callback->Process(p.a, p.b);
}
}
}
} while (depth);
}
} while(depth);
}
}
void btCompoundCompoundCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btCompoundCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
const btCollisionObjectWrapper* col0ObjWrap = body0Wrap;
const btCollisionObjectWrapper* col1ObjWrap = body1Wrap;
btAssert(col0ObjWrap->getCollisionShape()->isCompound());
btAssert(col1ObjWrap->getCollisionShape()->isCompound());
const btCollisionObjectWrapper* col0ObjWrap = body0Wrap;
const btCollisionObjectWrapper* col1ObjWrap= body1Wrap;
btAssert (col0ObjWrap->getCollisionShape()->isCompound());
btAssert (col1ObjWrap->getCollisionShape()->isCompound());
const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(col0ObjWrap->getCollisionShape());
const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(col1ObjWrap->getCollisionShape());
@@ -296,7 +293,7 @@ void btCompoundCompoundCollisionAlgorithm::processCollision(const btCollisionObj
const btDbvt* tree1 = compoundShape1->getDynamicAabbTree();
if (!tree0 || !tree1)
{
return btCompoundCollisionAlgorithm::processCollision(body0Wrap, body1Wrap, dispatchInfo, resultOut);
return btCompoundCollisionAlgorithm::processCollision(body0Wrap,body1Wrap,dispatchInfo,resultOut);
}
///btCompoundShape might have changed:
////make sure the internal child collision algorithm caches are still valid
@@ -306,26 +303,24 @@ void btCompoundCompoundCollisionAlgorithm::processCollision(const btCollisionObj
removeChildAlgorithms();
m_compoundShapeRevision0 = compoundShape0->getUpdateRevision();
m_compoundShapeRevision1 = compoundShape1->getUpdateRevision();
}
///we need to refresh all contact manifolds
///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep
///so we should add a 'refreshManifolds' in the btCollisionAlgorithm
{
int i;
btManifoldArray manifoldArray;
#ifdef USE_LOCAL_STACK
btPersistentManifold localManifolds[4];
manifoldArray.initializeFromBuffer(&localManifolds, 0, 4);
#endif
btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
for (i = 0; i < pairs.size(); i++)
for (i=0;i<pairs.size();i++)
{
if (pairs[i].m_userPointer)
{
btCollisionAlgorithm* algo = (btCollisionAlgorithm*)pairs[i].m_userPointer;
btCollisionAlgorithm* algo = (btCollisionAlgorithm*) pairs[i].m_userPointer;
algo->getAllContactManifolds(manifoldArray);
for (int m = 0; m < manifoldArray.size(); m++)
for (int m=0;m<manifoldArray.size();m++)
{
if (manifoldArray[m]->getNumContacts())
{
@@ -339,75 +334,93 @@ void btCompoundCompoundCollisionAlgorithm::processCollision(const btCollisionObj
}
}
btCompoundCompoundLeafCallback callback(col0ObjWrap, col1ObjWrap, this->m_dispatcher, dispatchInfo, resultOut, this->m_childCollisionAlgorithmCache, m_sharedManifold);
const btTransform xform = col0ObjWrap->getWorldTransform().inverse() * col1ObjWrap->getWorldTransform();
MycollideTT(tree0->m_root, tree1->m_root, xform, &callback, resultOut->m_closestPointDistanceThreshold);
btCompoundCompoundLeafCallback callback(col0ObjWrap,col1ObjWrap,this->m_dispatcher,dispatchInfo,resultOut,this->m_childCollisionAlgorithmCache,m_sharedManifold);
const btTransform xform=col0ObjWrap->getWorldTransform().inverse()*col1ObjWrap->getWorldTransform();
MycollideTT(tree0->m_root,tree1->m_root,xform,&callback);
//printf("#compound-compound child/leaf overlap =%d \r",callback.m_numOverlapPairs);
//remove non-overlapping child pairs
{
btAssert(m_removePairs.size() == 0);
btAssert(m_removePairs.size()==0);
//iterate over all children, perform an AABB check inside ProcessChildShape
btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
int i;
btManifoldArray manifoldArray;
btManifoldArray manifoldArray;
btVector3 aabbMin0, aabbMax0, aabbMin1, aabbMax1;
for (i = 0; i < pairs.size(); i++)
btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
for (i=0;i<pairs.size();i++)
{
if (pairs[i].m_userPointer)
{
btCollisionAlgorithm* algo = (btCollisionAlgorithm*)pairs[i].m_userPointer;
{
btTransform orgTrans0;
const btCollisionShape* childShape0 = 0;
btTransform newChildWorldTrans0;
btTransform newChildWorldTrans0;
btTransform orgInterpolationTrans0;
childShape0 = compoundShape0->getChildShape(pairs[i].m_indexA);
orgTrans0 = col0ObjWrap->getWorldTransform();
orgInterpolationTrans0 = col0ObjWrap->getWorldTransform();
const btTransform& childTrans0 = compoundShape0->getChildTransform(pairs[i].m_indexA);
newChildWorldTrans0 = col0ObjWrap->getWorldTransform() * childTrans0;
childShape0->getAabb(newChildWorldTrans0, aabbMin0, aabbMax0);
newChildWorldTrans0 = orgTrans0*childTrans0 ;
childShape0->getAabb(newChildWorldTrans0,aabbMin0,aabbMax0);
}
btVector3 thresholdVec(resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold);
aabbMin0 -= thresholdVec;
aabbMax0 += thresholdVec;
{
btTransform orgInterpolationTrans1;
const btCollisionShape* childShape1 = 0;
btTransform newChildWorldTrans1;
btTransform orgTrans1;
btTransform newChildWorldTrans1;
childShape1 = compoundShape1->getChildShape(pairs[i].m_indexB);
orgTrans1 = col1ObjWrap->getWorldTransform();
orgInterpolationTrans1 = col1ObjWrap->getWorldTransform();
const btTransform& childTrans1 = compoundShape1->getChildTransform(pairs[i].m_indexB);
newChildWorldTrans1 = col1ObjWrap->getWorldTransform() * childTrans1;
childShape1->getAabb(newChildWorldTrans1, aabbMin1, aabbMax1);
newChildWorldTrans1 = orgTrans1*childTrans1 ;
childShape1->getAabb(newChildWorldTrans1,aabbMin1,aabbMax1);
}
aabbMin1 -= thresholdVec;
aabbMax1 += thresholdVec;
if (!TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
{
algo->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(algo);
m_removePairs.push_back(btSimplePair(pairs[i].m_indexA, pairs[i].m_indexB));
m_removePairs.push_back(btSimplePair(pairs[i].m_indexA,pairs[i].m_indexB));
}
}
}
for (int i = 0; i < m_removePairs.size(); i++)
for (int i=0;i<m_removePairs.size();i++)
{
m_childCollisionAlgorithmCache->removeOverlappingPair(m_removePairs[i].m_indexA, m_removePairs[i].m_indexB);
m_childCollisionAlgorithmCache->removeOverlappingPair(m_removePairs[i].m_indexA,m_removePairs[i].m_indexB);
}
m_removePairs.clear();
}
}
btScalar btCompoundCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
btScalar btCompoundCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
btAssert(0);
return 0.f;
}

View File

@@ -33,50 +33,57 @@ class btDispatcher;
class btCollisionObject;
class btCollisionShape;
typedef bool (*btShapePairCallback)(const btCollisionShape* pShape0, const btCollisionShape* pShape1);
extern btShapePairCallback gCompoundCompoundChildShapePairCallback;
/// btCompoundCompoundCollisionAlgorithm supports collision between two btCompoundCollisionShape shapes
class btCompoundCompoundCollisionAlgorithm : public btCompoundCollisionAlgorithm
class btCompoundCompoundCollisionAlgorithm : public btCompoundCollisionAlgorithm
{
class btHashedSimplePairCache* m_childCollisionAlgorithmCache;
class btHashedSimplePairCache* m_childCollisionAlgorithmCache;
btSimplePairArray m_removePairs;
int m_compoundShapeRevision0; //to keep track of changes, so that childAlgorithm array can be updated
int m_compoundShapeRevision1;
void removeChildAlgorithms();
// void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
int m_compoundShapeRevision0;//to keep track of changes, so that childAlgorithm array can be updated
int m_compoundShapeRevision1;
void removeChildAlgorithms();
// void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
public:
btCompoundCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
btCompoundCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
virtual ~btCompoundCompoundCollisionAlgorithm();
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray);
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
struct CreateFunc : public btCollisionAlgorithmCreateFunc
virtual void getAllContactManifolds(btManifoldArray& manifoldArray);
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCompoundCollisionAlgorithm));
return new (mem) btCompoundCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, false);
return new(mem) btCompoundCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,false);
}
};
struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc
struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCompoundCollisionAlgorithm));
return new (mem) btCompoundCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, true);
return new(mem) btCompoundCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,true);
}
};
};
#endif //BT_COMPOUND_COMPOUND_COLLISION_ALGORITHM_H
#endif //BT_COMPOUND_COMPOUND_COLLISION_ALGORITHM_H

View File

@@ -22,6 +22,7 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
@@ -33,6 +34,8 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
@@ -42,28 +45,31 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
btConvex2dConvex2dAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
btConvex2dConvex2dAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
{
m_simplexSolver = simplexSolver;
m_pdSolver = pdSolver;
}
btConvex2dConvex2dAlgorithm::CreateFunc::~CreateFunc()
{
btConvex2dConvex2dAlgorithm::CreateFunc::~CreateFunc()
{
}
btConvex2dConvex2dAlgorithm::btConvex2dConvex2dAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int /* numPerturbationIterations */, int /* minimumPointsPerturbationThreshold */)
: btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
m_simplexSolver(simplexSolver),
m_pdSolver(pdSolver),
m_ownManifold(false),
m_manifoldPtr(mf),
m_lowLevelOfDetail(false)
btConvex2dConvex2dAlgorithm::btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int /* numPerturbationIterations */, int /* minimumPointsPerturbationThreshold */)
: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
m_simplexSolver(simplexSolver),
m_pdSolver(pdSolver),
m_ownManifold (false),
m_manifoldPtr(mf),
m_lowLevelOfDetail(false)
{
(void)body0Wrap;
(void)body1Wrap;
}
btConvex2dConvex2dAlgorithm::~btConvex2dConvex2dAlgorithm()
{
if (m_ownManifold)
@@ -73,22 +79,26 @@ btConvex2dConvex2dAlgorithm::~btConvex2dConvex2dAlgorithm()
}
}
void btConvex2dConvex2dAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
void btConvex2dConvex2dAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
{
m_lowLevelOfDetail = useLowLevel;
}
extern btScalar gContactBreakingThreshold;
//
// Convex-Convex collision algorithm
//
void btConvex2dConvex2dAlgorithm ::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btConvex2dConvex2dAlgorithm ::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
{
//swapped?
m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
m_ownManifold = true;
}
resultOut->setPersistentManifold(m_manifoldPtr);
@@ -96,41 +106,49 @@ void btConvex2dConvex2dAlgorithm ::processCollision(const btCollisionObjectWrapp
//comment-out next line to test multi-contact generation
//resultOut->getPersistentManifold()->clearManifold();
const btConvexShape* min0 = static_cast<const btConvexShape*>(body0Wrap->getCollisionShape());
const btConvexShape* min1 = static_cast<const btConvexShape*>(body1Wrap->getCollisionShape());
btVector3 normalOnB;
btVector3 pointOnBWorld;
btVector3 normalOnB;
btVector3 pointOnBWorld;
{
btGjkPairDetector::ClosestPointInput input;
btGjkPairDetector gjkPairDetector(min0, min1, m_simplexSolver, m_pdSolver);
btGjkPairDetector gjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver);
//TODO: if (dispatchInfo.m_useContinuous)
gjkPairDetector.setMinkowskiA(min0);
gjkPairDetector.setMinkowskiB(min1);
{
input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold();
input.m_maximumDistanceSquared *= input.m_maximumDistanceSquared;
input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
}
input.m_transformA = body0Wrap->getWorldTransform();
input.m_transformB = body1Wrap->getWorldTransform();
gjkPairDetector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw);
gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
btVector3 v0, v1;
btVector3 v0,v1;
btVector3 sepNormalWorldSpace;
}
if (m_ownManifold)
{
resultOut->refreshContactPoints();
}
}
btScalar btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
btScalar btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
@@ -140,6 +158,7 @@ btScalar btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* c
///col0->m_worldTransform,
btScalar resultFraction = btScalar(1.);
btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2();
btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2();
@@ -147,65 +166,77 @@ btScalar btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* c
squareMot1 < col1->getCcdSquareMotionThreshold())
return resultFraction;
//An adhoc way of testing the Continuous Collision Detection algorithms
//One object is approximated as a sphere, to simplify things
//Starting in penetration should report no time of impact
//For proper CCD, better accuracy and handling of 'allowed' penetration should be added
//also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies)
/// Convex0 against sphere for Convex1
{
btConvexShape* convex0 = static_cast<btConvexShape*>(col0->getCollisionShape());
btSphereShape sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
btSphereShape sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
btConvexCast::CastResult result;
btVoronoiSimplexSolver voronoiSimplex;
//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
///Simplification, one object is simplified as a sphere
btGjkConvexCast ccd1(convex0, &sphere1, &voronoiSimplex);
btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex);
//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
if (ccd1.calcTimeOfImpact(col0->getWorldTransform(), col0->getInterpolationWorldTransform(),
col1->getWorldTransform(), col1->getInterpolationWorldTransform(), result))
if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
{
//store result.m_fraction in both bodies
if (col0->getHitFraction() > result.m_fraction)
col0->setHitFraction(result.m_fraction);
if (col0->getHitFraction()> result.m_fraction)
col0->setHitFraction( result.m_fraction );
if (col1->getHitFraction() > result.m_fraction)
col1->setHitFraction(result.m_fraction);
col1->setHitFraction( result.m_fraction);
if (resultFraction > result.m_fraction)
resultFraction = result.m_fraction;
}
}
/// Sphere (for convex0) against Convex1
{
btConvexShape* convex1 = static_cast<btConvexShape*>(col1->getCollisionShape());
btSphereShape sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
btSphereShape sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
btConvexCast::CastResult result;
btVoronoiSimplexSolver voronoiSimplex;
//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
///Simplification, one object is simplified as a sphere
btGjkConvexCast ccd1(&sphere0, convex1, &voronoiSimplex);
btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex);
//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
if (ccd1.calcTimeOfImpact(col0->getWorldTransform(), col0->getInterpolationWorldTransform(),
col1->getWorldTransform(), col1->getInterpolationWorldTransform(), result))
if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
{
//store result.m_fraction in both bodies
if (col0->getHitFraction() > result.m_fraction)
col0->setHitFraction(result.m_fraction);
if (col0->getHitFraction() > result.m_fraction)
col0->setHitFraction( result.m_fraction);
if (col1->getHitFraction() > result.m_fraction)
col1->setHitFraction(result.m_fraction);
col1->setHitFraction( result.m_fraction);
if (resultFraction > result.m_fraction)
resultFraction = result.m_fraction;
}
}
return resultFraction;
}

View File

@@ -23,61 +23,70 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
class btConvexPenetrationDepthSolver;
///The convex2dConvex2dAlgorithm collision algorithm support 2d collision detection for btConvex2dShape
///Currently it requires the btMinkowskiPenetrationDepthSolver, it has support for 2d penetration depth computation
class btConvex2dConvex2dAlgorithm : public btActivatingCollisionAlgorithm
{
btSimplexSolverInterface* m_simplexSolver;
btSimplexSolverInterface* m_simplexSolver;
btConvexPenetrationDepthSolver* m_pdSolver;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_lowLevelOfDetail;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_lowLevelOfDetail;
public:
btConvex2dConvex2dAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
virtual ~btConvex2dConvex2dAlgorithm();
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
///should we use m_ownManifold to avoid adding duplicates?
if (m_manifoldPtr && m_ownManifold)
manifoldArray.push_back(m_manifoldPtr);
}
void setLowLevelOfDetail(bool useLowLevel);
const btPersistentManifold* getManifold()
void setLowLevelOfDetail(bool useLowLevel);
const btPersistentManifold* getManifold()
{
return m_manifoldPtr;
}
struct CreateFunc : public btCollisionAlgorithmCreateFunc
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
btConvexPenetrationDepthSolver* m_pdSolver;
btSimplexSolverInterface* m_simplexSolver;
btConvexPenetrationDepthSolver* m_pdSolver;
btSimplexSolverInterface* m_simplexSolver;
int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
virtual ~CreateFunc();
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvex2dConvex2dAlgorithm));
return new (mem) btConvex2dConvex2dAlgorithm(ci.m_manifold, ci, body0Wrap, body1Wrap, m_simplexSolver, m_pdSolver, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
return new(mem) btConvex2dConvex2dAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
}
};
};
#endif //BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H
#endif //BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H

View File

@@ -13,8 +13,8 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "btConvexConcaveCollisionAlgorithm.h"
#include "LinearMath/btQuickprof.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
@@ -26,12 +26,11 @@ subject to the following restrictions:
#include "LinearMath/btIDebugDraw.h"
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
#include "BulletCollision/CollisionShapes/btSdfCollisionShape.h"
btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped)
: btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
m_btConvexTriangleCallback(ci.m_dispatcher1, body0Wrap, body1Wrap, isSwapped),
m_isSwapped(isSwapped)
btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped)
: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
m_isSwapped(isSwapped),
m_btConvexTriangleCallback(ci.m_dispatcher1,body0Wrap,body1Wrap,isSwapped)
{
}
@@ -39,7 +38,7 @@ btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm()
{
}
void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_btConvexTriangleCallback.m_manifoldPtr)
{
@@ -47,46 +46,55 @@ void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray&
}
}
btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped) : m_dispatcher(dispatcher),
m_dispatchInfoPtr(0)
btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped):
m_dispatcher(dispatcher),
m_dispatchInfoPtr(0)
{
m_convexBodyWrap = isSwapped ? body1Wrap : body0Wrap;
m_triBodyWrap = isSwapped ? body0Wrap : body1Wrap;
m_convexBodyWrap = isSwapped? body1Wrap:body0Wrap;
m_triBodyWrap = isSwapped? body0Wrap:body1Wrap;
//
// create the manifold from the dispatcher 'manifold pool'
//
m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBodyWrap->getCollisionObject(),m_triBodyWrap->getCollisionObject());
//
// create the manifold from the dispatcher 'manifold pool'
//
m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBodyWrap->getCollisionObject(), m_triBodyWrap->getCollisionObject());
clearCache();
clearCache();
}
btConvexTriangleCallback::~btConvexTriangleCallback()
{
clearCache();
m_dispatcher->releaseManifold(m_manifoldPtr);
m_dispatcher->releaseManifold( m_manifoldPtr );
}
void btConvexTriangleCallback::clearCache()
void btConvexTriangleCallback::clearCache()
{
m_dispatcher->clearManifold(m_manifoldPtr);
}
void btConvexTriangleCallback::processTriangle(btVector3* triangle, int partId, int triangleIndex)
void btConvexTriangleCallback::processTriangle(btVector3* triangle,int
partId, int triangleIndex)
{
BT_PROFILE("btConvexTriangleCallback::processTriangle");
if (!TestTriangleAgainstAabb2(triangle, m_aabbMin, m_aabbMax))
{
return;
}
//just for debugging purposes
//printf("triangle %d",m_triangleCount++);
//just for debugging purposes
//printf("triangle %d",m_triangleCount++);
btCollisionAlgorithmConstructionInfo ci;
ci.m_dispatcher1 = m_dispatcher;
#if 0
///debug drawing of the overlapping triangles
@@ -100,55 +108,52 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle, int partId,
m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
}
#endif
if (m_convexBodyWrap->getCollisionShape()->isConvex())
{
btTriangleShape tm(triangle[0], triangle[1], triangle[2]);
btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
tm.setMargin(m_collisionMarginTriangle);
btCollisionObjectWrapper triObWrap(m_triBodyWrap,&tm,m_triBodyWrap->getCollisionObject(),m_triBodyWrap->getWorldTransform(),partId,triangleIndex);//correct transform?
btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap,&triObWrap,m_manifoldPtr);
btCollisionObjectWrapper triObWrap(m_triBodyWrap, &tm, m_triBodyWrap->getCollisionObject(), m_triBodyWrap->getWorldTransform(), partId, triangleIndex); //correct transform?
btCollisionAlgorithm* colAlgo = 0;
if (m_resultOut->m_closestPointDistanceThreshold > 0)
{
colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap, &triObWrap, 0, BT_CLOSEST_POINT_ALGORITHMS);
}
else
{
colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap, &triObWrap, m_manifoldPtr, BT_CONTACT_POINT_ALGORITHMS);
}
const btCollisionObjectWrapper* tmpWrap = 0;
if (m_resultOut->getBody0Internal() == m_triBodyWrap->getCollisionObject())
{
tmpWrap = m_resultOut->getBody0Wrap();
m_resultOut->setBody0Wrap(&triObWrap);
m_resultOut->setShapeIdentifiersA(partId, triangleIndex);
m_resultOut->setShapeIdentifiersA(partId,triangleIndex);
}
else
{
tmpWrap = m_resultOut->getBody1Wrap();
m_resultOut->setBody1Wrap(&triObWrap);
m_resultOut->setShapeIdentifiersB(partId, triangleIndex);
m_resultOut->setShapeIdentifiersB(partId,triangleIndex);
}
colAlgo->processCollision(m_convexBodyWrap, &triObWrap, *m_dispatchInfoPtr, m_resultOut);
colAlgo->processCollision(m_convexBodyWrap,&triObWrap,*m_dispatchInfoPtr,m_resultOut);
if (m_resultOut->getBody0Internal() == m_triBodyWrap->getCollisionObject())
{
m_resultOut->setBody0Wrap(tmpWrap);
}
else
} else
{
m_resultOut->setBody1Wrap(tmpWrap);
}
colAlgo->~btCollisionAlgorithm();
ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
}
}
void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle, const btDispatcherInfo& dispatchInfo, const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut)
void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut)
{
m_convexBodyWrap = convexBodyWrap;
m_triBodyWrap = triBodyWrap;
@@ -162,120 +167,65 @@ void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTr
convexInTriangleSpace = m_triBodyWrap->getWorldTransform().inverse() * m_convexBodyWrap->getWorldTransform();
const btCollisionShape* convexShape = static_cast<const btCollisionShape*>(m_convexBodyWrap->getCollisionShape());
//CollisionShape* triangleShape = static_cast<btCollisionShape*>(triBody->m_collisionShape);
convexShape->getAabb(convexInTriangleSpace, m_aabbMin, m_aabbMax);
btScalar extraMargin = collisionMarginTriangle + resultOut->m_closestPointDistanceThreshold;
btVector3 extra(extraMargin, extraMargin, extraMargin);
convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax);
btScalar extraMargin = collisionMarginTriangle;
btVector3 extra(extraMargin,extraMargin,extraMargin);
m_aabbMax += extra;
m_aabbMin -= extra;
}
void btConvexConcaveCollisionAlgorithm::clearCache()
{
m_btConvexTriangleCallback.clearCache();
}
void btConvexConcaveCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btConvexConcaveCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
BT_PROFILE("btConvexConcaveCollisionAlgorithm::processCollision");
const btCollisionObjectWrapper* convexBodyWrap = m_isSwapped ? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* triBodyWrap = m_isSwapped ? body0Wrap : body1Wrap;
if (triBodyWrap->getCollisionShape()->isConcave())
{
if (triBodyWrap->getCollisionShape()->getShapeType() == SDF_SHAPE_PROXYTYPE)
const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>( triBodyWrap->getCollisionShape());
if (convexBodyWrap->getCollisionShape()->isConvex())
{
btSdfCollisionShape* sdfShape = (btSdfCollisionShape*)triBodyWrap->getCollisionShape();
if (convexBodyWrap->getCollisionShape()->isConvex())
{
btConvexShape* convex = (btConvexShape*)convexBodyWrap->getCollisionShape();
btAlignedObjectArray<btVector3> queryVertices;
btScalar collisionMarginTriangle = concaveShape->getMargin();
resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,convexBodyWrap,triBodyWrap,resultOut);
if (convex->isPolyhedral())
{
btPolyhedralConvexShape* poly = (btPolyhedralConvexShape*)convex;
for (int v = 0; v < poly->getNumVertices(); v++)
{
btVector3 vtx;
poly->getVertex(v, vtx);
queryVertices.push_back(vtx);
}
}
btScalar maxDist = SIMD_EPSILON;
m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBodyWrap->getCollisionObject(),triBodyWrap->getCollisionObject());
if (convex->getShapeType() == SPHERE_SHAPE_PROXYTYPE)
{
queryVertices.push_back(btVector3(0, 0, 0));
btSphereShape* sphere = (btSphereShape*)convex;
maxDist = sphere->getRadius() + SIMD_EPSILON;
}
if (queryVertices.size())
{
resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
//m_btConvexTriangleCallback.m_manifoldPtr->clearManifold();
concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax());
resultOut->refreshContactPoints();
btPolyhedralConvexShape* poly = (btPolyhedralConvexShape*)convex;
for (int v = 0; v < queryVertices.size(); v++)
{
const btVector3& vtx = queryVertices[v];
btVector3 vtxWorldSpace = convexBodyWrap->getWorldTransform() * vtx;
btVector3 vtxInSdf = triBodyWrap->getWorldTransform().invXform(vtxWorldSpace);
btVector3 normalLocal;
btScalar dist;
if (sdfShape->queryPoint(vtxInSdf, dist, normalLocal))
{
if (dist <= maxDist)
{
normalLocal.safeNormalize();
btVector3 normal = triBodyWrap->getWorldTransform().getBasis() * normalLocal;
if (convex->getShapeType() == SPHERE_SHAPE_PROXYTYPE)
{
btSphereShape* sphere = (btSphereShape*)convex;
dist -= sphere->getRadius();
vtxWorldSpace -= sphere->getRadius() * normal;
}
resultOut->addContactPoint(normal, vtxWorldSpace - normal * dist, dist);
}
}
}
resultOut->refreshContactPoints();
}
}
}
else
{
const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>(triBodyWrap->getCollisionShape());
if (convexBodyWrap->getCollisionShape()->isConvex())
{
btScalar collisionMarginTriangle = concaveShape->getMargin();
resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle, dispatchInfo, convexBodyWrap, triBodyWrap, resultOut);
m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBodyWrap->getCollisionObject(), triBodyWrap->getCollisionObject());
concaveShape->processAllTriangles(&m_btConvexTriangleCallback, m_btConvexTriangleCallback.getAabbMin(), m_btConvexTriangleCallback.getAabbMax());
resultOut->refreshContactPoints();
m_btConvexTriangleCallback.clearWrapperData();
}
m_btConvexTriangleCallback.clearWrapperData();
}
}
}
btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
btCollisionObject* triBody = m_isSwapped ? body0 : body1;
//quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
//only perform CCD above a certain threshold, this prevents blocking on the long run
@@ -294,26 +244,27 @@ btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObj
btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
struct LocalTriangleSphereCastCallback : public btTriangleCallback
struct LocalTriangleSphereCastCallback : public btTriangleCallback
{
btTransform m_ccdSphereFromTrans;
btTransform m_ccdSphereToTrans;
btTransform m_meshTransform;
btTransform m_meshTransform;
btScalar m_ccdSphereRadius;
btScalar m_hitFraction;
btScalar m_ccdSphereRadius;
btScalar m_hitFraction;
LocalTriangleSphereCastCallback(const btTransform& from, const btTransform& to, btScalar ccdSphereRadius, btScalar hitFraction)
: m_ccdSphereFromTrans(from),
m_ccdSphereToTrans(to),
m_ccdSphereRadius(ccdSphereRadius),
m_hitFraction(hitFraction)
{
LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction)
:m_ccdSphereFromTrans(from),
m_ccdSphereToTrans(to),
m_ccdSphereRadius(ccdSphereRadius),
m_hitFraction(hitFraction)
{
}
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
{
BT_PROFILE("processTriangle");
(void)partId;
(void)triangleIndex;
//do a swept sphere for now
@@ -321,23 +272,29 @@ btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObj
ident.setIdentity();
btConvexCast::CastResult castResult;
castResult.m_fraction = m_hitFraction;
btSphereShape pointShape(m_ccdSphereRadius);
btTriangleShape triShape(triangle[0], triangle[1], triangle[2]);
btVoronoiSimplexSolver simplexSolver;
btSubsimplexConvexCast convexCaster(&pointShape, &triShape, &simplexSolver);
btSphereShape pointShape(m_ccdSphereRadius);
btTriangleShape triShape(triangle[0],triangle[1],triangle[2]);
btVoronoiSimplexSolver simplexSolver;
btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver);
//GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
//ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
//local space?
if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans, m_ccdSphereToTrans,
ident, ident, castResult))
if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans,
ident,ident,castResult))
{
if (m_hitFraction > castResult.m_fraction)
m_hitFraction = castResult.m_fraction;
}
}
};
if (triBody->getCollisionShape()->isConcave())
{
btVector3 rayAabbMin = convexFromLocal.getOrigin();
@@ -345,30 +302,33 @@ btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObj
btVector3 rayAabbMax = convexFromLocal.getOrigin();
rayAabbMax.setMax(convexToLocal.getOrigin());
btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
rayAabbMin -= btVector3(ccdRadius0, ccdRadius0, ccdRadius0);
rayAabbMax += btVector3(ccdRadius0, ccdRadius0, ccdRadius0);
rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
btScalar curHitFraction = btScalar(1.); //is this available?
LocalTriangleSphereCastCallback raycastCallback(convexFromLocal, convexToLocal,
convexbody->getCcdSweptSphereRadius(), curHitFraction);
btScalar curHitFraction = btScalar(1.); //is this available?
LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal,
convexbody->getCcdSweptSphereRadius(),curHitFraction);
raycastCallback.m_hitFraction = convexbody->getHitFraction();
btCollisionObject* concavebody = triBody;
btConcaveShape* triangleMesh = (btConcaveShape*)concavebody->getCollisionShape();
btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape();
if (triangleMesh)
{
triangleMesh->processAllTriangles(&raycastCallback, rayAabbMin, rayAabbMax);
triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax);
}
if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
{
convexbody->setHitFraction(raycastCallback.m_hitFraction);
convexbody->setHitFraction( raycastCallback.m_hitFraction);
return raycastCallback.m_hitFraction;
}
}
return btScalar(1.);
}

View File

@@ -26,40 +26,38 @@ class btDispatcher;
#include "btCollisionCreateFunc.h"
///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called.
ATTRIBUTE_ALIGNED16(class)
btConvexTriangleCallback : public btTriangleCallback
class btConvexTriangleCallback : public btTriangleCallback
{
btVector3 m_aabbMin;
btVector3 m_aabbMax;
const btCollisionObjectWrapper* m_convexBodyWrap;
const btCollisionObjectWrapper* m_triBodyWrap;
btVector3 m_aabbMin;
btVector3 m_aabbMax ;
btManifoldResult* m_resultOut;
btDispatcher* m_dispatcher;
btDispatcher* m_dispatcher;
const btDispatcherInfo* m_dispatchInfoPtr;
btScalar m_collisionMarginTriangle;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
int m_triangleCount;
btPersistentManifold* m_manifoldPtr;
int m_triangleCount;
btConvexTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
btPersistentManifold* m_manifoldPtr;
void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut);
btConvexTriangleCallback(btDispatcher * dispatcher, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
void setTimeStepAndCounters(btScalar collisionMarginTriangle, const btDispatcherInfo& dispatchInfo, const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut);
void clearWrapperData()
void clearWrapperData()
{
m_convexBodyWrap = 0;
m_triBodyWrap = 0;
}
virtual ~btConvexTriangleCallback();
virtual void processTriangle(btVector3 * triangle, int partId, int triangleIndex);
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
void clearCache();
SIMD_FORCE_INLINE const btVector3& getAabbMin() const
@@ -70,48 +68,54 @@ public:
{
return m_aabbMax;
}
};
/// btConvexConcaveCollisionAlgorithm supports collision between convex shapes and (concave) trianges meshes.
ATTRIBUTE_ALIGNED16(class)
btConvexConcaveCollisionAlgorithm : public btActivatingCollisionAlgorithm
class btConvexConcaveCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_isSwapped;
btConvexTriangleCallback m_btConvexTriangleCallback;
bool m_isSwapped;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btConvexConcaveCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
virtual ~btConvexConcaveCollisionAlgorithm();
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
btScalar calculateTimeOfImpact(btCollisionObject * body0, btCollisionObject * body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray & manifoldArray);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray);
void clearCache();
void clearCache();
struct CreateFunc : public btCollisionAlgorithmCreateFunc
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
return new (mem) btConvexConcaveCollisionAlgorithm(ci, body0Wrap, body1Wrap, false);
return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,false);
}
};
struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc
struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
return new (mem) btConvexConcaveCollisionAlgorithm(ci, body0Wrap, body1Wrap, true);
return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,true);
}
};
};
#endif //BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H
#endif //BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H

View File

@@ -23,8 +23,7 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "btCollisionCreateFunc.h"
#include "btCollisionDispatcher.h"
#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h"
#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
class btConvexPenetrationDepthSolver;
@@ -41,61 +40,69 @@ class btConvexPenetrationDepthSolver;
class btConvexConvexAlgorithm : public btActivatingCollisionAlgorithm
{
#ifdef USE_SEPDISTANCE_UTIL2
btConvexSeparatingDistanceUtil m_sepDistance;
btConvexSeparatingDistanceUtil m_sepDistance;
#endif
btSimplexSolverInterface* m_simplexSolver;
btConvexPenetrationDepthSolver* m_pdSolver;
btVertexArray worldVertsB1;
btVertexArray worldVertsB2;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_lowLevelOfDetail;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_lowLevelOfDetail;
int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
///cache separating vector to speedup collision detection
public:
btConvexConvexAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
virtual ~btConvexConvexAlgorithm();
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
///should we use m_ownManifold to avoid adding duplicates?
if (m_manifoldPtr && m_ownManifold)
manifoldArray.push_back(m_manifoldPtr);
}
void setLowLevelOfDetail(bool useLowLevel);
const btPersistentManifold* getManifold()
void setLowLevelOfDetail(bool useLowLevel);
const btPersistentManifold* getManifold()
{
return m_manifoldPtr;
}
struct CreateFunc : public btCollisionAlgorithmCreateFunc
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
btConvexPenetrationDepthSolver* m_pdSolver;
btConvexPenetrationDepthSolver* m_pdSolver;
btSimplexSolverInterface* m_simplexSolver;
int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
CreateFunc(btConvexPenetrationDepthSolver* pdSolver);
CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
virtual ~CreateFunc();
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm));
return new (mem) btConvexConvexAlgorithm(ci.m_manifold, ci, body0Wrap, body1Wrap, m_pdSolver, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
}
};
};
#endif //BT_CONVEX_CONVEX_ALGORITHM_H
#endif //BT_CONVEX_CONVEX_ALGORITHM_H

View File

@@ -23,24 +23,25 @@ subject to the following restrictions:
//#include <stdio.h>
btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, bool isSwapped, int numPerturbationIterations, int minimumPointsPerturbationThreshold)
: btCollisionAlgorithm(ci),
m_ownManifold(false),
m_manifoldPtr(mf),
m_isSwapped(isSwapped),
m_numPerturbationIterations(numPerturbationIterations),
m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold)
: btCollisionAlgorithm(ci),
m_ownManifold(false),
m_manifoldPtr(mf),
m_isSwapped(isSwapped),
m_numPerturbationIterations(numPerturbationIterations),
m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
{
const btCollisionObjectWrapper* convexObjWrap = m_isSwapped ? col1Wrap : col0Wrap;
const btCollisionObjectWrapper* planeObjWrap = m_isSwapped ? col0Wrap : col1Wrap;
const btCollisionObjectWrapper* convexObjWrap = m_isSwapped? col1Wrap : col0Wrap;
const btCollisionObjectWrapper* planeObjWrap = m_isSwapped? col0Wrap : col1Wrap;
if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObjWrap->getCollisionObject(), planeObjWrap->getCollisionObject()))
if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObjWrap->getCollisionObject(),planeObjWrap->getCollisionObject()))
{
m_manifoldPtr = m_dispatcher->getNewManifold(convexObjWrap->getCollisionObject(), planeObjWrap->getCollisionObject());
m_manifoldPtr = m_dispatcher->getNewManifold(convexObjWrap->getCollisionObject(),planeObjWrap->getCollisionObject());
m_ownManifold = true;
}
}
btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm()
{
if (m_ownManifold)
@@ -50,32 +51,32 @@ btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm()
}
}
void btConvexPlaneCollisionAlgorithm::collideSingleContact(const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btConvexPlaneCollisionAlgorithm::collideSingleContact (const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
const btCollisionObjectWrapper* convexObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* planeObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
const btCollisionObjectWrapper* convexObjWrap = m_isSwapped? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* planeObjWrap = m_isSwapped? body0Wrap: body1Wrap;
btConvexShape* convexShape = (btConvexShape*)convexObjWrap->getCollisionShape();
btStaticPlaneShape* planeShape = (btStaticPlaneShape*)planeObjWrap->getCollisionShape();
btConvexShape* convexShape = (btConvexShape*) convexObjWrap->getCollisionShape();
btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObjWrap->getCollisionShape();
bool hasCollision = false;
bool hasCollision = false;
const btVector3& planeNormal = planeShape->getPlaneNormal();
const btScalar& planeConstant = planeShape->getPlaneConstant();
btTransform convexWorldTransform = convexObjWrap->getWorldTransform();
btTransform convexInPlaneTrans;
convexInPlaneTrans = planeObjWrap->getWorldTransform().inverse() * convexWorldTransform;
convexInPlaneTrans= planeObjWrap->getWorldTransform().inverse() * convexWorldTransform;
//now perturbe the convex-world transform
convexWorldTransform.getBasis() *= btMatrix3x3(perturbeRot);
convexWorldTransform.getBasis()*=btMatrix3x3(perturbeRot);
btTransform planeInConvex;
planeInConvex = convexWorldTransform.inverse() * planeObjWrap->getWorldTransform();
btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis() * -planeNormal);
planeInConvex= convexWorldTransform.inverse() * planeObjWrap->getWorldTransform();
btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
btVector3 vtxInPlane = convexInPlaneTrans(vtx);
btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
btVector3 vtxInPlaneProjected = vtxInPlane - distance * planeNormal;
btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
btVector3 vtxInPlaneWorld = planeObjWrap->getWorldTransform() * vtxInPlaneProjected;
hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold();
@@ -85,69 +86,70 @@ void btConvexPlaneCollisionAlgorithm::collideSingleContact(const btQuaternion& p
/// report a contact. internally this will be kept persistent, and contact reduction is done
btVector3 normalOnSurfaceB = planeObjWrap->getWorldTransform().getBasis() * planeNormal;
btVector3 pOnB = vtxInPlaneWorld;
resultOut->addContactPoint(normalOnSurfaceB, pOnB, distance);
resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance);
}
}
void btConvexPlaneCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btConvexPlaneCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)dispatchInfo;
if (!m_manifoldPtr)
return;
const btCollisionObjectWrapper* convexObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* planeObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
const btCollisionObjectWrapper* convexObjWrap = m_isSwapped? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* planeObjWrap = m_isSwapped? body0Wrap: body1Wrap;
btConvexShape* convexShape = (btConvexShape*)convexObjWrap->getCollisionShape();
btStaticPlaneShape* planeShape = (btStaticPlaneShape*)planeObjWrap->getCollisionShape();
btConvexShape* convexShape = (btConvexShape*) convexObjWrap->getCollisionShape();
btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObjWrap->getCollisionShape();
bool hasCollision = false;
const btVector3& planeNormal = planeShape->getPlaneNormal();
const btScalar& planeConstant = planeShape->getPlaneConstant();
btTransform planeInConvex;
planeInConvex = convexObjWrap->getWorldTransform().inverse() * planeObjWrap->getWorldTransform();
planeInConvex= convexObjWrap->getWorldTransform().inverse() * planeObjWrap->getWorldTransform();
btTransform convexInPlaneTrans;
convexInPlaneTrans = planeObjWrap->getWorldTransform().inverse() * convexObjWrap->getWorldTransform();
convexInPlaneTrans= planeObjWrap->getWorldTransform().inverse() * convexObjWrap->getWorldTransform();
btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis() * -planeNormal);
btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
btVector3 vtxInPlane = convexInPlaneTrans(vtx);
btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
btVector3 vtxInPlaneProjected = vtxInPlane - distance * planeNormal;
btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
btVector3 vtxInPlaneWorld = planeObjWrap->getWorldTransform() * vtxInPlaneProjected;
hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold();
resultOut->setPersistentManifold(m_manifoldPtr);
if (hasCollision)
{
/// report a contact. internally this will be kept persistent, and contact reduction is done
btVector3 normalOnSurfaceB = planeObjWrap->getWorldTransform().getBasis() * planeNormal;
btVector3 pOnB = vtxInPlaneWorld;
resultOut->addContactPoint(normalOnSurfaceB, pOnB, distance);
resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance);
}
//the perturbation algorithm doesn't work well with implicit surfaces such as spheres, cylinder and cones:
//they keep on rolling forever because of the additional off-center contact points
//so only enable the feature for polyhedral shapes (btBoxShape, btConvexHullShape etc)
if (convexShape->isPolyhedral() && resultOut->getPersistentManifold()->getNumContacts() < m_minimumPointsPerturbationThreshold)
if (convexShape->isPolyhedral() && resultOut->getPersistentManifold()->getNumContacts()<m_minimumPointsPerturbationThreshold)
{
btVector3 v0, v1;
btPlaneSpace1(planeNormal, v0, v1);
btVector3 v0,v1;
btPlaneSpace1(planeNormal,v0,v1);
//now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
const btScalar angleLimit = 0.125f * SIMD_PI;
btScalar perturbeAngle;
btScalar radius = convexShape->getAngularMotionDisc();
perturbeAngle = gContactBreakingThreshold / radius;
if (perturbeAngle > angleLimit)
perturbeAngle = angleLimit;
if ( perturbeAngle > angleLimit )
perturbeAngle = angleLimit;
btQuaternion perturbeRot(v0, perturbeAngle);
for (int i = 0; i < m_numPerturbationIterations; i++)
btQuaternion perturbeRot(v0,perturbeAngle);
for (int i=0;i<m_numPerturbationIterations;i++)
{
btScalar iterationAngle = i * (SIMD_2_PI / btScalar(m_numPerturbationIterations));
btQuaternion rotq(planeNormal, iterationAngle);
collideSingleContact(rotq.inverse() * perturbeRot * rotq, body0Wrap, body1Wrap, dispatchInfo, resultOut);
btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations));
btQuaternion rotq(planeNormal,iterationAngle);
collideSingleContact(rotq.inverse()*perturbeRot*rotq,body0Wrap,body1Wrap,dispatchInfo,resultOut);
}
}
@@ -160,7 +162,7 @@ void btConvexPlaneCollisionAlgorithm::processCollision(const btCollisionObjectWr
}
}
btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;

View File

@@ -28,24 +28,25 @@ class btPersistentManifold;
/// Other features are frame-coherency (persistent data) and collision response.
class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_isSwapped;
int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_isSwapped;
int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
public:
btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold);
virtual ~btConvexPlaneCollisionAlgorithm();
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
void collideSingleContact(const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
void collideSingleContact (const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
@@ -53,30 +54,31 @@ public:
}
}
struct CreateFunc : public btCollisionAlgorithmCreateFunc
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
int m_numPerturbationIterations;
int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
CreateFunc()
CreateFunc()
: m_numPerturbationIterations(1),
m_minimumPointsPerturbationThreshold(0)
m_minimumPointsPerturbationThreshold(0)
{
}
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm));
if (!m_swapped)
{
return new (mem) btConvexPlaneCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, false, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
}
else
return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,false,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
} else
{
return new (mem) btConvexPlaneCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, true, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,true,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
}
}
};
};
#endif //BT_CONVEX_PLANE_COLLISION_ALGORITHM_H
#endif //BT_CONVEX_PLANE_COLLISION_ALGORITHM_H

View File

@@ -26,108 +26,115 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "LinearMath/btPoolAllocator.h"
btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo)
//btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* stackAlloc,btPoolAllocator* persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool)
{
void* mem = NULL;
void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16);
m_simplexSolver = new (mem)btVoronoiSimplexSolver();
if (constructionInfo.m_useEpaPenetrationAlgorithm)
{
mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver), 16);
m_pdSolver = new (mem) btGjkEpaPenetrationDepthSolver;
}
else
mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16);
m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver;
}else
{
mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver), 16);
m_pdSolver = new (mem) btMinkowskiPenetrationDepthSolver;
mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver),16);
m_pdSolver = new (mem)btMinkowskiPenetrationDepthSolver;
}
//default CreationFunctions, filling the m_doubleDispatch table
mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc), 16);
m_convexConvexCreateFunc = new (mem) btConvexConvexAlgorithm::CreateFunc(m_pdSolver);
mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc), 16);
m_convexConcaveCreateFunc = new (mem) btConvexConcaveCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc), 16);
m_swappedConvexConcaveCreateFunc = new (mem) btConvexConcaveCollisionAlgorithm::SwappedCreateFunc;
mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc), 16);
m_compoundCreateFunc = new (mem) btCompoundCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16);
m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver);
mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
m_swappedConvexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::SwappedCreateFunc;
mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc),16);
m_compoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btCompoundCompoundCollisionAlgorithm::CreateFunc), 16);
m_compoundCompoundCreateFunc = new (mem) btCompoundCompoundCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btCompoundCompoundCollisionAlgorithm::CreateFunc),16);
m_compoundCompoundCreateFunc = new (mem)btCompoundCompoundCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc), 16);
m_swappedCompoundCreateFunc = new (mem) btCompoundCollisionAlgorithm::SwappedCreateFunc;
mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc), 16);
m_emptyCreateFunc = new (mem) btEmptyAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc), 16);
m_sphereSphereCF = new (mem) btSphereSphereCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc),16);
m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc;
mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16);
m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16);
m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc;
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc), 16);
m_sphereBoxCF = new (mem) btSphereBoxCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc), 16);
m_boxSphereCF = new (mem) btSphereBoxCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc;
m_boxSphereCF->m_swapped = true;
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc), 16);
m_sphereTriangleCF = new (mem) btSphereTriangleCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc), 16);
m_triangleSphereCF = new (mem) btSphereTriangleCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
m_triangleSphereCF->m_swapped = true;
mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc), 16);
m_boxBoxCF = new (mem) btBoxBoxCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc),16);
m_boxBoxCF = new(mem)btBoxBoxCollisionAlgorithm::CreateFunc;
//convex versus plane
mem = btAlignedAlloc(sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc), 16);
mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc), 16);
mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
m_planeConvexCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
m_planeConvexCF->m_swapped = true;
///calculate maximum element size, big enough to fit any collision algorithm in the memory pool
int maxSize = sizeof(btConvexConvexAlgorithm);
int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm);
int maxSize3 = sizeof(btCompoundCollisionAlgorithm);
int maxSize4 = sizeof(btCompoundCompoundCollisionAlgorithm);
int collisionAlgorithmMaxElementSize = btMax(maxSize, constructionInfo.m_customCollisionAlgorithmMaxElementSize);
collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize, maxSize2);
collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize, maxSize3);
collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize, maxSize4);
int collisionAlgorithmMaxElementSize = btMax(maxSize,constructionInfo.m_customCollisionAlgorithmMaxElementSize);
collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize2);
collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3);
collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize4);
if (constructionInfo.m_persistentManifoldPool)
{
m_ownsPersistentManifoldPool = false;
m_persistentManifoldPool = constructionInfo.m_persistentManifoldPool;
}
else
} else
{
m_ownsPersistentManifoldPool = true;
void* mem = btAlignedAlloc(sizeof(btPoolAllocator), 16);
m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold), constructionInfo.m_defaultMaxPersistentManifoldPoolSize);
void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),constructionInfo.m_defaultMaxPersistentManifoldPoolSize);
}
collisionAlgorithmMaxElementSize = (collisionAlgorithmMaxElementSize + 16) & 0xffffffffffff0;
if (constructionInfo.m_collisionAlgorithmPool)
{
m_ownsCollisionAlgorithmPool = false;
m_collisionAlgorithmPool = constructionInfo.m_collisionAlgorithmPool;
}
else
} else
{
m_ownsCollisionAlgorithmPool = true;
void* mem = btAlignedAlloc(sizeof(btPoolAllocator), 16);
m_collisionAlgorithmPool = new (mem) btPoolAllocator(collisionAlgorithmMaxElementSize, constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
}
}
btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration()
@@ -144,159 +151,95 @@ btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration()
}
m_convexConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_convexConvexCreateFunc);
btAlignedFree( m_convexConvexCreateFunc);
m_convexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_convexConcaveCreateFunc);
btAlignedFree( m_convexConcaveCreateFunc);
m_swappedConvexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_swappedConvexConcaveCreateFunc);
btAlignedFree( m_swappedConvexConcaveCreateFunc);
m_compoundCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_compoundCreateFunc);
btAlignedFree( m_compoundCreateFunc);
m_compoundCompoundCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_compoundCompoundCreateFunc);
m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_swappedCompoundCreateFunc);
btAlignedFree( m_swappedCompoundCreateFunc);
m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_emptyCreateFunc);
btAlignedFree( m_emptyCreateFunc);
m_sphereSphereCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_sphereSphereCF);
btAlignedFree( m_sphereSphereCF);
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
m_sphereBoxCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_sphereBoxCF);
btAlignedFree( m_sphereBoxCF);
m_boxSphereCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_boxSphereCF);
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
btAlignedFree( m_boxSphereCF);
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_sphereTriangleCF);
btAlignedFree( m_sphereTriangleCF);
m_triangleSphereCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_triangleSphereCF);
btAlignedFree( m_triangleSphereCF);
m_boxBoxCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_boxBoxCF);
btAlignedFree( m_boxBoxCF);
m_convexPlaneCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_convexPlaneCF);
btAlignedFree( m_convexPlaneCF);
m_planeConvexCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_planeConvexCF);
btAlignedFree( m_planeConvexCF);
m_simplexSolver->~btVoronoiSimplexSolver();
btAlignedFree(m_simplexSolver);
m_pdSolver->~btConvexPenetrationDepthSolver();
btAlignedFree(m_pdSolver);
}
btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1)
btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1)
{
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
{
return m_sphereSphereCF;
return m_sphereSphereCF;
}
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==BOX_SHAPE_PROXYTYPE))
{
return m_sphereBoxCF;
return m_sphereBoxCF;
}
if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
if ((proxyType0 == BOX_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
{
return m_boxSphereCF;
return m_boxSphereCF;
}
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == TRIANGLE_SHAPE_PROXYTYPE))
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE ) && (proxyType1==TRIANGLE_SHAPE_PROXYTYPE))
{
return m_sphereTriangleCF;
return m_sphereTriangleCF;
}
if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
{
return m_triangleSphereCF;
}
if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE))
{
return m_convexPlaneCF;
}
if (btBroadphaseProxy::isConvex(proxyType1) && (proxyType0 == STATIC_PLANE_PROXYTYPE))
{
return m_planeConvexCF;
}
if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1))
{
return m_convexConvexCreateFunc;
}
if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1))
{
return m_convexConcaveCreateFunc;
}
if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0))
{
return m_swappedConvexConcaveCreateFunc;
}
if (btBroadphaseProxy::isCompound(proxyType0) && btBroadphaseProxy::isCompound(proxyType1))
{
return m_compoundCompoundCreateFunc;
}
if (btBroadphaseProxy::isCompound(proxyType0))
{
return m_compoundCreateFunc;
}
else
{
if (btBroadphaseProxy::isCompound(proxyType1))
{
return m_swappedCompoundCreateFunc;
}
}
//failed to find an algorithm
return m_emptyCreateFunc;
}
btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1)
{
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
{
return m_sphereSphereCF;
}
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
{
return m_sphereBoxCF;
}
if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
{
return m_boxSphereCF;
}
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == TRIANGLE_SHAPE_PROXYTYPE))
{
return m_sphereTriangleCF;
}
if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
{
return m_triangleSphereCF;
}
return m_triangleSphereCF;
}
if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
{
return m_boxBoxCF;
}
if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE))
{
return m_convexPlaneCF;
@@ -306,6 +249,8 @@ btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlg
{
return m_planeConvexCF;
}
if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1))
{
@@ -322,6 +267,7 @@ btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlg
return m_swappedConvexConcaveCreateFunc;
}
if (btBroadphaseProxy::isCompound(proxyType0) && btBroadphaseProxy::isCompound(proxyType1))
{
return m_compoundCompoundCreateFunc;
@@ -330,8 +276,7 @@ btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlg
if (btBroadphaseProxy::isCompound(proxyType0))
{
return m_compoundCreateFunc;
}
else
} else
{
if (btBroadphaseProxy::isCompound(proxyType1))
{
@@ -345,17 +290,17 @@ btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlg
void btDefaultCollisionConfiguration::setConvexConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold)
{
btConvexConvexAlgorithm::CreateFunc* convexConvex = (btConvexConvexAlgorithm::CreateFunc*)m_convexConvexCreateFunc;
btConvexConvexAlgorithm::CreateFunc* convexConvex = (btConvexConvexAlgorithm::CreateFunc*) m_convexConvexCreateFunc;
convexConvex->m_numPerturbationIterations = numPerturbationIterations;
convexConvex->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;
}
void btDefaultCollisionConfiguration::setPlaneConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold)
void btDefaultCollisionConfiguration::setPlaneConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold)
{
btConvexPlaneCollisionAlgorithm::CreateFunc* cpCF = (btConvexPlaneCollisionAlgorithm::CreateFunc*)m_convexPlaneCF;
cpCF->m_numPerturbationIterations = numPerturbationIterations;
cpCF->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;
btConvexPlaneCollisionAlgorithm::CreateFunc* pcCF = (btConvexPlaneCollisionAlgorithm::CreateFunc*)m_planeConvexCF;
pcCF->m_numPerturbationIterations = numPerturbationIterations;
pcCF->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;

View File

@@ -20,68 +20,77 @@ subject to the following restrictions:
class btVoronoiSimplexSolver;
class btConvexPenetrationDepthSolver;
struct btDefaultCollisionConstructionInfo
struct btDefaultCollisionConstructionInfo
{
btPoolAllocator* m_persistentManifoldPool;
btPoolAllocator* m_collisionAlgorithmPool;
int m_defaultMaxPersistentManifoldPoolSize;
int m_defaultMaxCollisionAlgorithmPoolSize;
int m_customCollisionAlgorithmMaxElementSize;
int m_useEpaPenetrationAlgorithm;
btPoolAllocator* m_persistentManifoldPool;
btPoolAllocator* m_collisionAlgorithmPool;
int m_defaultMaxPersistentManifoldPoolSize;
int m_defaultMaxCollisionAlgorithmPoolSize;
int m_customCollisionAlgorithmMaxElementSize;
int m_useEpaPenetrationAlgorithm;
btDefaultCollisionConstructionInfo()
: m_persistentManifoldPool(0),
m_collisionAlgorithmPool(0),
m_defaultMaxPersistentManifoldPoolSize(4096),
m_defaultMaxCollisionAlgorithmPoolSize(4096),
m_customCollisionAlgorithmMaxElementSize(0),
m_useEpaPenetrationAlgorithm(true)
:m_persistentManifoldPool(0),
m_collisionAlgorithmPool(0),
m_defaultMaxPersistentManifoldPoolSize(4096),
m_defaultMaxCollisionAlgorithmPoolSize(4096),
m_customCollisionAlgorithmMaxElementSize(0),
m_useEpaPenetrationAlgorithm(true)
{
}
};
///btCollisionConfiguration allows to configure Bullet collision detection
///stack allocator, pool memory allocators
///@todo: describe the meaning
class btDefaultCollisionConfiguration : public btCollisionConfiguration
class btDefaultCollisionConfiguration : public btCollisionConfiguration
{
protected:
int m_persistentManifoldPoolSize;
btPoolAllocator* m_persistentManifoldPool;
bool m_ownsPersistentManifoldPool;
int m_persistentManifoldPoolSize;
btPoolAllocator* m_collisionAlgorithmPool;
bool m_ownsCollisionAlgorithmPool;
btPoolAllocator* m_persistentManifoldPool;
bool m_ownsPersistentManifoldPool;
//default penetration depth solver
btConvexPenetrationDepthSolver* m_pdSolver;
btPoolAllocator* m_collisionAlgorithmPool;
bool m_ownsCollisionAlgorithmPool;
//default simplex/penetration depth solvers
btVoronoiSimplexSolver* m_simplexSolver;
btConvexPenetrationDepthSolver* m_pdSolver;
//default CreationFunctions, filling the m_doubleDispatch table
btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc;
btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc;
btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc;
btCollisionAlgorithmCreateFunc* m_compoundCreateFunc;
btCollisionAlgorithmCreateFunc* m_compoundCompoundCreateFunc;
btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc;
btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc;
btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc;
btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc;
btCollisionAlgorithmCreateFunc* m_compoundCreateFunc;
btCollisionAlgorithmCreateFunc* m_compoundCompoundCreateFunc;
btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc;
btCollisionAlgorithmCreateFunc* m_emptyCreateFunc;
btCollisionAlgorithmCreateFunc* m_sphereSphereCF;
btCollisionAlgorithmCreateFunc* m_sphereBoxCF;
btCollisionAlgorithmCreateFunc* m_boxSphereCF;
btCollisionAlgorithmCreateFunc* m_boxBoxCF;
btCollisionAlgorithmCreateFunc* m_sphereTriangleCF;
btCollisionAlgorithmCreateFunc* m_triangleSphereCF;
btCollisionAlgorithmCreateFunc* m_planeConvexCF;
btCollisionAlgorithmCreateFunc* m_convexPlaneCF;
btCollisionAlgorithmCreateFunc* m_sphereTriangleCF;
btCollisionAlgorithmCreateFunc* m_triangleSphereCF;
btCollisionAlgorithmCreateFunc* m_planeConvexCF;
btCollisionAlgorithmCreateFunc* m_convexPlaneCF;
public:
btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo());
virtual ~btDefaultCollisionConfiguration();
///memory pools
///memory pools
virtual btPoolAllocator* getPersistentManifoldPool()
{
return m_persistentManifoldPool;
@@ -92,9 +101,14 @@ public:
return m_collisionAlgorithmPool;
}
virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1);
virtual btCollisionAlgorithmCreateFunc* getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1);
virtual btVoronoiSimplexSolver* getSimplexSolver()
{
return m_simplexSolver;
}
virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1);
///Use this method to allow to generate multiple contact points between at once, between two objects using the generic convex-convex algorithm.
///By default, this feature is disabled for best performance.
@@ -103,9 +117,11 @@ public:
///3 is a good value for both params, if you want to enable the feature. This is because the default contact cache contains a maximum of 4 points, and one collision query at the unperturbed orientation is performed first.
///See Bullet/Demos/CollisionDemo for an example how this feature gathers multiple points.
///@todo we could add a per-object setting of those parameters, for level-of-detail collision detection.
void setConvexConvexMultipointIterations(int numPerturbationIterations = 3, int minimumPointsPerturbationThreshold = 3);
void setConvexConvexMultipointIterations(int numPerturbationIterations=3, int minimumPointsPerturbationThreshold = 3);
void setPlaneConvexMultipointIterations(int numPerturbationIterations=3, int minimumPointsPerturbationThreshold = 3);
void setPlaneConvexMultipointIterations(int numPerturbationIterations = 3, int minimumPointsPerturbationThreshold = 3);
};
#endif //BT_DEFAULT_COLLISION_CONFIGURATION
#endif //BT_DEFAULT_COLLISION_CONFIGURATION

View File

@@ -15,16 +15,20 @@ subject to the following restrictions:
#include "btEmptyCollisionAlgorithm.h"
btEmptyAlgorithm::btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btCollisionAlgorithm(ci)
{
}
void btEmptyAlgorithm::processCollision(const btCollisionObjectWrapper*, const btCollisionObjectWrapper*, const btDispatcherInfo&, btManifoldResult*)
void btEmptyAlgorithm::processCollision (const btCollisionObjectWrapper* ,const btCollisionObjectWrapper* ,const btDispatcherInfo& ,btManifoldResult* )
{
}
btScalar btEmptyAlgorithm::calculateTimeOfImpact(btCollisionObject*, btCollisionObject*, const btDispatcherInfo&, btManifoldResult*)
btScalar btEmptyAlgorithm::calculateTimeOfImpact(btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* )
{
return btScalar(1.);
}

View File

@@ -25,28 +25,30 @@ subject to the following restrictions:
///The dispatcher can dispatch a persistent btEmptyAlgorithm to avoid a search every frame.
class btEmptyAlgorithm : public btCollisionAlgorithm
{
public:
btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
}
struct CreateFunc : public btCollisionAlgorithmCreateFunc
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
(void)body0Wrap;
(void)body1Wrap;
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm));
return new (mem) btEmptyAlgorithm(ci);
return new(mem) btEmptyAlgorithm(ci);
}
};
} ATTRIBUTE_ALIGNED(16);
#endif //BT_EMPTY_ALGORITH
#endif //BT_EMPTY_ALGORITH

View File

@@ -29,58 +29,60 @@ btGhostObject::~btGhostObject()
btAssert(!m_overlappingObjects.size());
}
void btGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy)
void btGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy)
{
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btAssert(otherObject);
///if this linearSearch becomes too slow (too many overlapping objects) we should add a more appropriate data structure
int index = m_overlappingObjects.findLinearSearch(otherObject);
if (index == m_overlappingObjects.size())
if (index==m_overlappingObjects.size())
{
//not found
m_overlappingObjects.push_back(otherObject);
}
}
void btGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btDispatcher* dispatcher, btBroadphaseProxy* thisProxy)
void btGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy)
{
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btAssert(otherObject);
int index = m_overlappingObjects.findLinearSearch(otherObject);
if (index < m_overlappingObjects.size())
if (index<m_overlappingObjects.size())
{
m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size() - 1];
m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1];
m_overlappingObjects.pop_back();
}
}
btPairCachingGhostObject::btPairCachingGhostObject()
{
m_hashPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache), 16)) btHashedOverlappingPairCache();
m_hashPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
}
btPairCachingGhostObject::~btPairCachingGhostObject()
{
m_hashPairCache->~btHashedOverlappingPairCache();
btAlignedFree(m_hashPairCache);
btAlignedFree( m_hashPairCache );
}
void btPairCachingGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy)
void btPairCachingGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy)
{
btBroadphaseProxy* actualThisProxy = thisProxy ? thisProxy : getBroadphaseHandle();
btBroadphaseProxy*actualThisProxy = thisProxy ? thisProxy : getBroadphaseHandle();
btAssert(actualThisProxy);
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btAssert(otherObject);
int index = m_overlappingObjects.findLinearSearch(otherObject);
if (index == m_overlappingObjects.size())
if (index==m_overlappingObjects.size())
{
m_overlappingObjects.push_back(otherObject);
m_hashPairCache->addOverlappingPair(actualThisProxy, otherProxy);
m_hashPairCache->addOverlappingPair(actualThisProxy,otherProxy);
}
}
void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btDispatcher* dispatcher, btBroadphaseProxy* thisProxy1)
void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy1)
{
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btBroadphaseProxy* actualThisProxy = thisProxy1 ? thisProxy1 : getBroadphaseHandle();
@@ -88,79 +90,82 @@ void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy
btAssert(otherObject);
int index = m_overlappingObjects.findLinearSearch(otherObject);
if (index < m_overlappingObjects.size())
if (index<m_overlappingObjects.size())
{
m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size() - 1];
m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1];
m_overlappingObjects.pop_back();
m_hashPairCache->removeOverlappingPair(actualThisProxy, otherProxy, dispatcher);
m_hashPairCache->removeOverlappingPair(actualThisProxy,otherProxy,dispatcher);
}
}
void btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
void btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
{
btTransform convexFromTrans, convexToTrans;
btTransform convexFromTrans,convexToTrans;
convexFromTrans = convexFromWorld;
convexToTrans = convexToWorld;
btVector3 castShapeAabbMin, castShapeAabbMax;
/* Compute AABB that encompasses angular movement */
{
btVector3 linVel, angVel;
btTransformUtil::calculateVelocity(convexFromTrans, convexToTrans, 1.0, linVel, angVel);
btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel);
btTransform R;
R.setIdentity();
R.setRotation(convexFromTrans.getRotation());
castShape->calculateTemporalAabb(R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax);
R.setIdentity ();
R.setRotation (convexFromTrans.getRotation());
castShape->calculateTemporalAabb (R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax);
}
/// go over all objects, and if the ray intersects their aabb + cast shape aabb,
// do a ray-shape query using convexCaster (CCD)
int i;
for (i = 0; i < m_overlappingObjects.size(); i++)
for (i=0;i<m_overlappingObjects.size();i++)
{
btCollisionObject* collisionObject = m_overlappingObjects[i];
btCollisionObject* collisionObject= m_overlappingObjects[i];
//only perform raycast if filterMask matches
if (resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
{
if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
btVector3 collisionObjectAabbMin, collisionObjectAabbMax;
collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(), collisionObjectAabbMin, collisionObjectAabbMax);
AabbExpand(collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
btVector3 hitNormal;
if (btRayAabb(convexFromWorld.getOrigin(), convexToWorld.getOrigin(), collisionObjectAabbMin, collisionObjectAabbMax, hitLambda, hitNormal))
if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
{
btCollisionWorld::objectQuerySingle(castShape, convexFromTrans, convexToTrans,
collisionObject,
collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(),
resultCallback,
allowedCcdPenetration);
btCollisionWorld::objectQuerySingle(castShape, convexFromTrans,convexToTrans,
collisionObject,
collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(),
resultCallback,
allowedCcdPenetration);
}
}
}
}
void btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const
void btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const
{
btTransform rayFromTrans;
rayFromTrans.setIdentity();
rayFromTrans.setOrigin(rayFromWorld);
btTransform rayToTrans;
btTransform rayToTrans;
rayToTrans.setIdentity();
rayToTrans.setOrigin(rayToWorld);
int i;
for (i = 0; i < m_overlappingObjects.size(); i++)
for (i=0;i<m_overlappingObjects.size();i++)
{
btCollisionObject* collisionObject = m_overlappingObjects[i];
btCollisionObject* collisionObject= m_overlappingObjects[i];
//only perform raycast if filterMask matches
if (resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
{
btCollisionWorld::rayTestSingle(rayFromTrans, rayToTrans,
collisionObject,
collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(),
resultCallback);
btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,
collisionObject,
collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(),
resultCallback);
}
}
}

View File

@@ -16,6 +16,7 @@ subject to the following restrictions:
#ifndef BT_GHOST_OBJECT_H
#define BT_GHOST_OBJECT_H
#include "btCollisionObject.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h"
#include "LinearMath/btAlignedAllocator.h"
@@ -30,47 +31,48 @@ class btDispatcher;
///By default, this overlap is based on the AABB
///This is useful for creating a character controller, collision sensors/triggers, explosions etc.
///We plan on adding rayTest and other queries for the btGhostObject
ATTRIBUTE_ALIGNED16(class)
btGhostObject : public btCollisionObject
ATTRIBUTE_ALIGNED16(class) btGhostObject : public btCollisionObject
{
protected:
btAlignedObjectArray<btCollisionObject*> m_overlappingObjects;
public:
btGhostObject();
virtual ~btGhostObject();
void convexSweepTest(const class btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = 0.f) const;
void convexSweepTest(const class btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = 0.f) const;
void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const;
void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const;
///this method is mainly for expert/internal use only.
virtual void addOverlappingObjectInternal(btBroadphaseProxy * otherProxy, btBroadphaseProxy* thisProxy = 0);
virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0);
///this method is mainly for expert/internal use only.
virtual void removeOverlappingObjectInternal(btBroadphaseProxy * otherProxy, btDispatcher * dispatcher, btBroadphaseProxy* thisProxy = 0);
virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0);
int getNumOverlappingObjects() const
int getNumOverlappingObjects() const
{
return m_overlappingObjects.size();
}
btCollisionObject* getOverlappingObject(int index)
btCollisionObject* getOverlappingObject(int index)
{
return m_overlappingObjects[index];
}
const btCollisionObject* getOverlappingObject(int index) const
const btCollisionObject* getOverlappingObject(int index) const
{
return m_overlappingObjects[index];
}
btAlignedObjectArray<btCollisionObject*>& getOverlappingPairs()
btAlignedObjectArray<btCollisionObject*>& getOverlappingPairs()
{
return m_overlappingObjects;
}
const btAlignedObjectArray<btCollisionObject*> getOverlappingPairs() const
const btAlignedObjectArray<btCollisionObject*> getOverlappingPairs() const
{
return m_overlappingObjects;
}
@@ -79,43 +81,49 @@ public:
// internal cast
//
static const btGhostObject* upcast(const btCollisionObject* colObj)
static const btGhostObject* upcast(const btCollisionObject* colObj)
{
if (colObj->getInternalType() == CO_GHOST_OBJECT)
if (colObj->getInternalType()==CO_GHOST_OBJECT)
return (const btGhostObject*)colObj;
return 0;
}
static btGhostObject* upcast(btCollisionObject * colObj)
static btGhostObject* upcast(btCollisionObject* colObj)
{
if (colObj->getInternalType() == CO_GHOST_OBJECT)
if (colObj->getInternalType()==CO_GHOST_OBJECT)
return (btGhostObject*)colObj;
return 0;
}
};
class btPairCachingGhostObject : public btGhostObject
class btPairCachingGhostObject : public btGhostObject
{
btHashedOverlappingPairCache* m_hashPairCache;
btHashedOverlappingPairCache* m_hashPairCache;
public:
btPairCachingGhostObject();
virtual ~btPairCachingGhostObject();
///this method is mainly for expert/internal use only.
virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy = 0);
virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0);
virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btDispatcher* dispatcher, btBroadphaseProxy* thisProxy = 0);
virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0);
btHashedOverlappingPairCache* getOverlappingPairCache()
btHashedOverlappingPairCache* getOverlappingPairCache()
{
return m_hashPairCache;
}
};
///The btGhostPairCallback interfaces and forwards adding and removal of overlapping pairs from the btBroadphaseInterface to btGhostObject.
class btGhostPairCallback : public btOverlappingPairCallback
{
public:
btGhostPairCallback()
{
@@ -123,14 +131,15 @@ public:
virtual ~btGhostPairCallback()
{
}
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
btCollisionObject* colObj0 = (btCollisionObject*)proxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)proxy1->m_clientObject;
btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject;
btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
if (ghost0)
ghost0->addOverlappingObjectInternal(proxy1, proxy0);
if (ghost1)
@@ -138,25 +147,29 @@ public:
return 0;
}
virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher)
virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
{
btCollisionObject* colObj0 = (btCollisionObject*)proxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)proxy1->m_clientObject;
btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject;
btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
if (ghost0)
ghost0->removeOverlappingObjectInternal(proxy1, dispatcher, proxy0);
ghost0->removeOverlappingObjectInternal(proxy1,dispatcher,proxy0);
if (ghost1)
ghost1->removeOverlappingObjectInternal(proxy0, dispatcher, proxy1);
ghost1->removeOverlappingObjectInternal(proxy0,dispatcher,proxy1);
return 0;
}
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/, btDispatcher* /*dispatcher*/)
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/)
{
btAssert(0);
//need to keep track of all ghost objects and call them here
//m_hashPairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher);
}
};
#endif

View File

@@ -13,49 +13,61 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "btHashedSimplePairCache.h"
#include <stdio.h>
#ifdef BT_DEBUG_COLLISION_PAIRS
int gOverlappingSimplePairs = 0;
int gRemoveSimplePairs = 0;
int gAddedSimplePairs = 0;
int gFindSimplePairs = 0;
#endif //BT_DEBUG_COLLISION_PAIRS
int gOverlappingSimplePairs = 0;
int gRemoveSimplePairs =0;
int gAddedSimplePairs =0;
int gFindSimplePairs =0;
btHashedSimplePairCache::btHashedSimplePairCache()
{
int initialAllocatedSize = 2;
btHashedSimplePairCache::btHashedSimplePairCache() {
int initialAllocatedSize= 2;
m_overlappingPairArray.reserve(initialAllocatedSize);
growTables();
}
btHashedSimplePairCache::~btHashedSimplePairCache()
{
}
void btHashedSimplePairCache::removeAllPairs()
{
m_overlappingPairArray.clear();
m_hashTable.clear();
m_next.clear();
int initialAllocatedSize = 2;
int initialAllocatedSize= 2;
m_overlappingPairArray.reserve(initialAllocatedSize);
growTables();
}
btSimplePair* btHashedSimplePairCache::findPair(int indexA, int indexB)
{
#ifdef BT_DEBUG_COLLISION_PAIRS
gFindSimplePairs++;
#endif
/*if (indexA > indexB)
btSwap(indexA, indexB);*/
int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1));
int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1));
if (hash >= m_hashTable.size())
{
@@ -80,8 +92,9 @@ btSimplePair* btHashedSimplePairCache::findPair(int indexA, int indexB)
//#include <stdio.h>
void btHashedSimplePairCache::growTables()
void btHashedSimplePairCache::growTables()
{
int newCapacity = m_overlappingPairArray.capacity();
if (m_hashTable.size() < newCapacity)
@@ -92,9 +105,10 @@ void btHashedSimplePairCache::growTables()
m_hashTable.resize(newCapacity);
m_next.resize(newCapacity);
int i;
for (i = 0; i < newCapacity; ++i)
for (i= 0; i < newCapacity; ++i)
{
m_hashTable[i] = BT_SIMPLE_NULL_PAIR;
}
@@ -103,22 +117,27 @@ void btHashedSimplePairCache::growTables()
m_next[i] = BT_SIMPLE_NULL_PAIR;
}
for (i = 0; i < curHashtableSize; i++)
for(i=0;i<curHashtableSize;i++)
{
const btSimplePair& pair = m_overlappingPairArray[i];
int indexA = pair.m_indexA;
int indexB = pair.m_indexB;
int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1)); // New hash value with new mask
int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
m_next[i] = m_hashTable[hashValue];
m_hashTable[hashValue] = i;
}
}
}
btSimplePair* btHashedSimplePairCache::internalAddPair(int indexA, int indexB)
{
int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1)); // New hash value with new mask
int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
btSimplePair* pair = internalFindPair(indexA, indexB, hash);
if (pair != NULL)
@@ -136,29 +155,30 @@ btSimplePair* btHashedSimplePairCache::internalAddPair(int indexA, int indexB)
{
growTables();
//hash with new capacity
hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1));
hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1));
}
pair = new (mem) btSimplePair(indexA, indexB);
pair = new (mem) btSimplePair(indexA,indexB);
pair->m_userPointer = 0;
m_next[count] = m_hashTable[hash];
m_hashTable[hash] = count;
return pair;
}
void* btHashedSimplePairCache::removeOverlappingPair(int indexA, int indexB)
{
#ifdef BT_DEBUG_COLLISION_PAIRS
gRemoveSimplePairs++;
#endif
/*if (indexA > indexB)
btSwap(indexA, indexB);*/
int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1));
int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1));
btSimplePair* pair = internalFindPair(indexA, indexB, hash);
if (pair == NULL)
@@ -166,8 +186,10 @@ void* btHashedSimplePairCache::removeOverlappingPair(int indexA, int indexB)
return 0;
}
void* userData = pair->m_userPointer;
int pairIndex = int(pair - &m_overlappingPairArray[0]);
btAssert(pairIndex < m_overlappingPairArray.size());
@@ -207,8 +229,8 @@ void* btHashedSimplePairCache::removeOverlappingPair(int indexA, int indexB)
// Remove the last pair from the hash table.
const btSimplePair* last = &m_overlappingPairArray[lastPairIndex];
/* missing swap here too, Nat. */
int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_indexA), static_cast<unsigned int>(last->m_indexB)) & (m_overlappingPairArray.capacity() - 1));
/* missing swap here too, Nat. */
int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_indexA), static_cast<unsigned int>(last->m_indexB)) & (m_overlappingPairArray.capacity()-1));
index = m_hashTable[lastHash];
btAssert(index != BT_SIMPLE_NULL_PAIR);
@@ -242,3 +264,13 @@ void* btHashedSimplePairCache::removeOverlappingPair(int indexA, int indexB)
return userData;
}
//#include <stdio.h>

View File

@@ -16,126 +16,142 @@ subject to the following restrictions:
#ifndef BT_HASHED_SIMPLE_PAIR_CACHE_H
#define BT_HASHED_SIMPLE_PAIR_CACHE_H
#include "LinearMath/btAlignedObjectArray.h"
const int BT_SIMPLE_NULL_PAIR = 0xffffffff;
const int BT_SIMPLE_NULL_PAIR=0xffffffff;
struct btSimplePair
{
btSimplePair(int indexA, int indexB)
: m_indexA(indexA),
m_indexB(indexB),
m_userPointer(0)
btSimplePair(int indexA,int indexB)
:m_indexA(indexA),
m_indexB(indexB),
m_userPointer(0)
{
}
int m_indexA;
int m_indexB;
union {
void* m_userPointer;
int m_userValue;
union
{
void* m_userPointer;
int m_userValue;
};
};
typedef btAlignedObjectArray<btSimplePair> btSimplePairArray;
typedef btAlignedObjectArray<btSimplePair> btSimplePairArray;
#ifdef BT_DEBUG_COLLISION_PAIRS
extern int gOverlappingSimplePairs;
extern int gRemoveSimplePairs;
extern int gAddedSimplePairs;
extern int gFindSimplePairs;
#endif //BT_DEBUG_COLLISION_PAIRS
class btHashedSimplePairCache
{
btSimplePairArray m_overlappingPairArray;
btSimplePairArray m_overlappingPairArray;
protected:
btAlignedObjectArray<int> m_hashTable;
btAlignedObjectArray<int> m_next;
btAlignedObjectArray<int> m_hashTable;
btAlignedObjectArray<int> m_next;
public:
btHashedSimplePairCache();
virtual ~btHashedSimplePairCache();
void removeAllPairs();
virtual void* removeOverlappingPair(int indexA, int indexB);
virtual void* removeOverlappingPair(int indexA,int indexB);
// Add a pair and return the new pair. If the pair already exists,
// no new pair is created and the old one is returned.
virtual btSimplePair* addOverlappingPair(int indexA, int indexB)
virtual btSimplePair* addOverlappingPair(int indexA,int indexB)
{
#ifdef BT_DEBUG_COLLISION_PAIRS
gAddedSimplePairs++;
#endif
return internalAddPair(indexA, indexB);
return internalAddPair(indexA,indexB);
}
virtual btSimplePair* getOverlappingPairArrayPtr()
virtual btSimplePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
const btSimplePair* getOverlappingPairArrayPtr() const
const btSimplePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
btSimplePairArray& getOverlappingPairArray()
btSimplePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
const btSimplePairArray& getOverlappingPairArray() const
const btSimplePairArray& getOverlappingPairArray() const
{
return m_overlappingPairArray;
}
btSimplePair* findPair(int indexA, int indexB);
btSimplePair* findPair(int indexA,int indexB);
int GetCount() const { return m_overlappingPairArray.size(); }
int getNumOverlappingPairs() const
int getNumOverlappingPairs() const
{
return m_overlappingPairArray.size();
}
private:
btSimplePair* internalAddPair(int indexA, int indexB);
btSimplePair* internalAddPair(int indexA, int indexB);
void growTables();
void growTables();
SIMD_FORCE_INLINE bool equalsPair(const btSimplePair& pair, int indexA, int indexB)
{
{
return pair.m_indexA == indexA && pair.m_indexB == indexB;
}
SIMD_FORCE_INLINE unsigned int getHash(unsigned int indexA, unsigned int indexB)
SIMD_FORCE_INLINE unsigned int getHash(unsigned int indexA, unsigned int indexB)
{
unsigned int key = indexA | (indexB << 16);
int key = static_cast<int>(((unsigned int)indexA) | (((unsigned int)indexB) <<16));
// Thomas Wang's hash
key += ~(key << 15);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
return key;
key ^= (key >> 16);
return static_cast<unsigned int>(key);
}
SIMD_FORCE_INLINE btSimplePair* internalFindPair(int proxyIdA, int proxyIdB, int hash)
SIMD_FORCE_INLINE btSimplePair* internalFindPair(int proxyIdA , int proxyIdB, int hash)
{
int index = m_hashTable[hash];
while (index != BT_SIMPLE_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyIdA, proxyIdB) == false)
while( index != BT_SIMPLE_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyIdA, proxyIdB) == false)
{
index = m_next[index];
}
if (index == BT_SIMPLE_NULL_PAIR)
if ( index == BT_SIMPLE_NULL_PAIR )
{
return NULL;
}
@@ -144,6 +160,13 @@ private:
return &m_overlappingPairArray[index];
}
};
#endif //BT_HASHED_SIMPLE_PAIR_CACHE_H
#endif //BT_HASHED_SIMPLE_PAIR_CACHE_H

View File

@@ -15,30 +15,33 @@ class btCollisionObject;
struct btCollisionObjectWrapper;
class btManifoldPoint;
class btIDebugDraw;
class btHeightfieldTerrainShape;
enum btInternalEdgeAdjustFlags
{
BT_TRIANGLE_CONVEX_BACKFACE_MODE = 1,
BT_TRIANGLE_CONCAVE_DOUBLE_SIDED = 2, //double sided options are experimental, single sided is recommended
BT_TRIANGLE_CONCAVE_DOUBLE_SIDED = 2, //double sided options are experimental, single sided is recommended
BT_TRIANGLE_CONVEX_DOUBLE_SIDED = 4
};
///Call btGenerateInternalEdgeInfo to create triangle info, store in the shape 'userInfo'
void btGenerateInternalEdgeInfo(btBvhTriangleMeshShape* trimeshShape, btTriangleInfoMap* triangleInfoMap);
void btGenerateInternalEdgeInfo(btHeightfieldTerrainShape* trimeshShape, btTriangleInfoMap* triangleInfoMap);
///Call btGenerateInternalEdgeInfo to create triangle info, store in the shape 'userInfo'
void btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangleInfoMap* triangleInfoMap);
///Call the btFixMeshNormal to adjust the collision normal, using the triangle info map (generated using btGenerateInternalEdgeInfo)
///If this info map is missing, or the triangle is not store in this map, nothing will be done
void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* trimeshColObj0Wrap, const btCollisionObjectWrapper* otherColObj1Wrap, int partId0, int index0, int normalAdjustFlags = 0);
void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* trimeshColObj0Wrap,const btCollisionObjectWrapper* otherColObj1Wrap, int partId0, int index0, int normalAdjustFlags = 0);
///Enable the BT_INTERNAL_EDGE_DEBUG_DRAW define and call btSetDebugDrawer, to get visual info to see if the internal edge utility works properly.
///If the utility doesn't work properly, you might have to adjust the threshold values in btTriangleInfoMap
//#define BT_INTERNAL_EDGE_DEBUG_DRAW
#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
void btSetDebugDrawer(btIDebugDraw* debugDrawer);
#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
void btSetDebugDrawer(btIDebugDraw* debugDrawer);
#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
#endif //BT_INTERNAL_EDGE_UTILITY_H
#endif //BT_INTERNAL_EDGE_UTILITY_H

View File

@@ -13,191 +13,142 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "btManifoldResult.h"
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
///This is to allow MaterialCombiner/Custom Friction/Restitution values
ContactAddedCallback gContactAddedCallback = 0;
ContactAddedCallback gContactAddedCallback=0;
CalculateCombinedCallback gCalculateCombinedRestitutionCallback = &btManifoldResult::calculateCombinedRestitution;
CalculateCombinedCallback gCalculateCombinedFrictionCallback = &btManifoldResult::calculateCombinedFriction;
CalculateCombinedCallback gCalculateCombinedRollingFrictionCallback = &btManifoldResult::calculateCombinedRollingFriction;
CalculateCombinedCallback gCalculateCombinedSpinningFrictionCallback = &btManifoldResult::calculateCombinedSpinningFriction;
CalculateCombinedCallback gCalculateCombinedContactDampingCallback = &btManifoldResult::calculateCombinedContactDamping;
CalculateCombinedCallback gCalculateCombinedContactStiffnessCallback = &btManifoldResult::calculateCombinedContactStiffness;
btScalar btManifoldResult::calculateCombinedRollingFriction(const btCollisionObject* body0, const btCollisionObject* body1)
{
btScalar friction = body0->getRollingFriction() * body1->getFriction() + body1->getRollingFriction() * body0->getFriction();
const btScalar MAX_FRICTION = btScalar(10.);
if (friction < -MAX_FRICTION)
friction = -MAX_FRICTION;
if (friction > MAX_FRICTION)
friction = MAX_FRICTION;
return friction;
}
btScalar btManifoldResult::calculateCombinedSpinningFriction(const btCollisionObject* body0, const btCollisionObject* body1)
{
btScalar friction = body0->getSpinningFriction() * body1->getFriction() + body1->getSpinningFriction() * body0->getFriction();
const btScalar MAX_FRICTION = btScalar(10.);
if (friction < -MAX_FRICTION)
friction = -MAX_FRICTION;
if (friction > MAX_FRICTION)
friction = MAX_FRICTION;
return friction;
}
///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback;
btScalar btManifoldResult::calculateCombinedFriction(const btCollisionObject* body0, const btCollisionObject* body1)
inline btScalar calculateCombinedRollingFriction(const btCollisionObject* body0,const btCollisionObject* body1)
{
btScalar friction = body0->getRollingFriction() * body1->getRollingFriction();
const btScalar MAX_FRICTION = btScalar(10.);
if (friction < -MAX_FRICTION)
friction = -MAX_FRICTION;
if (friction > MAX_FRICTION)
friction = MAX_FRICTION;
return friction;
}
///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback;
btScalar btManifoldResult::calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1)
{
btScalar friction = body0->getFriction() * body1->getFriction();
const btScalar MAX_FRICTION = btScalar(10.);
const btScalar MAX_FRICTION = btScalar(10.);
if (friction < -MAX_FRICTION)
friction = -MAX_FRICTION;
if (friction > MAX_FRICTION)
friction = MAX_FRICTION;
return friction;
}
btScalar btManifoldResult::calculateCombinedRestitution(const btCollisionObject* body0, const btCollisionObject* body1)
btScalar btManifoldResult::calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1)
{
return body0->getRestitution() * body1->getRestitution();
}
btScalar btManifoldResult::calculateCombinedContactDamping(const btCollisionObject* body0, const btCollisionObject* body1)
{
return body0->getContactDamping() + body1->getContactDamping();
}
btScalar btManifoldResult::calculateCombinedContactStiffness(const btCollisionObject* body0, const btCollisionObject* body1)
{
btScalar s0 = body0->getContactStiffness();
btScalar s1 = body1->getContactStiffness();
btScalar tmp0 = btScalar(1) / s0;
btScalar tmp1 = btScalar(1) / s1;
btScalar combinedStiffness = btScalar(1) / (tmp0 + tmp1);
return combinedStiffness;
}
btManifoldResult::btManifoldResult(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
: m_manifoldPtr(0),
m_body0Wrap(body0Wrap),
m_body1Wrap(body1Wrap)
btManifoldResult::btManifoldResult(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
:m_manifoldPtr(0),
m_body0Wrap(body0Wrap),
m_body1Wrap(body1Wrap)
#ifdef DEBUG_PART_INDEX
,
m_partId0(-1),
m_partId1(-1),
m_index0(-1),
m_index1(-1)
#endif //DEBUG_PART_INDEX
,
m_closestPointDistanceThreshold(0)
,m_partId0(-1),
m_partId1(-1),
m_index0(-1),
m_index1(-1)
#endif //DEBUG_PART_INDEX
{
}
void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
{
btAssert(m_manifoldPtr);
//order in manifold needs to match
if (depth > m_manifoldPtr->getContactBreakingThreshold())
// if (depth > m_manifoldPtr->getContactProcessingThreshold())
// if (depth > m_manifoldPtr->getContactProcessingThreshold())
return;
bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
bool isNewCollision = m_manifoldPtr->getNumContacts() == 0;
btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
btVector3 localA;
btVector3 localB;
if (isSwapped)
{
localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
localB = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
}
else
} else
{
localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
localB = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
}
btManifoldPoint newPt(localA, localB, normalOnBInWorld, depth);
btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
newPt.m_positionWorldOnA = pointA;
newPt.m_positionWorldOnB = pointInWorld;
int insertIndex = m_manifoldPtr->getCacheEntry(newPt);
newPt.m_combinedFriction = gCalculateCombinedFrictionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
newPt.m_combinedRestitution = gCalculateCombinedRestitutionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
newPt.m_combinedRollingFriction = gCalculateCombinedRollingFrictionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
newPt.m_combinedSpinningFriction = gCalculateCombinedSpinningFrictionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
newPt.m_combinedFriction = calculateCombinedFriction(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
newPt.m_combinedRollingFriction = calculateCombinedRollingFriction(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
btPlaneSpace1(newPt.m_normalWorldOnB,newPt.m_lateralFrictionDir1,newPt.m_lateralFrictionDir2);
if ((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_CONTACT_STIFFNESS_DAMPING) ||
(m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_CONTACT_STIFFNESS_DAMPING))
{
newPt.m_combinedContactDamping1 = gCalculateCombinedContactDampingCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
newPt.m_combinedContactStiffness1 = gCalculateCombinedContactStiffnessCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
newPt.m_contactPointFlags |= BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING;
}
if ((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_FRICTION_ANCHOR) ||
(m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_FRICTION_ANCHOR))
{
newPt.m_contactPointFlags |= BT_CONTACT_FLAG_FRICTION_ANCHOR;
}
btPlaneSpace1(newPt.m_normalWorldOnB, newPt.m_lateralFrictionDir1, newPt.m_lateralFrictionDir2);
//BP mod, store contact triangles.
//BP mod, store contact triangles.
if (isSwapped)
{
newPt.m_partId0 = m_partId1;
newPt.m_partId1 = m_partId0;
newPt.m_index0 = m_index1;
newPt.m_index1 = m_index0;
}
else
newPt.m_index0 = m_index1;
newPt.m_index1 = m_index0;
} else
{
newPt.m_partId0 = m_partId0;
newPt.m_partId1 = m_partId1;
newPt.m_index0 = m_index0;
newPt.m_index1 = m_index1;
newPt.m_index0 = m_index0;
newPt.m_index1 = m_index1;
}
//printf("depth=%f\n",depth);
///@todo, check this for any side effects
if (insertIndex >= 0)
{
//const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
m_manifoldPtr->replaceContactPoint(newPt, insertIndex);
}
else
m_manifoldPtr->replaceContactPoint(newPt,insertIndex);
} else
{
insertIndex = m_manifoldPtr->addManifoldPoint(newPt);
}
//User can override friction and/or restitution
if (gContactAddedCallback &&
//and if either of the two bodies requires custom material
((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) ||
(m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)))
((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) ||
(m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)))
{
//experimental feature info, for per-triangle material etc.
const btCollisionObjectWrapper* obj0Wrap = isSwapped ? m_body1Wrap : m_body0Wrap;
const btCollisionObjectWrapper* obj1Wrap = isSwapped ? m_body0Wrap : m_body1Wrap;
(*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex), obj0Wrap, newPt.m_partId0, newPt.m_index0, obj1Wrap, newPt.m_partId1, newPt.m_index1);
const btCollisionObjectWrapper* obj0Wrap = isSwapped? m_body1Wrap : m_body0Wrap;
const btCollisionObjectWrapper* obj1Wrap = isSwapped? m_body0Wrap : m_body1Wrap;
(*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex),obj0Wrap,newPt.m_partId0,newPt.m_index0,obj1Wrap,newPt.m_partId1,newPt.m_index1);
}
if (gContactStartedCallback && isNewCollision)
{
gContactStartedCallback(m_manifoldPtr);
}
}

View File

@@ -13,6 +13,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_MANIFOLD_RESULT_H
#define BT_MANIFOLD_RESULT_H
@@ -28,81 +29,74 @@ class btManifoldPoint;
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper* colObj1Wrap, int partId1, int index1);
extern ContactAddedCallback gContactAddedCallback;
typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1);
extern ContactAddedCallback gContactAddedCallback;
//#define DEBUG_PART_INDEX 1
/// These callbacks are used to customize the algorith that combine restitution, friction, damping, Stiffness
typedef btScalar (*CalculateCombinedCallback)(const btCollisionObject* body0, const btCollisionObject* body1);
extern CalculateCombinedCallback gCalculateCombinedRestitutionCallback;
extern CalculateCombinedCallback gCalculateCombinedFrictionCallback;
extern CalculateCombinedCallback gCalculateCombinedRollingFrictionCallback;
extern CalculateCombinedCallback gCalculateCombinedSpinningFrictionCallback;
extern CalculateCombinedCallback gCalculateCombinedContactDampingCallback;
extern CalculateCombinedCallback gCalculateCombinedContactStiffnessCallback;
///btManifoldResult is a helper class to manage contact results.
class btManifoldResult : public btDiscreteCollisionDetectorInterface::Result
{
protected:
btPersistentManifold* m_manifoldPtr;
const btCollisionObjectWrapper* m_body0Wrap;
const btCollisionObjectWrapper* m_body1Wrap;
int m_partId0;
int m_partId0;
int m_partId1;
int m_index0;
int m_index1;
public:
btManifoldResult()
:
#ifdef DEBUG_PART_INDEX
m_partId0(-1),
m_partId1(-1),
m_index0(-1),
m_index1(-1)
#endif //DEBUG_PART_INDEX
m_closestPointDistanceThreshold(0)
btManifoldResult()
#ifdef DEBUG_PART_INDEX
:
m_partId0(-1),
m_partId1(-1),
m_index0(-1),
m_index1(-1)
#endif //DEBUG_PART_INDEX
{
}
btManifoldResult(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
btManifoldResult(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
virtual ~btManifoldResult(){};
virtual ~btManifoldResult() {};
void setPersistentManifold(btPersistentManifold* manifoldPtr)
void setPersistentManifold(btPersistentManifold* manifoldPtr)
{
m_manifoldPtr = manifoldPtr;
}
const btPersistentManifold* getPersistentManifold() const
const btPersistentManifold* getPersistentManifold() const
{
return m_manifoldPtr;
}
btPersistentManifold* getPersistentManifold()
btPersistentManifold* getPersistentManifold()
{
return m_manifoldPtr;
}
virtual void setShapeIdentifiersA(int partId0, int index0)
virtual void setShapeIdentifiersA(int partId0,int index0)
{
m_partId0 = partId0;
m_index0 = index0;
m_partId0=partId0;
m_index0=index0;
}
virtual void setShapeIdentifiersB(int partId1, int index1)
virtual void setShapeIdentifiersB( int partId1,int index1)
{
m_partId1 = partId1;
m_index1 = index1;
m_partId1=partId1;
m_index1=index1;
}
virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth);
SIMD_FORCE_INLINE void refreshContactPoints()
virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth);
SIMD_FORCE_INLINE void refreshContactPoints()
{
btAssert(m_manifoldPtr);
if (!m_manifoldPtr->getNumContacts())
@@ -112,11 +106,10 @@ public:
if (isSwapped)
{
m_manifoldPtr->refreshContactPoints(m_body1Wrap->getCollisionObject()->getWorldTransform(), m_body0Wrap->getCollisionObject()->getWorldTransform());
}
else
m_manifoldPtr->refreshContactPoints(m_body1Wrap->getCollisionObject()->getWorldTransform(),m_body0Wrap->getCollisionObject()->getWorldTransform());
} else
{
m_manifoldPtr->refreshContactPoints(m_body0Wrap->getCollisionObject()->getWorldTransform(), m_body1Wrap->getCollisionObject()->getWorldTransform());
m_manifoldPtr->refreshContactPoints(m_body0Wrap->getCollisionObject()->getWorldTransform(),m_body1Wrap->getCollisionObject()->getWorldTransform());
}
}
@@ -149,15 +142,9 @@ public:
return m_body1Wrap->getCollisionObject();
}
btScalar m_closestPointDistanceThreshold;
/// in the future we can let the user override the methods to combine restitution and friction
static btScalar calculateCombinedRestitution(const btCollisionObject* body0, const btCollisionObject* body1);
static btScalar calculateCombinedFriction(const btCollisionObject* body0, const btCollisionObject* body1);
static btScalar calculateCombinedRollingFriction(const btCollisionObject* body0, const btCollisionObject* body1);
static btScalar calculateCombinedSpinningFriction(const btCollisionObject* body0, const btCollisionObject* body1);
static btScalar calculateCombinedContactDamping(const btCollisionObject* body0, const btCollisionObject* body1);
static btScalar calculateCombinedContactStiffness(const btCollisionObject* body0, const btCollisionObject* body1);
static btScalar calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1);
static btScalar calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1);
};
#endif //BT_MANIFOLD_RESULT_H
#endif //BT_MANIFOLD_RESULT_H

View File

@@ -14,6 +14,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "LinearMath/btScalar.h"
#include "btSimulationIslandManager.h"
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
@@ -24,7 +25,8 @@ subject to the following restrictions:
//#include <stdio.h>
#include "LinearMath/btQuickprof.h"
btSimulationIslandManager::btSimulationIslandManager() : m_splitIslands(true)
btSimulationIslandManager::btSimulationIslandManager():
m_splitIslands(true)
{
}
@@ -32,47 +34,53 @@ btSimulationIslandManager::~btSimulationIslandManager()
{
}
void btSimulationIslandManager::initUnionFind(int n)
{
m_unionFind.reset(n);
m_unionFind.reset(n);
}
void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */, btCollisionWorld* colWorld)
void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld)
{
{
btOverlappingPairCache* pairCachePtr = colWorld->getPairCache();
const int numOverlappingPairs = pairCachePtr->getNumOverlappingPairs();
if (numOverlappingPairs)
{
btBroadphasePair* pairPtr = pairCachePtr->getOverlappingPairArrayPtr();
btBroadphasePair* pairPtr = pairCachePtr->getOverlappingPairArrayPtr();
for (int i=0;i<numOverlappingPairs;i++)
{
const btBroadphasePair& collisionPair = pairPtr[i];
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
for (int i = 0; i < numOverlappingPairs; i++)
if (((colObj0) && ((colObj0)->mergesSimulationIslands())) &&
((colObj1) && ((colObj1)->mergesSimulationIslands())))
{
const btBroadphasePair& collisionPair = pairPtr[i];
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
if (((colObj0) && ((colObj0)->mergesSimulationIslands())) &&
((colObj1) && ((colObj1)->mergesSimulationIslands())))
{
m_unionFind.unite((colObj0)->getIslandTag(),
(colObj1)->getIslandTag());
}
m_unionFind.unite((colObj0)->getIslandTag(),
(colObj1)->getIslandTag());
}
}
}
}
}
#ifdef STATIC_SIMULATION_ISLAND_OPTIMIZATION
void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld, btDispatcher* dispatcher)
void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
{
// put the index into m_controllers into m_tag
// put the index into m_controllers into m_tag
int index = 0;
{
int i;
for (i = 0; i < colWorld->getCollisionObjectArray().size(); i++)
for (i=0;i<colWorld->getCollisionObjectArray().size(); i++)
{
btCollisionObject* collisionObject = colWorld->getCollisionObjectArray()[i];
btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
//Adding filtering here
if (!collisionObject->isStaticOrKinematicObject())
{
@@ -84,29 +92,28 @@ void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld
}
// do the union find
initUnionFind(index);
initUnionFind( index );
findUnions(dispatcher, colWorld);
findUnions(dispatcher,colWorld);
}
void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
{
// put the islandId ('find' value) into m_tag
// put the islandId ('find' value) into m_tag
{
int index = 0;
int i;
for (i = 0; i < colWorld->getCollisionObjectArray().size(); i++)
for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
{
btCollisionObject* collisionObject = colWorld->getCollisionObjectArray()[i];
btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
if (!collisionObject->isStaticOrKinematicObject())
{
collisionObject->setIslandTag(m_unionFind.find(index));
collisionObject->setIslandTag( m_unionFind.find(index) );
//Set the correct object offset in Collision Object Array
m_unionFind.getElement(index).m_sz = i;
collisionObject->setCompanionId(-1);
index++;
}
else
} else
{
collisionObject->setIslandTag(-1);
collisionObject->setCompanionId(-2);
@@ -115,44 +122,49 @@ void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* col
}
}
#else //STATIC_SIMULATION_ISLAND_OPTIMIZATION
void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld, btDispatcher* dispatcher)
{
initUnionFind(int(colWorld->getCollisionObjectArray().size()));
// put the index into m_controllers into m_tag
#else //STATIC_SIMULATION_ISLAND_OPTIMIZATION
void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
{
initUnionFind( int (colWorld->getCollisionObjectArray().size()));
// put the index into m_controllers into m_tag
{
int index = 0;
int i;
for (i = 0; i < colWorld->getCollisionObjectArray().size(); i++)
for (i=0;i<colWorld->getCollisionObjectArray().size(); i++)
{
btCollisionObject* collisionObject = colWorld->getCollisionObjectArray()[i];
btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
collisionObject->setIslandTag(index);
collisionObject->setCompanionId(-1);
collisionObject->setHitFraction(btScalar(1.));
index++;
}
}
// do the union find
findUnions(dispatcher, colWorld);
findUnions(dispatcher,colWorld);
}
void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
{
// put the islandId ('find' value) into m_tag
// put the islandId ('find' value) into m_tag
{
int index = 0;
int i;
for (i = 0; i < colWorld->getCollisionObjectArray().size(); i++)
for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
{
btCollisionObject* collisionObject = colWorld->getCollisionObjectArray()[i];
btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
if (!collisionObject->isStaticOrKinematicObject())
{
collisionObject->setIslandTag(m_unionFind.find(index));
collisionObject->setIslandTag( m_unionFind.find(index) );
collisionObject->setCompanionId(-1);
}
else
} else
{
collisionObject->setIslandTag(-1);
collisionObject->setCompanionId(-2);
@@ -162,59 +174,56 @@ void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* col
}
}
#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
inline int getIslandId(const btPersistentManifold* lhs)
inline int getIslandId(const btPersistentManifold* lhs)
{
int islandId;
const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0());
const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1());
islandId = rcolObj0->getIslandTag() >= 0 ? rcolObj0->getIslandTag() : rcolObj1->getIslandTag();
islandId= rcolObj0->getIslandTag()>=0?rcolObj0->getIslandTag():rcolObj1->getIslandTag();
return islandId;
}
/// function object that routes calls to operator<
class btPersistentManifoldSortPredicate
{
public:
SIMD_FORCE_INLINE bool operator()(const btPersistentManifold* lhs, const btPersistentManifold* rhs) const
{
return getIslandId(lhs) < getIslandId(rhs);
}
public:
SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs ) const
{
return getIslandId(lhs) < getIslandId(rhs);
}
};
class btPersistentManifoldSortPredicateDeterministic
{
public:
SIMD_FORCE_INLINE bool operator()(const btPersistentManifold* lhs, const btPersistentManifold* rhs) const
{
return (
(getIslandId(lhs) < getIslandId(rhs)) || ((getIslandId(lhs) == getIslandId(rhs)) && lhs->getBody0()->getBroadphaseHandle()->m_uniqueId < rhs->getBody0()->getBroadphaseHandle()->m_uniqueId) || ((getIslandId(lhs) == getIslandId(rhs)) && (lhs->getBody0()->getBroadphaseHandle()->m_uniqueId == rhs->getBody0()->getBroadphaseHandle()->m_uniqueId) && (lhs->getBody1()->getBroadphaseHandle()->m_uniqueId < rhs->getBody1()->getBroadphaseHandle()->m_uniqueId)));
}
};
void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld)
void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld)
{
BT_PROFILE("islandUnionFindAndQuickSort");
btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
m_islandmanifold.resize(0);
//we are going to sort the unionfind array, and store the element id in the size
//afterwards, we clean unionfind, to make sure no-one uses it anymore
getUnionFind().sortIslands();
int numElem = getUnionFind().getNumElements();
int endIslandIndex = 1;
int endIslandIndex=1;
int startIslandIndex;
//update the sleeping state for bodies, if all are sleeping
for (startIslandIndex = 0; startIslandIndex < numElem; startIslandIndex = endIslandIndex)
for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
{
int islandId = getUnionFind().getElement(startIslandIndex).m_id;
for (endIslandIndex = startIslandIndex + 1; (endIslandIndex < numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId); endIslandIndex++)
for (endIslandIndex = startIslandIndex+1;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
{
}
@@ -223,69 +232,71 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisi
bool allSleeping = true;
int idx;
for (idx = startIslandIndex; idx < endIslandIndex; idx++)
for (idx=startIslandIndex;idx<endIslandIndex;idx++)
{
int i = getUnionFind().getElement(idx).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
// printf("error in island management\n");
// printf("error in island management\n");
}
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
if (colObj0->getActivationState() == ACTIVE_TAG ||
colObj0->getActivationState() == DISABLE_DEACTIVATION)
if (colObj0->getActivationState()== ACTIVE_TAG)
{
allSleeping = false;
}
if (colObj0->getActivationState()== DISABLE_DEACTIVATION)
{
allSleeping = false;
break;
}
}
}
if (allSleeping)
{
int idx;
for (idx = startIslandIndex; idx < endIslandIndex; idx++)
for (idx=startIslandIndex;idx<endIslandIndex;idx++)
{
int i = getUnionFind().getElement(idx).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
// printf("error in island management\n");
// printf("error in island management\n");
}
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
colObj0->setActivationState(ISLAND_SLEEPING);
colObj0->setActivationState( ISLAND_SLEEPING );
}
}
}
else
} else
{
int idx;
for (idx = startIslandIndex; idx < endIslandIndex; idx++)
for (idx=startIslandIndex;idx<endIslandIndex;idx++)
{
int i = getUnionFind().getElement(idx).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
// printf("error in island management\n");
// printf("error in island management\n");
}
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
if (colObj0->getActivationState() == ISLAND_SLEEPING)
if ( colObj0->getActivationState() == ISLAND_SLEEPING)
{
colObj0->setActivationState(WANTS_DEACTIVATION);
colObj0->setActivationState( WANTS_DEACTIVATION);
colObj0->setDeactivationTime(0.f);
}
}
@@ -293,30 +304,29 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisi
}
}
int i;
int maxNumManifolds = dispatcher->getNumManifolds();
//#define SPLIT_ISLANDS 1
//#ifdef SPLIT_ISLANDS
//#define SPLIT_ISLANDS 1
//#ifdef SPLIT_ISLANDS
//#endif //SPLIT_ISLANDS
//#endif //SPLIT_ISLANDS
for (i = 0; i < maxNumManifolds; i++)
for (i=0;i<maxNumManifolds ;i++)
{
btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
if (collisionWorld->getDispatchInfo().m_deterministicOverlappingPairs)
{
if (manifold->getNumContacts() == 0)
continue;
}
const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
///@todo: check sleeping conditions!
if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
///@todo: check sleeping conditions!
if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING))
{
//kinematic objects don't merge islands, but wake up all connected objects
if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
{
@@ -328,10 +338,10 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisi
if (colObj1->hasContactResponse())
colObj0->activate();
}
if (m_splitIslands)
{
if(m_splitIslands)
{
//filtering for response
if (dispatcher->needsResponse(colObj0, colObj1))
if (dispatcher->needsResponse(colObj0,colObj1))
m_islandmanifold.push_back(manifold);
}
}
@@ -339,27 +349,25 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisi
}
///@todo: this is random access, it can be walked 'cache friendly'!
void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback)
{
buildIslands(dispatcher, collisionWorld);
processIslands(dispatcher, collisionWorld, callback);
}
void btSimulationIslandManager::processIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback)
///@todo: this is random access, it can be walked 'cache friendly'!
void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback)
{
btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
int endIslandIndex = 1;
btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
buildIslands(dispatcher,collisionWorld);
int endIslandIndex=1;
int startIslandIndex;
int numElem = getUnionFind().getNumElements();
BT_PROFILE("processIslands");
if (!m_splitIslands)
if(!m_splitIslands)
{
btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer();
int maxNumManifolds = dispatcher->getNumManifolds();
callback->processIsland(&collisionObjects[0], collisionObjects.size(), manifold, maxNumManifolds, -1);
callback->processIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1);
}
else
{
@@ -367,21 +375,11 @@ void btSimulationIslandManager::processIslands(btDispatcher* dispatcher, btColli
// Sort the vector using predicate and std::sort
//std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate);
int numManifolds = int(m_islandmanifold.size());
int numManifolds = int (m_islandmanifold.size());
//tried a radix sort, but quicksort/heapsort seems still faster
//@todo rewrite island management
//btPersistentManifoldSortPredicateDeterministic sorts contact manifolds based on islandid,
//but also based on object0 unique id and object1 unique id
if (collisionWorld->getDispatchInfo().m_deterministicOverlappingPairs)
{
m_islandmanifold.quickSort(btPersistentManifoldSortPredicateDeterministic());
}
else
{
m_islandmanifold.quickSort(btPersistentManifoldSortPredicate());
}
m_islandmanifold.quickSort(btPersistentManifoldSortPredicate());
//m_islandmanifold.heapSort(btPersistentManifoldSortPredicate());
//now process all active islands (sets of manifolds for now)
@@ -391,49 +389,55 @@ void btSimulationIslandManager::processIslands(btDispatcher* dispatcher, btColli
//int islandId;
// printf("Start Islands\n");
// printf("Start Islands\n");
//traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated
for (startIslandIndex = 0; startIslandIndex < numElem; startIslandIndex = endIslandIndex)
for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
{
int islandId = getUnionFind().getElement(startIslandIndex).m_id;
bool islandSleeping = true;
for (endIslandIndex = startIslandIndex; (endIslandIndex < numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId); endIslandIndex++)
{
int i = getUnionFind().getElement(endIslandIndex).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
m_islandBodies.push_back(colObj0);
if (colObj0->isActive())
islandSleeping = false;
}
bool islandSleeping = true;
for (endIslandIndex = startIslandIndex;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
{
int i = getUnionFind().getElement(endIslandIndex).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
m_islandBodies.push_back(colObj0);
if (colObj0->isActive())
islandSleeping = false;
}
//find the accompanying contact manifold for this islandId
int numIslandManifolds = 0;
btPersistentManifold** startManifold = 0;
if (startManifoldIndex < numManifolds)
if (startManifoldIndex<numManifolds)
{
int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]);
if (curIslandId == islandId)
{
startManifold = &m_islandmanifold[startManifoldIndex];
for (endManifoldIndex = startManifoldIndex + 1; (endManifoldIndex < numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex])); endManifoldIndex++)
for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex]));endManifoldIndex++)
{
}
/// Process the actual simulation, only if not sleeping/deactivated
numIslandManifolds = endManifoldIndex - startManifoldIndex;
numIslandManifolds = endManifoldIndex-startManifoldIndex;
}
}
if (!islandSleeping)
{
callback->processIsland(&m_islandBodies[0], m_islandBodies.size(), startManifold, numIslandManifolds, islandId);
// printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds);
callback->processIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId);
// printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds);
}
if (numIslandManifolds)
{
startManifoldIndex = endManifoldIndex;
@@ -441,5 +445,6 @@ void btSimulationIslandManager::processIslands(btDispatcher* dispatcher, btColli
m_islandBodies.resize(0);
}
} // else if(!splitIslands)
} // else if(!splitIslands)
}

View File

@@ -26,42 +26,46 @@ class btCollisionWorld;
class btDispatcher;
class btPersistentManifold;
///SimulationIslandManager creates and handles simulation islands, using btUnionFind
class btSimulationIslandManager
{
btUnionFind m_unionFind;
btAlignedObjectArray<btPersistentManifold*> m_islandmanifold;
btAlignedObjectArray<btCollisionObject*> m_islandBodies;
btAlignedObjectArray<btPersistentManifold*> m_islandmanifold;
btAlignedObjectArray<btCollisionObject* > m_islandBodies;
bool m_splitIslands;
public:
btSimulationIslandManager();
virtual ~btSimulationIslandManager();
void initUnionFind(int n);
btUnionFind& getUnionFind() { return m_unionFind; }
void initUnionFind(int n);
btUnionFind& getUnionFind() { return m_unionFind;}
virtual void updateActivationState(btCollisionWorld* colWorld, btDispatcher* dispatcher);
virtual void storeIslandActivationState(btCollisionWorld* world);
virtual void updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher);
virtual void storeIslandActivationState(btCollisionWorld* world);
void findUnions(btDispatcher* dispatcher, btCollisionWorld* colWorld);
struct IslandCallback
void findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld);
struct IslandCallback
{
virtual ~IslandCallback(){};
virtual ~IslandCallback() {};
virtual void processIsland(btCollisionObject** bodies, int numBodies, class btPersistentManifold** manifolds, int numManifolds, int islandId) = 0;
virtual void processIsland(btCollisionObject** bodies,int numBodies,class btPersistentManifold** manifolds,int numManifolds, int islandId) = 0;
};
void buildAndProcessIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback);
void buildIslands(btDispatcher* dispatcher, btCollisionWorld* colWorld);
void buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback);
void buildIslands(btDispatcher* dispatcher,btCollisionWorld* colWorld);
void processIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback);
bool getSplitIslands()
{
return m_splitIslands;
@@ -70,6 +74,8 @@ public:
{
m_splitIslands = doSplitIslands;
}
};
#endif //BT_SIMULATION_ISLAND_MANAGER_H
#endif //BT_SIMULATION_ISLAND_MANAGER_H

View File

@@ -21,22 +21,23 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
//#include <stdio.h>
btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, bool isSwapped)
: btActivatingCollisionAlgorithm(ci, col0Wrap, col1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf),
m_isSwapped(isSwapped)
btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap, bool isSwapped)
: btActivatingCollisionAlgorithm(ci,col0Wrap,col1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf),
m_isSwapped(isSwapped)
{
const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped ? col1Wrap : col0Wrap;
const btCollisionObjectWrapper* boxObjWrap = m_isSwapped ? col0Wrap : col1Wrap;
if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObjWrap->getCollisionObject(), boxObjWrap->getCollisionObject()))
const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped? col1Wrap : col0Wrap;
const btCollisionObjectWrapper* boxObjWrap = m_isSwapped? col0Wrap : col1Wrap;
if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObjWrap->getCollisionObject(),boxObjWrap->getCollisionObject()))
{
m_manifoldPtr = m_dispatcher->getNewManifold(sphereObjWrap->getCollisionObject(), boxObjWrap->getCollisionObject());
m_manifoldPtr = m_dispatcher->getNewManifold(sphereObjWrap->getCollisionObject(),boxObjWrap->getCollisionObject());
m_ownManifold = true;
}
}
btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm()
{
if (m_ownManifold)
@@ -46,15 +47,17 @@ btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm()
}
}
void btSphereBoxCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btSphereBoxCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
(void)dispatchInfo;
(void)resultOut;
if (!m_manifoldPtr)
return;
const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* boxObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* boxObjWrap = m_isSwapped? body0Wrap : body1Wrap;
btVector3 pOnBox;
@@ -80,9 +83,10 @@ void btSphereBoxCollisionAlgorithm::processCollision(const btCollisionObjectWrap
resultOut->refreshContactPoints();
}
}
}
btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
@@ -93,26 +97,27 @@ btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject*
return btScalar(1.);
}
bool btSphereBoxCollisionAlgorithm::getSphereDistance(const btCollisionObjectWrapper* boxObjWrap, btVector3& pointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& sphereCenter, btScalar fRadius, btScalar maxContactDistance)
bool btSphereBoxCollisionAlgorithm::getSphereDistance(const btCollisionObjectWrapper* boxObjWrap, btVector3& pointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& sphereCenter, btScalar fRadius, btScalar maxContactDistance )
{
const btBoxShape* boxShape = (const btBoxShape*)boxObjWrap->getCollisionShape();
btVector3 const& boxHalfExtent = boxShape->getHalfExtentsWithoutMargin();
const btBoxShape* boxShape= (const btBoxShape*)boxObjWrap->getCollisionShape();
btVector3 const &boxHalfExtent = boxShape->getHalfExtentsWithoutMargin();
btScalar boxMargin = boxShape->getMargin();
penetrationDepth = 1.0f;
// convert the sphere position to the box's local space
btTransform const& m44T = boxObjWrap->getWorldTransform();
btTransform const &m44T = boxObjWrap->getWorldTransform();
btVector3 sphereRelPos = m44T.invXform(sphereCenter);
// Determine the closest point to the sphere center in the box
btVector3 closestPoint = sphereRelPos;
closestPoint.setX(btMin(boxHalfExtent.getX(), closestPoint.getX()));
closestPoint.setX(btMax(-boxHalfExtent.getX(), closestPoint.getX()));
closestPoint.setY(btMin(boxHalfExtent.getY(), closestPoint.getY()));
closestPoint.setY(btMax(-boxHalfExtent.getY(), closestPoint.getY()));
closestPoint.setZ(btMin(boxHalfExtent.getZ(), closestPoint.getZ()));
closestPoint.setZ(btMax(-boxHalfExtent.getZ(), closestPoint.getZ()));
closestPoint.setX( btMin(boxHalfExtent.getX(), closestPoint.getX()) );
closestPoint.setX( btMax(-boxHalfExtent.getX(), closestPoint.getX()) );
closestPoint.setY( btMin(boxHalfExtent.getY(), closestPoint.getY()) );
closestPoint.setY( btMax(-boxHalfExtent.getY(), closestPoint.getY()) );
closestPoint.setZ( btMin(boxHalfExtent.getZ(), closestPoint.getZ()) );
closestPoint.setZ( btMax(-boxHalfExtent.getZ(), closestPoint.getZ()) );
btScalar intersectionDist = fRadius + boxMargin;
btScalar contactDist = intersectionDist + maxContactDistance;
normal = sphereRelPos - closestPoint;
@@ -131,42 +136,42 @@ bool btSphereBoxCollisionAlgorithm::getSphereDistance(const btCollisionObjectWra
{
distance = -getSpherePenetration(boxHalfExtent, sphereRelPos, closestPoint, normal);
}
else //compute the penetration details
else //compute the penetration details
{
distance = normal.length();
normal /= distance;
}
pointOnBox = closestPoint + normal * boxMargin;
// v3PointOnSphere = sphereRelPos - (normal * fRadius);
// v3PointOnSphere = sphereRelPos - (normal * fRadius);
penetrationDepth = distance - intersectionDist;
// transform back in world space
btVector3 tmp = m44T(pointOnBox);
pointOnBox = tmp;
// tmp = m44T(v3PointOnSphere);
// v3PointOnSphere = tmp;
// tmp = m44T(v3PointOnSphere);
// v3PointOnSphere = tmp;
tmp = m44T.getBasis() * normal;
normal = tmp;
return true;
}
btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration(btVector3 const& boxHalfExtent, btVector3 const& sphereRelPos, btVector3& closestPoint, btVector3& normal)
btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btVector3 const &boxHalfExtent, btVector3 const &sphereRelPos, btVector3 &closestPoint, btVector3& normal )
{
//project the center of the sphere on the closest face of the box
btScalar faceDist = boxHalfExtent.getX() - sphereRelPos.getX();
btScalar minDist = faceDist;
closestPoint.setX(boxHalfExtent.getX());
normal.setValue(btScalar(1.0f), btScalar(0.0f), btScalar(0.0f));
closestPoint.setX( boxHalfExtent.getX() );
normal.setValue(btScalar(1.0f), btScalar(0.0f), btScalar(0.0f));
faceDist = boxHalfExtent.getX() + sphereRelPos.getX();
if (faceDist < minDist)
{
minDist = faceDist;
closestPoint = sphereRelPos;
closestPoint.setX(-boxHalfExtent.getX());
normal.setValue(btScalar(-1.0f), btScalar(0.0f), btScalar(0.0f));
closestPoint.setX( -boxHalfExtent.getX() );
normal.setValue(btScalar(-1.0f), btScalar(0.0f), btScalar(0.0f));
}
faceDist = boxHalfExtent.getY() - sphereRelPos.getY();
@@ -174,8 +179,8 @@ btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration(btVector3 const& bo
{
minDist = faceDist;
closestPoint = sphereRelPos;
closestPoint.setY(boxHalfExtent.getY());
normal.setValue(btScalar(0.0f), btScalar(1.0f), btScalar(0.0f));
closestPoint.setY( boxHalfExtent.getY() );
normal.setValue(btScalar(0.0f), btScalar(1.0f), btScalar(0.0f));
}
faceDist = boxHalfExtent.getY() + sphereRelPos.getY();
@@ -183,8 +188,8 @@ btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration(btVector3 const& bo
{
minDist = faceDist;
closestPoint = sphereRelPos;
closestPoint.setY(-boxHalfExtent.getY());
normal.setValue(btScalar(0.0f), btScalar(-1.0f), btScalar(0.0f));
closestPoint.setY( -boxHalfExtent.getY() );
normal.setValue(btScalar(0.0f), btScalar(-1.0f), btScalar(0.0f));
}
faceDist = boxHalfExtent.getZ() - sphereRelPos.getZ();
@@ -192,8 +197,8 @@ btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration(btVector3 const& bo
{
minDist = faceDist;
closestPoint = sphereRelPos;
closestPoint.setZ(boxHalfExtent.getZ());
normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(1.0f));
closestPoint.setZ( boxHalfExtent.getZ() );
normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(1.0f));
}
faceDist = boxHalfExtent.getZ() + sphereRelPos.getZ();
@@ -201,8 +206,8 @@ btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration(btVector3 const& bo
{
minDist = faceDist;
closestPoint = sphereRelPos;
closestPoint.setZ(-boxHalfExtent.getZ());
normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(-1.0f));
closestPoint.setZ( -boxHalfExtent.getZ() );
normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(-1.0f));
}
return minDist;

View File

@@ -28,20 +28,21 @@ class btPersistentManifold;
/// Other features are frame-coherency (persistent data) and collision response.
class btSphereBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_isSwapped;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_isSwapped;
public:
btSphereBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
virtual ~btSphereBoxCollisionAlgorithm();
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
@@ -49,25 +50,26 @@ public:
}
}
bool getSphereDistance(const btCollisionObjectWrapper* boxObjWrap, btVector3& v3PointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& v3SphereCenter, btScalar fRadius, btScalar maxContactDistance);
bool getSphereDistance( const btCollisionObjectWrapper* boxObjWrap, btVector3& v3PointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& v3SphereCenter, btScalar fRadius, btScalar maxContactDistance );
btScalar getSpherePenetration(btVector3 const& boxHalfExtent, btVector3 const& sphereRelPos, btVector3& closestPoint, btVector3& normal);
struct CreateFunc : public btCollisionAlgorithmCreateFunc
btScalar getSpherePenetration( btVector3 const &boxHalfExtent, btVector3 const &sphereRelPos, btVector3 &closestPoint, btVector3& normal );
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm));
if (!m_swapped)
{
return new (mem) btSphereBoxCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, false);
}
else
return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,false);
} else
{
return new (mem) btSphereBoxCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, true);
return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,true);
}
}
};
};
#endif //BT_SPHERE_BOX_COLLISION_ALGORITHM_H
#endif //BT_SPHERE_BOX_COLLISION_ALGORITHM_H

View File

@@ -12,7 +12,6 @@ subject to the following restrictions:
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#define CLEAR_MANIFOLD 1
#include "btSphereSphereCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
@@ -20,14 +19,14 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap)
: btActivatingCollisionAlgorithm(ci, col0Wrap, col1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf)
btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap)
: btActivatingCollisionAlgorithm(ci,col0Wrap,col1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf)
{
if (!m_manifoldPtr)
{
m_manifoldPtr = m_dispatcher->getNewManifold(col0Wrap->getCollisionObject(), col1Wrap->getCollisionObject());
m_manifoldPtr = m_dispatcher->getNewManifold(col0Wrap->getCollisionObject(),col1Wrap->getCollisionObject());
m_ownManifold = true;
}
}
@@ -41,7 +40,7 @@ btSphereSphereCollisionAlgorithm::~btSphereSphereCollisionAlgorithm()
}
}
void btSphereSphereCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btSphereSphereCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)dispatchInfo;
@@ -53,27 +52,27 @@ void btSphereSphereCollisionAlgorithm::processCollision(const btCollisionObjectW
btSphereShape* sphere0 = (btSphereShape*)col0Wrap->getCollisionShape();
btSphereShape* sphere1 = (btSphereShape*)col1Wrap->getCollisionShape();
btVector3 diff = col0Wrap->getWorldTransform().getOrigin() - col1Wrap->getWorldTransform().getOrigin();
btVector3 diff = col0Wrap->getWorldTransform().getOrigin()- col1Wrap->getWorldTransform().getOrigin();
btScalar len = diff.length();
btScalar radius0 = sphere0->getRadius();
btScalar radius1 = sphere1->getRadius();
#ifdef CLEAR_MANIFOLD
m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting
m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting
#endif
///iff distance positive, don't generate a new contact
if (len > (radius0 + radius1 + resultOut->m_closestPointDistanceThreshold))
if ( len > (radius0+radius1))
{
#ifndef CLEAR_MANIFOLD
resultOut->refreshContactPoints();
#endif //CLEAR_MANIFOLD
#endif //CLEAR_MANIFOLD
return;
}
///distance (negative means penetration)
btScalar dist = len - (radius0 + radius1);
btScalar dist = len - (radius0+radius1);
btVector3 normalOnSurfaceB(1, 0, 0);
btVector3 normalOnSurfaceB(1,0,0);
if (len > SIMD_EPSILON)
{
normalOnSurfaceB = diff / len;
@@ -82,18 +81,20 @@ void btSphereSphereCollisionAlgorithm::processCollision(const btCollisionObjectW
///point on A (worldspace)
///btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB;
///point on B (worldspace)
btVector3 pos1 = col1Wrap->getWorldTransform().getOrigin() + radius1 * normalOnSurfaceB;
btVector3 pos1 = col1Wrap->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB;
/// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->addContactPoint(normalOnSurfaceB, pos1, dist);
resultOut->addContactPoint(normalOnSurfaceB,pos1,dist);
#ifndef CLEAR_MANIFOLD
resultOut->refreshContactPoints();
#endif //CLEAR_MANIFOLD
#endif //CLEAR_MANIFOLD
}
btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)col0;
(void)col1;

View File

@@ -28,37 +28,39 @@ class btPersistentManifold;
/// Also provides the most basic sample for custom/user btCollisionAlgorithm
class btSphereSphereCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
public:
btSphereSphereCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap);
btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap);
btSphereSphereCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
virtual ~btSphereSphereCollisionAlgorithm();
struct CreateFunc : public btCollisionAlgorithmCreateFunc
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm));
return new (mem) btSphereSphereCollisionAlgorithm(0, ci, col0Wrap, col1Wrap);
return new(mem) btSphereSphereCollisionAlgorithm(0,ci,col0Wrap,col1Wrap);
}
};
};
#endif //BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H
#endif //BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H

View File

@@ -13,6 +13,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "btSphereTriangleCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
@@ -20,15 +21,15 @@ subject to the following restrictions:
#include "SphereTriangleDetector.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool swapped)
: btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf),
m_swapped(swapped)
btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool swapped)
: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf),
m_swapped(swapped)
{
if (!m_manifoldPtr)
{
m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
m_ownManifold = true;
}
}
@@ -42,35 +43,36 @@ btSphereTriangleCollisionAlgorithm::~btSphereTriangleCollisionAlgorithm()
}
}
void btSphereTriangleCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btSphereTriangleCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
return;
const btCollisionObjectWrapper* sphereObjWrap = m_swapped ? col1Wrap : col0Wrap;
const btCollisionObjectWrapper* triObjWrap = m_swapped ? col0Wrap : col1Wrap;
const btCollisionObjectWrapper* sphereObjWrap = m_swapped? col1Wrap : col0Wrap;
const btCollisionObjectWrapper* triObjWrap = m_swapped? col0Wrap : col1Wrap;
btSphereShape* sphere = (btSphereShape*)sphereObjWrap->getCollisionShape();
btTriangleShape* triangle = (btTriangleShape*)triObjWrap->getCollisionShape();
/// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->setPersistentManifold(m_manifoldPtr);
SphereTriangleDetector detector(sphere, triangle, m_manifoldPtr->getContactBreakingThreshold() + resultOut->m_closestPointDistanceThreshold);
SphereTriangleDetector detector(sphere,triangle, m_manifoldPtr->getContactBreakingThreshold());
btDiscreteCollisionDetectorInterface::ClosestPointInput input;
input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT); ///@todo: tighter bounds
input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);///@todo: tighter bounds
input.m_transformA = sphereObjWrap->getWorldTransform();
input.m_transformB = triObjWrap->getWorldTransform();
bool swapResults = m_swapped;
detector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw, swapResults);
detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw,swapResults);
if (m_ownManifold)
resultOut->refreshContactPoints();
}
btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;

View File

@@ -27,39 +27,43 @@ class btPersistentManifold;
/// Also provides the most basic sample for custom/user btCollisionAlgorithm
class btSphereTriangleCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_swapped;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_swapped;
public:
btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool swapped);
btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool swapped);
btSphereTriangleCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
virtual ~btSphereTriangleCollisionAlgorithm();
struct CreateFunc : public btCollisionAlgorithmCreateFunc
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm));
return new (mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold, ci, body0Wrap, body1Wrap, m_swapped);
return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_swapped);
}
};
};
#endif //BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
#endif //BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H

View File

@@ -15,60 +15,68 @@ subject to the following restrictions:
#include "btUnionFind.h"
btUnionFind::~btUnionFind()
{
Free();
}
btUnionFind::btUnionFind()
{
{
}
void btUnionFind::allocate(int N)
void btUnionFind::allocate(int N)
{
m_elements.resize(N);
}
void btUnionFind::Free()
void btUnionFind::Free()
{
m_elements.clear();
}
void btUnionFind::reset(int N)
void btUnionFind::reset(int N)
{
allocate(N);
for (int i = 0; i < N; i++)
{
m_elements[i].m_id = i;
m_elements[i].m_sz = 1;
}
for (int i = 0; i < N; i++)
{
m_elements[i].m_id = i; m_elements[i].m_sz = 1;
}
}
class btUnionFindElementSortPredicate
{
public:
bool operator()(const btElement& lhs, const btElement& rhs) const
{
return lhs.m_id < rhs.m_id;
}
public:
bool operator() ( const btElement& lhs, const btElement& rhs ) const
{
return lhs.m_id < rhs.m_id;
}
};
///this is a special operation, destroying the content of btUnionFind.
///it sorts the elements, based on island id, in order to make it easy to iterate over islands
void btUnionFind::sortIslands()
void btUnionFind::sortIslands()
{
//first store the original body index, and islandId
int numElements = m_elements.size();
for (int i = 0; i < numElements; i++)
for (int i=0;i<numElements;i++)
{
m_elements[i].m_id = find(i);
#ifndef STATIC_SIMULATION_ISLAND_OPTIMIZATION
m_elements[i].m_sz = i;
#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
}
// Sort the vector using predicate and std::sort
//std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate);
m_elements.quickSort(btUnionFindElementSortPredicate());
// Sort the vector using predicate and std::sort
//std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate);
m_elements.quickSort(btUnionFindElementSortPredicate());
}

View File

@@ -23,101 +23,107 @@ subject to the following restrictions:
///see for discussion of static island optimizations by Vroonsh here: http://code.google.com/p/bullet/issues/detail?id=406
#define STATIC_SIMULATION_ISLAND_OPTIMIZATION 1
struct btElement
struct btElement
{
int m_id;
int m_sz;
int m_id;
int m_sz;
};
///UnionFind calculates connected subsets
// Implements weighted Quick Union with path compression
// optimization: could use short ints instead of ints (halving memory, would limit the number of rigid bodies to 64k, sounds reasonable)
class btUnionFind
{
private:
btAlignedObjectArray<btElement> m_elements;
{
private:
btAlignedObjectArray<btElement> m_elements;
public:
btUnionFind();
~btUnionFind();
public:
btUnionFind();
~btUnionFind();
//this is a special operation, destroying the content of btUnionFind.
//it sorts the elements, based on island id, in order to make it easy to iterate over islands
void sortIslands();
//this is a special operation, destroying the content of btUnionFind.
//it sorts the elements, based on island id, in order to make it easy to iterate over islands
void sortIslands();
void reset(int N);
void reset(int N);
SIMD_FORCE_INLINE int getNumElements() const
{
return int(m_elements.size());
}
SIMD_FORCE_INLINE bool isRoot(int x) const
{
return (x == m_elements[x].m_id);
}
SIMD_FORCE_INLINE int getNumElements() const
{
return int(m_elements.size());
}
SIMD_FORCE_INLINE bool isRoot(int x) const
{
return (x == m_elements[x].m_id);
}
btElement& getElement(int index)
{
return m_elements[index];
}
const btElement& getElement(int index) const
{
return m_elements[index];
}
btElement& getElement(int index)
{
return m_elements[index];
}
const btElement& getElement(int index) const
{
return m_elements[index];
}
void allocate(int N);
void Free();
void allocate(int N);
void Free();
int find(int p, int q)
{
return (find(p) == find(q));
}
void unite(int p, int q)
{
int i = find(p), j = find(q);
if (i == j)
return;
int find(int p, int q)
{
return (find(p) == find(q));
}
void unite(int p, int q)
{
int i = find(p), j = find(q);
if (i == j)
return;
#ifndef USE_PATH_COMPRESSION
//weighted quick union, this keeps the 'trees' balanced, and keeps performance of unite O( log(n) )
if (m_elements[i].m_sz < m_elements[j].m_sz)
{
m_elements[i].m_id = j;
m_elements[j].m_sz += m_elements[i].m_sz;
}
else
{
m_elements[j].m_id = i;
m_elements[i].m_sz += m_elements[j].m_sz;
}
//weighted quick union, this keeps the 'trees' balanced, and keeps performance of unite O( log(n) )
if (m_elements[i].m_sz < m_elements[j].m_sz)
{
m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz;
}
else
{
m_elements[j].m_id = i; m_elements[i].m_sz += m_elements[j].m_sz;
}
#else
m_elements[i].m_id = j;
m_elements[j].m_sz += m_elements[i].m_sz;
#endif //USE_PATH_COMPRESSION
}
m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz;
#endif //USE_PATH_COMPRESSION
}
int find(int x)
{
//btAssert(x < m_N);
//btAssert(x >= 0);
while (x != m_elements[x].m_id)
{
//not really a reason not to use path compression, and it flattens the trees/improves find performance dramatically
#ifdef USE_PATH_COMPRESSION
const btElement* elementPtr = &m_elements[m_elements[x].m_id];
m_elements[x].m_id = elementPtr->m_id;
x = elementPtr->m_id;
#else //
x = m_elements[x].m_id;
#endif
int find(int x)
{
//btAssert(x < m_N);
//btAssert(x >= 0);
}
return x;
}
};
#endif //BT_UNION_FIND_H
while (x != m_elements[x].m_id)
{
//not really a reason not to use path compression, and it flattens the trees/improves find performance dramatically
#ifdef USE_PATH_COMPRESSION
const btElement* elementPtr = &m_elements[m_elements[x].m_id];
m_elements[x].m_id = elementPtr->m_id;
x = elementPtr->m_id;
#else//
x = m_elements[x].m_id;
#endif
//btAssert(x < m_N);
//btAssert(x >= 0);
}
return x;
}
};
#endif //BT_UNION_FIND_H

View File

@@ -15,23 +15,28 @@ subject to the following restrictions:
#include "btBox2dShape.h"
//{
void btBox2dShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
//{
void btBox2dShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
{
btTransformAabb(getHalfExtentsWithoutMargin(), getMargin(), t, aabbMin, aabbMax);
btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax);
}
void btBox2dShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
void btBox2dShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
//btScalar margin = btScalar(0.);
btVector3 halfExtents = getHalfExtentsWithMargin();
btScalar lx = btScalar(2.) * (halfExtents.x());
btScalar ly = btScalar(2.) * (halfExtents.y());
btScalar lz = btScalar(2.) * (halfExtents.z());
btScalar lx=btScalar(2.)*(halfExtents.x());
btScalar ly=btScalar(2.)*(halfExtents.y());
btScalar lz=btScalar(2.)*(halfExtents.z());
inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
mass/(btScalar(12.0)) * (lx*lx + lz*lz),
mass/(btScalar(12.0)) * (lx*lx + ly*ly));
inertia.setValue(mass / (btScalar(12.0)) * (ly * ly + lz * lz),
mass / (btScalar(12.0)) * (lx * lx + lz * lz),
mass / (btScalar(12.0)) * (lx * lx + ly * ly));
}

View File

@@ -23,9 +23,9 @@ subject to the following restrictions:
#include "LinearMath/btMinMax.h"
///The btBox2dShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space.
ATTRIBUTE_ALIGNED16(class)
btBox2dShape : public btPolyhedralConvexShape
ATTRIBUTE_ALIGNED16(class) btBox2dShape: public btPolyhedralConvexShape
{
//btVector3 m_boxHalfExtents1; //use m_implicitShapeDimensions instead
btVector3 m_centroid;
@@ -33,111 +33,122 @@ btBox2dShape : public btPolyhedralConvexShape
btVector3 m_normals[4];
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btVector3 getHalfExtentsWithMargin() const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
btVector3 margin(getMargin(), getMargin(), getMargin());
btVector3 margin(getMargin(),getMargin(),getMargin());
halfExtents += margin;
return halfExtents;
}
const btVector3& getHalfExtentsWithoutMargin() const
{
return m_implicitShapeDimensions; //changed in Bullet 2.63: assume the scaling and margin are included
return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included
}
virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
btVector3 margin(getMargin(), getMargin(), getMargin());
btVector3 margin(getMargin(),getMargin(),getMargin());
halfExtents += margin;
return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
}
SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const
SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const
{
const btVector3& halfExtents = getHalfExtentsWithoutMargin();
return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
}
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
{
const btVector3& halfExtents = getHalfExtentsWithoutMargin();
for (int i = 0; i < numVectors; i++)
for (int i=0;i<numVectors;i++)
{
const btVector3& vec = vectors[i];
supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
}
}
///a btBox2dShape is a flat 2D box in the X-Y plane (Z extents are zero)
btBox2dShape(const btVector3& boxHalfExtents)
: btPolyhedralConvexShape(),
m_centroid(0, 0, 0)
{
m_vertices[0].setValue(-boxHalfExtents.getX(), -boxHalfExtents.getY(), 0);
m_vertices[1].setValue(boxHalfExtents.getX(), -boxHalfExtents.getY(), 0);
m_vertices[2].setValue(boxHalfExtents.getX(), boxHalfExtents.getY(), 0);
m_vertices[3].setValue(-boxHalfExtents.getX(), boxHalfExtents.getY(), 0);
m_normals[0].setValue(0, -1, 0);
m_normals[1].setValue(1, 0, 0);
m_normals[2].setValue(0, 1, 0);
m_normals[3].setValue(-1, 0, 0);
///a btBox2dShape is a flat 2D box in the X-Y plane (Z extents are zero)
btBox2dShape( const btVector3& boxHalfExtents)
: btPolyhedralConvexShape(),
m_centroid(0,0,0)
{
m_vertices[0].setValue(-boxHalfExtents.getX(),-boxHalfExtents.getY(),0);
m_vertices[1].setValue(boxHalfExtents.getX(),-boxHalfExtents.getY(),0);
m_vertices[2].setValue(boxHalfExtents.getX(),boxHalfExtents.getY(),0);
m_vertices[3].setValue(-boxHalfExtents.getX(),boxHalfExtents.getY(),0);
m_normals[0].setValue(0,-1,0);
m_normals[1].setValue(1,0,0);
m_normals[2].setValue(0,1,0);
m_normals[3].setValue(-1,0,0);
btScalar minDimension = boxHalfExtents.getX();
if (minDimension > boxHalfExtents.getY())
if (minDimension>boxHalfExtents.getY())
minDimension = boxHalfExtents.getY();
setSafeMargin(minDimension);
m_shapeType = BOX_2D_SHAPE_PROXYTYPE;
btVector3 margin(getMargin(), getMargin(), getMargin());
btVector3 margin(getMargin(),getMargin(),getMargin());
m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
setSafeMargin(minDimension);
};
virtual void setMargin(btScalar collisionMargin)
{
//correct the m_implicitShapeDimensions for the margin
btVector3 oldMargin(getMargin(), getMargin(), getMargin());
btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
btVector3 oldMargin(getMargin(),getMargin(),getMargin());
btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
btConvexInternalShape::setMargin(collisionMargin);
btVector3 newMargin(getMargin(), getMargin(), getMargin());
btVector3 newMargin(getMargin(),getMargin(),getMargin());
m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
}
virtual void setLocalScaling(const btVector3& scaling)
virtual void setLocalScaling(const btVector3& scaling)
{
btVector3 oldMargin(getMargin(), getMargin(), getMargin());
btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
btVector3 oldMargin(getMargin(),getMargin(),getMargin());
btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
btConvexInternalShape::setLocalScaling(scaling);
m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
}
virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
int getVertexCount() const
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
int getVertexCount() const
{
return 4;
}
virtual int getNumVertices() const
virtual int getNumVertices()const
{
return 4;
}
@@ -152,70 +163,82 @@ public:
return &m_normals[0];
}
virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const
virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const
{
//this plane might not be aligned...
btVector4 plane;
getPlaneEquation(plane, i);
planeNormal = btVector3(plane.getX(), plane.getY(), plane.getZ());
btVector4 plane ;
getPlaneEquation(plane,i);
planeNormal = btVector3(plane.getX(),plane.getY(),plane.getZ());
planeSupport = localGetSupportingVertex(-planeNormal);
}
const btVector3& getCentroid() const
{
return m_centroid;
}
virtual int getNumPlanes() const
{
return 6;
}
}
virtual int getNumEdges() const
{
return 12;
}
virtual void getVertex(int i, btVector3& vtx) const
virtual void getVertex(int i,btVector3& vtx) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
vtx = btVector3(
halfExtents.x() * (1 - (i & 1)) - halfExtents.x() * (i & 1),
halfExtents.y() * (1 - ((i & 2) >> 1)) - halfExtents.y() * ((i & 2) >> 1),
halfExtents.z() * (1 - ((i & 4) >> 2)) - halfExtents.z() * ((i & 4) >> 2));
halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1),
halfExtents.y() * (1-((i&2)>>1)) - halfExtents.y() * ((i&2)>>1),
halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2));
}
virtual void getPlaneEquation(btVector4 & plane, int i) const
virtual void getPlaneEquation(btVector4& plane,int i) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
switch (i)
{
case 0:
plane.setValue(btScalar(1.), btScalar(0.), btScalar(0.), -halfExtents.x());
break;
case 1:
plane.setValue(btScalar(-1.), btScalar(0.), btScalar(0.), -halfExtents.x());
break;
case 2:
plane.setValue(btScalar(0.), btScalar(1.), btScalar(0.), -halfExtents.y());
break;
case 3:
plane.setValue(btScalar(0.), btScalar(-1.), btScalar(0.), -halfExtents.y());
break;
case 4:
plane.setValue(btScalar(0.), btScalar(0.), btScalar(1.), -halfExtents.z());
break;
case 5:
plane.setValue(btScalar(0.), btScalar(0.), btScalar(-1.), -halfExtents.z());
break;
default:
btAssert(0);
case 0:
plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x());
break;
case 1:
plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x());
break;
case 2:
plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y());
break;
case 3:
plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y());
break;
case 4:
plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z());
break;
case 5:
plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z());
break;
default:
btAssert(0);
}
}
virtual void getEdge(int i, btVector3& pa, btVector3& pb) const
virtual void getEdge(int i,btVector3& pa,btVector3& pb) const
//virtual void getEdge(int i,Edge& edge) const
{
int edgeVert0 = 0;
@@ -223,117 +246,126 @@ public:
switch (i)
{
case 0:
case 0:
edgeVert0 = 0;
edgeVert1 = 1;
break;
case 1:
break;
case 1:
edgeVert0 = 0;
edgeVert1 = 2;
break;
case 2:
edgeVert0 = 1;
edgeVert1 = 3;
break;
case 2:
edgeVert0 = 1;
edgeVert1 = 3;
break;
case 3:
edgeVert0 = 2;
edgeVert1 = 3;
break;
case 4:
edgeVert0 = 0;
edgeVert1 = 4;
break;
case 5:
edgeVert0 = 1;
edgeVert1 = 5;
break;
case 3:
edgeVert0 = 2;
edgeVert1 = 3;
break;
case 4:
edgeVert0 = 0;
edgeVert1 = 4;
break;
case 5:
edgeVert0 = 1;
edgeVert1 = 5;
break;
case 6:
edgeVert0 = 2;
edgeVert1 = 6;
break;
case 7:
edgeVert0 = 3;
edgeVert1 = 7;
break;
case 8:
edgeVert0 = 4;
edgeVert1 = 5;
break;
case 9:
edgeVert0 = 4;
edgeVert1 = 6;
break;
case 10:
edgeVert0 = 5;
edgeVert1 = 7;
break;
case 11:
edgeVert0 = 6;
edgeVert1 = 7;
break;
default:
btAssert(0);
break;
case 6:
edgeVert0 = 2;
edgeVert1 = 6;
break;
case 7:
edgeVert0 = 3;
edgeVert1 = 7;
break;
case 8:
edgeVert0 = 4;
edgeVert1 = 5;
break;
case 9:
edgeVert0 = 4;
edgeVert1 = 6;
break;
case 10:
edgeVert0 = 5;
edgeVert1 = 7;
break;
case 11:
edgeVert0 = 6;
edgeVert1 = 7;
break;
default:
btAssert(0);
}
getVertex(edgeVert0, pa);
getVertex(edgeVert1, pb);
getVertex(edgeVert0,pa );
getVertex(edgeVert1,pb );
}
virtual bool isInside(const btVector3& pt, btScalar tolerance) const
virtual bool isInside(const btVector3& pt,btScalar tolerance) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
//btScalar minDist = 2*tolerance;
bool result = (pt.x() <= (halfExtents.x() + tolerance)) &&
(pt.x() >= (-halfExtents.x() - tolerance)) &&
(pt.y() <= (halfExtents.y() + tolerance)) &&
(pt.y() >= (-halfExtents.y() - tolerance)) &&
(pt.z() <= (halfExtents.z() + tolerance)) &&
(pt.z() >= (-halfExtents.z() - tolerance));
bool result = (pt.x() <= (halfExtents.x()+tolerance)) &&
(pt.x() >= (-halfExtents.x()-tolerance)) &&
(pt.y() <= (halfExtents.y()+tolerance)) &&
(pt.y() >= (-halfExtents.y()-tolerance)) &&
(pt.z() <= (halfExtents.z()+tolerance)) &&
(pt.z() >= (-halfExtents.z()-tolerance));
return result;
}
//debugging
virtual const char* getName() const
virtual const char* getName()const
{
return "Box2d";
}
virtual int getNumPreferredPenetrationDirections() const
virtual int getNumPreferredPenetrationDirections() const
{
return 6;
}
virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
{
switch (index)
{
case 0:
penetrationVector.setValue(btScalar(1.), btScalar(0.), btScalar(0.));
break;
case 1:
penetrationVector.setValue(btScalar(-1.), btScalar(0.), btScalar(0.));
break;
case 2:
penetrationVector.setValue(btScalar(0.), btScalar(1.), btScalar(0.));
break;
case 3:
penetrationVector.setValue(btScalar(0.), btScalar(-1.), btScalar(0.));
break;
case 4:
penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(1.));
break;
case 5:
penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(-1.));
break;
default:
btAssert(0);
case 0:
penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.));
break;
case 1:
penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.));
break;
case 2:
penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.));
break;
case 3:
penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.));
break;
case 4:
penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.));
break;
case 5:
penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.));
break;
default:
btAssert(0);
}
}
};
#endif //BT_OBB_BOX_2D_SHAPE_H
#endif //BT_OBB_BOX_2D_SHAPE_H

View File

@@ -14,32 +14,38 @@ subject to the following restrictions:
*/
#include "btBoxShape.h"
btBoxShape::btBoxShape(const btVector3& boxHalfExtents)
: btPolyhedralConvexShape()
btBoxShape::btBoxShape( const btVector3& boxHalfExtents)
: btPolyhedralConvexShape()
{
m_shapeType = BOX_SHAPE_PROXYTYPE;
btVector3 margin(getMargin(), getMargin(), getMargin());
m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
setSafeMargin(boxHalfExtents);
btVector3 margin(getMargin(),getMargin(),getMargin());
m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
};
void btBoxShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
{
btTransformAabb(getHalfExtentsWithoutMargin(), getMargin(), t, aabbMin, aabbMax);
btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax);
}
void btBoxShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
//btScalar margin = btScalar(0.);
btVector3 halfExtents = getHalfExtentsWithMargin();
btScalar lx = btScalar(2.) * (halfExtents.x());
btScalar ly = btScalar(2.) * (halfExtents.y());
btScalar lz = btScalar(2.) * (halfExtents.z());
btScalar lx=btScalar(2.)*(halfExtents.x());
btScalar ly=btScalar(2.)*(halfExtents.y());
btScalar lz=btScalar(2.)*(halfExtents.z());
inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
mass/(btScalar(12.0)) * (lx*lx + lz*lz),
mass/(btScalar(12.0)) * (lx*lx + ly*ly));
inertia.setValue(mass / (btScalar(12.0)) * (ly * ly + lz * lz),
mass / (btScalar(12.0)) * (lx * lx + lz * lz),
mass / (btScalar(12.0)) * (lx * lx + ly * ly));
}

View File

@@ -23,102 +23,112 @@ subject to the following restrictions:
#include "LinearMath/btMinMax.h"
///The btBoxShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space.
ATTRIBUTE_ALIGNED16(class)
btBoxShape : public btPolyhedralConvexShape
ATTRIBUTE_ALIGNED16(class) btBoxShape: public btPolyhedralConvexShape
{
//btVector3 m_boxHalfExtents1; //use m_implicitShapeDimensions instead
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
BT_DECLARE_ALIGNED_ALLOCATOR();
btVector3 getHalfExtentsWithMargin() const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
btVector3 margin(getMargin(), getMargin(), getMargin());
btVector3 margin(getMargin(),getMargin(),getMargin());
halfExtents += margin;
return halfExtents;
}
const btVector3& getHalfExtentsWithoutMargin() const
{
return m_implicitShapeDimensions; //scaling is included, margin is not
return m_implicitShapeDimensions;//scaling is included, margin is not
}
virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
btVector3 margin(getMargin(), getMargin(), getMargin());
btVector3 margin(getMargin(),getMargin(),getMargin());
halfExtents += margin;
return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
}
SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const
SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const
{
const btVector3& halfExtents = getHalfExtentsWithoutMargin();
return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
}
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
{
const btVector3& halfExtents = getHalfExtentsWithoutMargin();
for (int i = 0; i < numVectors; i++)
for (int i=0;i<numVectors;i++)
{
const btVector3& vec = vectors[i];
supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
}
}
btBoxShape(const btVector3& boxHalfExtents);
btBoxShape( const btVector3& boxHalfExtents);
virtual void setMargin(btScalar collisionMargin)
{
//correct the m_implicitShapeDimensions for the margin
btVector3 oldMargin(getMargin(), getMargin(), getMargin());
btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
btVector3 oldMargin(getMargin(),getMargin(),getMargin());
btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
btConvexInternalShape::setMargin(collisionMargin);
btVector3 newMargin(getMargin(), getMargin(), getMargin());
btVector3 newMargin(getMargin(),getMargin(),getMargin());
m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
}
virtual void setLocalScaling(const btVector3& scaling)
virtual void setLocalScaling(const btVector3& scaling)
{
btVector3 oldMargin(getMargin(), getMargin(), getMargin());
btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
btVector3 oldMargin(getMargin(),getMargin(),getMargin());
btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
btConvexInternalShape::setLocalScaling(scaling);
m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
}
virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const
{
//this plane might not be aligned...
btVector4 plane;
getPlaneEquation(plane, i);
planeNormal = btVector3(plane.getX(), plane.getY(), plane.getZ());
btVector4 plane ;
getPlaneEquation(plane,i);
planeNormal = btVector3(plane.getX(),plane.getY(),plane.getZ());
planeSupport = localGetSupportingVertex(-planeNormal);
}
virtual int getNumPlanes() const
{
return 6;
}
virtual int getNumVertices() const
}
virtual int getNumVertices() const
{
return 8;
}
@@ -128,46 +138,49 @@ public:
return 12;
}
virtual void getVertex(int i, btVector3& vtx) const
virtual void getVertex(int i,btVector3& vtx) const
{
btVector3 halfExtents = getHalfExtentsWithMargin();
vtx = btVector3(
halfExtents.x() * (1 - (i & 1)) - halfExtents.x() * (i & 1),
halfExtents.y() * (1 - ((i & 2) >> 1)) - halfExtents.y() * ((i & 2) >> 1),
halfExtents.z() * (1 - ((i & 4) >> 2)) - halfExtents.z() * ((i & 4) >> 2));
halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1),
halfExtents.y() * (1-((i&2)>>1)) - halfExtents.y() * ((i&2)>>1),
halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2));
}
virtual void getPlaneEquation(btVector4 & plane, int i) const
virtual void getPlaneEquation(btVector4& plane,int i) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
switch (i)
{
case 0:
plane.setValue(btScalar(1.), btScalar(0.), btScalar(0.), -halfExtents.x());
break;
case 1:
plane.setValue(btScalar(-1.), btScalar(0.), btScalar(0.), -halfExtents.x());
break;
case 2:
plane.setValue(btScalar(0.), btScalar(1.), btScalar(0.), -halfExtents.y());
break;
case 3:
plane.setValue(btScalar(0.), btScalar(-1.), btScalar(0.), -halfExtents.y());
break;
case 4:
plane.setValue(btScalar(0.), btScalar(0.), btScalar(1.), -halfExtents.z());
break;
case 5:
plane.setValue(btScalar(0.), btScalar(0.), btScalar(-1.), -halfExtents.z());
break;
default:
btAssert(0);
case 0:
plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x());
break;
case 1:
plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x());
break;
case 2:
plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y());
break;
case 3:
plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y());
break;
case 4:
plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z());
break;
case 5:
plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z());
break;
default:
btAssert(0);
}
}
virtual void getEdge(int i, btVector3& pa, btVector3& pb) const
virtual void getEdge(int i,btVector3& pa,btVector3& pb) const
//virtual void getEdge(int i,Edge& edge) const
{
int edgeVert0 = 0;
@@ -175,117 +188,127 @@ public:
switch (i)
{
case 0:
case 0:
edgeVert0 = 0;
edgeVert1 = 1;
break;
case 1:
break;
case 1:
edgeVert0 = 0;
edgeVert1 = 2;
break;
case 2:
edgeVert0 = 1;
edgeVert1 = 3;
break;
case 2:
edgeVert0 = 1;
edgeVert1 = 3;
break;
case 3:
edgeVert0 = 2;
edgeVert1 = 3;
break;
case 4:
edgeVert0 = 0;
edgeVert1 = 4;
break;
case 5:
edgeVert0 = 1;
edgeVert1 = 5;
break;
case 3:
edgeVert0 = 2;
edgeVert1 = 3;
break;
case 4:
edgeVert0 = 0;
edgeVert1 = 4;
break;
case 5:
edgeVert0 = 1;
edgeVert1 = 5;
break;
case 6:
edgeVert0 = 2;
edgeVert1 = 6;
break;
case 7:
edgeVert0 = 3;
edgeVert1 = 7;
break;
case 8:
edgeVert0 = 4;
edgeVert1 = 5;
break;
case 9:
edgeVert0 = 4;
edgeVert1 = 6;
break;
case 10:
edgeVert0 = 5;
edgeVert1 = 7;
break;
case 11:
edgeVert0 = 6;
edgeVert1 = 7;
break;
default:
btAssert(0);
break;
case 6:
edgeVert0 = 2;
edgeVert1 = 6;
break;
case 7:
edgeVert0 = 3;
edgeVert1 = 7;
break;
case 8:
edgeVert0 = 4;
edgeVert1 = 5;
break;
case 9:
edgeVert0 = 4;
edgeVert1 = 6;
break;
case 10:
edgeVert0 = 5;
edgeVert1 = 7;
break;
case 11:
edgeVert0 = 6;
edgeVert1 = 7;
break;
default:
btAssert(0);
}
getVertex(edgeVert0, pa);
getVertex(edgeVert1, pb);
getVertex(edgeVert0,pa );
getVertex(edgeVert1,pb );
}
virtual bool isInside(const btVector3& pt, btScalar tolerance) const
virtual bool isInside(const btVector3& pt,btScalar tolerance) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
//btScalar minDist = 2*tolerance;
bool result = (pt.x() <= (halfExtents.x() + tolerance)) &&
(pt.x() >= (-halfExtents.x() - tolerance)) &&
(pt.y() <= (halfExtents.y() + tolerance)) &&
(pt.y() >= (-halfExtents.y() - tolerance)) &&
(pt.z() <= (halfExtents.z() + tolerance)) &&
(pt.z() >= (-halfExtents.z() - tolerance));
bool result = (pt.x() <= (halfExtents.x()+tolerance)) &&
(pt.x() >= (-halfExtents.x()-tolerance)) &&
(pt.y() <= (halfExtents.y()+tolerance)) &&
(pt.y() >= (-halfExtents.y()-tolerance)) &&
(pt.z() <= (halfExtents.z()+tolerance)) &&
(pt.z() >= (-halfExtents.z()-tolerance));
return result;
}
//debugging
virtual const char* getName() const
virtual const char* getName()const
{
return "Box";
}
virtual int getNumPreferredPenetrationDirections() const
virtual int getNumPreferredPenetrationDirections() const
{
return 6;
}
virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
{
switch (index)
{
case 0:
penetrationVector.setValue(btScalar(1.), btScalar(0.), btScalar(0.));
break;
case 1:
penetrationVector.setValue(btScalar(-1.), btScalar(0.), btScalar(0.));
break;
case 2:
penetrationVector.setValue(btScalar(0.), btScalar(1.), btScalar(0.));
break;
case 3:
penetrationVector.setValue(btScalar(0.), btScalar(-1.), btScalar(0.));
break;
case 4:
penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(1.));
break;
case 5:
penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(-1.));
break;
default:
btAssert(0);
case 0:
penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.));
break;
case 1:
penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.));
break;
case 2:
penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.));
break;
case 3:
penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.));
break;
case 4:
penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.));
break;
case 5:
penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.));
break;
default:
btAssert(0);
}
}
};
#endif //BT_OBB_BOX_MINKOWSKI_H
#endif //BT_OBB_BOX_MINKOWSKI_H

View File

@@ -22,11 +22,11 @@ subject to the following restrictions:
///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh)
: btTriangleMeshShape(meshInterface),
m_bvh(0),
m_triangleInfoMap(0),
m_useQuantizedAabbCompression(useQuantizedAabbCompression),
m_ownsBvh(false)
:btTriangleMeshShape(meshInterface),
m_bvh(0),
m_triangleInfoMap(0),
m_useQuantizedAabbCompression(useQuantizedAabbCompression),
m_ownsBvh(false)
{
m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
//construct bvh from meshInterface
@@ -37,15 +37,16 @@ btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInte
buildOptimizedBvh();
}
#endif //DISABLE_BVH
#endif //DISABLE_BVH
}
btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax, bool buildBvh)
: btTriangleMeshShape(meshInterface),
m_bvh(0),
m_triangleInfoMap(0),
m_useQuantizedAabbCompression(useQuantizedAabbCompression),
m_ownsBvh(false)
btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh)
:btTriangleMeshShape(meshInterface),
m_bvh(0),
m_triangleInfoMap(0),
m_useQuantizedAabbCompression(useQuantizedAabbCompression),
m_ownsBvh(false)
{
m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
//construct bvh from meshInterface
@@ -53,28 +54,30 @@ btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInte
if (buildBvh)
{
void* mem = btAlignedAlloc(sizeof(btOptimizedBvh), 16);
void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
m_bvh = new (mem) btOptimizedBvh();
m_bvh->build(meshInterface, m_useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax);
m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
m_ownsBvh = true;
}
#endif //DISABLE_BVH
#endif //DISABLE_BVH
}
void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin, const btVector3& aabbMax)
void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax)
{
m_bvh->refitPartial(m_meshInterface, aabbMin, aabbMax);
m_bvh->refitPartial( m_meshInterface,aabbMin,aabbMax );
m_localAabbMin.setMin(aabbMin);
m_localAabbMax.setMax(aabbMax);
}
void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin, const btVector3& aabbMax)
{
m_bvh->refit(m_meshInterface, aabbMin, aabbMax);
void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax)
{
m_bvh->refit( m_meshInterface, aabbMin,aabbMax );
recalcLocalAabb();
}
@@ -87,27 +90,27 @@ btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
}
}
void btBvhTriangleMeshShape::performRaycast(btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
void btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
{
struct MyNodeOverlapCallback : public btNodeOverlapCallback
struct MyNodeOverlapCallback : public btNodeOverlapCallback
{
btStridingMeshInterface* m_meshInterface;
btStridingMeshInterface* m_meshInterface;
btTriangleCallback* m_callback;
MyNodeOverlapCallback(btTriangleCallback* callback, btStridingMeshInterface* meshInterface)
: m_meshInterface(meshInterface),
m_callback(callback)
MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
:m_meshInterface(meshInterface),
m_callback(callback)
{
}
virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
{
btVector3 m_triangle[3];
const unsigned char* vertexbase;
const unsigned char *vertexbase;
int numverts;
PHY_ScalarType type;
int stride;
const unsigned char* indexbase;
const unsigned char *indexbase;
int indexstride;
int numfaces;
PHY_ScalarType indicestype;
@@ -123,65 +126,60 @@ void btBvhTriangleMeshShape::performRaycast(btTriangleCallback* callback, const
indicestype,
nodeSubPart);
unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
const btVector3& meshScaling = m_meshInterface->getScaling();
for (int j = 2; j >= 0; j--)
for (int j=2;j>=0;j--)
{
int graphicsindex;
switch (indicestype) {
case PHY_INTEGER: graphicsindex = gfxbase[j]; break;
case PHY_SHORT: graphicsindex = ((unsigned short*)gfxbase)[j]; break;
case PHY_UCHAR: graphicsindex = ((unsigned char*)gfxbase)[j]; break;
default: btAssert(0);
}
int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
if (type == PHY_FLOAT)
{
float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
m_triangle[j] = btVector3(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
}
else
{
double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
m_triangle[j] = btVector3(btScalar(graphicsbase[0]) * meshScaling.getX(), btScalar(graphicsbase[1]) * meshScaling.getY(), btScalar(graphicsbase[2]) * meshScaling.getZ());
double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());
}
}
/* Perform ray vs. triangle collision here */
m_callback->processTriangle(m_triangle, nodeSubPart, nodeTriangleIndex);
m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
}
};
MyNodeOverlapCallback myNodeCallback(callback, m_meshInterface);
MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
m_bvh->reportRayOverlappingNodex(&myNodeCallback, raySource, rayTarget);
m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget);
}
void btBvhTriangleMeshShape::performConvexcast(btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
void btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
{
struct MyNodeOverlapCallback : public btNodeOverlapCallback
struct MyNodeOverlapCallback : public btNodeOverlapCallback
{
btStridingMeshInterface* m_meshInterface;
btStridingMeshInterface* m_meshInterface;
btTriangleCallback* m_callback;
MyNodeOverlapCallback(btTriangleCallback* callback, btStridingMeshInterface* meshInterface)
: m_meshInterface(meshInterface),
m_callback(callback)
MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
:m_meshInterface(meshInterface),
m_callback(callback)
{
}
virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
{
btVector3 m_triangle[3];
const unsigned char* vertexbase;
const unsigned char *vertexbase;
int numverts;
PHY_ScalarType type;
int stride;
const unsigned char* indexbase;
const unsigned char *indexbase;
int indexstride;
int numfaces;
PHY_ScalarType indicestype;
@@ -197,79 +195,75 @@ void btBvhTriangleMeshShape::performConvexcast(btTriangleCallback* callback, con
indicestype,
nodeSubPart);
unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
const btVector3& meshScaling = m_meshInterface->getScaling();
for (int j = 2; j >= 0; j--)
for (int j=2;j>=0;j--)
{
int graphicsindex;
switch (indicestype) {
case PHY_INTEGER: graphicsindex = gfxbase[j]; break;
case PHY_SHORT: graphicsindex = ((unsigned short*)gfxbase)[j]; break;
case PHY_UCHAR: graphicsindex = ((unsigned char*)gfxbase)[j]; break;
default: btAssert(0);
}
int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
if (type == PHY_FLOAT)
{
float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
m_triangle[j] = btVector3(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
}
else
{
double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
m_triangle[j] = btVector3(btScalar(graphicsbase[0]) * meshScaling.getX(), btScalar(graphicsbase[1]) * meshScaling.getY(), btScalar(graphicsbase[2]) * meshScaling.getZ());
double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());
}
}
/* Perform ray vs. triangle collision here */
m_callback->processTriangle(m_triangle, nodeSubPart, nodeTriangleIndex);
m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
}
};
MyNodeOverlapCallback myNodeCallback(callback, m_meshInterface);
MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
m_bvh->reportBoxCastOverlappingNodex(&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
}
//perform bvh tree traversal and report overlapping triangles to 'callback'
void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
{
#ifdef DISABLE_BVH
//brute force traverse all triangles
btTriangleMeshShape::processAllTriangles(callback, aabbMin, aabbMax);
btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax);
#else
//first get all the nodes
struct MyNodeOverlapCallback : public btNodeOverlapCallback
struct MyNodeOverlapCallback : public btNodeOverlapCallback
{
btStridingMeshInterface* m_meshInterface;
btTriangleCallback* m_callback;
btVector3 m_triangle[3];
int m_numOverlap;
btStridingMeshInterface* m_meshInterface;
btTriangleCallback* m_callback;
btVector3 m_triangle[3];
MyNodeOverlapCallback(btTriangleCallback* callback, btStridingMeshInterface* meshInterface)
: m_meshInterface(meshInterface),
m_callback(callback),
m_numOverlap(0)
MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
:m_meshInterface(meshInterface),
m_callback(callback)
{
}
virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
{
m_numOverlap++;
const unsigned char* vertexbase;
const unsigned char *vertexbase;
int numverts;
PHY_ScalarType type;
int stride;
const unsigned char* indexbase;
const unsigned char *indexbase;
int indexstride;
int numfaces;
PHY_ScalarType indicestype;
m_meshInterface->getLockedReadOnlyVertexIndexBase(
&vertexbase,
@@ -282,62 +276,68 @@ void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback, c
indicestype,
nodeSubPart);
unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
btAssert(indicestype == PHY_INTEGER || indicestype == PHY_SHORT || indicestype == PHY_UCHAR);
unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT||indicestype==PHY_UCHAR);
const btVector3& meshScaling = m_meshInterface->getScaling();
for (int j = 2; j >= 0; j--)
for (int j=2;j>=0;j--)
{
int graphicsindex = indicestype == PHY_SHORT ? ((unsigned short*)gfxbase)[j] : indicestype == PHY_INTEGER ? gfxbase[j] : ((unsigned char*)gfxbase)[j];
int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:indicestype==PHY_INTEGER?gfxbase[j]:((unsigned char*)gfxbase)[j];
#ifdef DEBUG_TRIANGLE_MESH
printf("%d ,", graphicsindex);
#endif //DEBUG_TRIANGLE_MESH
printf("%d ,",graphicsindex);
#endif //DEBUG_TRIANGLE_MESH
if (type == PHY_FLOAT)
{
float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
m_triangle[j] = btVector3(
graphicsbase[0] * meshScaling.getX(),
graphicsbase[1] * meshScaling.getY(),
graphicsbase[2] * meshScaling.getZ());
graphicsbase[0]*meshScaling.getX(),
graphicsbase[1]*meshScaling.getY(),
graphicsbase[2]*meshScaling.getZ());
}
else
{
double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
m_triangle[j] = btVector3(
btScalar(graphicsbase[0]) * meshScaling.getX(),
btScalar(graphicsbase[1]) * meshScaling.getY(),
btScalar(graphicsbase[2]) * meshScaling.getZ());
btScalar(graphicsbase[0])*meshScaling.getX(),
btScalar(graphicsbase[1])*meshScaling.getY(),
btScalar(graphicsbase[2])*meshScaling.getZ());
}
#ifdef DEBUG_TRIANGLE_MESH
printf("triangle vertices:%f,%f,%f\n", triangle[j].x(), triangle[j].y(), triangle[j].z());
#endif //DEBUG_TRIANGLE_MESH
printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z());
#endif //DEBUG_TRIANGLE_MESH
}
m_callback->processTriangle(m_triangle, nodeSubPart, nodeTriangleIndex);
m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
}
};
MyNodeOverlapCallback myNodeCallback(callback, m_meshInterface);
MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
#endif//DISABLE_BVH
m_bvh->reportAabbOverlappingNodex(&myNodeCallback, aabbMin, aabbMax);
#endif //DISABLE_BVH
}
void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
{
if ((getLocalScaling() - scaling).length2() > SIMD_EPSILON)
{
btTriangleMeshShape::setLocalScaling(scaling);
buildOptimizedBvh();
}
if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
{
btTriangleMeshShape::setLocalScaling(scaling);
buildOptimizedBvh();
}
}
void btBvhTriangleMeshShape::buildOptimizedBvh()
void btBvhTriangleMeshShape::buildOptimizedBvh()
{
if (m_ownsBvh)
{
@@ -345,39 +345,43 @@ void btBvhTriangleMeshShape::buildOptimizedBvh()
btAlignedFree(m_bvh);
}
///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work
void* mem = btAlignedAlloc(sizeof(btOptimizedBvh), 16);
m_bvh = new (mem) btOptimizedBvh();
void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
m_bvh = new(mem) btOptimizedBvh();
//rebuild the bvh...
m_bvh->build(m_meshInterface, m_useQuantizedAabbCompression, m_localAabbMin, m_localAabbMax);
m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax);
m_ownsBvh = true;
}
void btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling)
void btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling)
{
btAssert(!m_bvh);
btAssert(!m_ownsBvh);
btAssert(!m_bvh);
btAssert(!m_ownsBvh);
m_bvh = bvh;
m_ownsBvh = false;
// update the scaling without rebuilding the bvh
if ((getLocalScaling() - scaling).length2() > SIMD_EPSILON)
{
btTriangleMeshShape::setLocalScaling(scaling);
}
m_bvh = bvh;
m_ownsBvh = false;
// update the scaling without rebuilding the bvh
if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
{
btTriangleMeshShape::setLocalScaling(scaling);
}
}
///fills the dataBuffer and returns the struct name (and 0 on failure)
const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
{
btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*)dataBuffer;
btCollisionShape::serialize(&trimeshData->m_collisionShapeData, serializer);
///fills the dataBuffer and returns the struct name (and 0 on failure)
const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
{
btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*) dataBuffer;
btCollisionShape::serialize(&trimeshData->m_collisionShapeData,serializer);
m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
trimeshData->m_collisionMargin = float(m_collisionMargin);
if (m_bvh && !(serializer->getSerializationFlags() & BT_SERIALIZE_NO_BVH))
if (m_bvh && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_BVH))
{
void* chunk = serializer->findPointer(m_bvh);
if (chunk)
@@ -386,77 +390,77 @@ const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* se
trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)chunk;
trimeshData->m_quantizedFloatBvh = 0;
#else
trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)chunk;
trimeshData->m_quantizedDoubleBvh = 0;
#endif //BT_USE_DOUBLE_PRECISION
}
else
trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)chunk;
trimeshData->m_quantizedDoubleBvh= 0;
#endif //BT_USE_DOUBLE_PRECISION
} else
{
#ifdef BT_USE_DOUBLE_PRECISION
trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
trimeshData->m_quantizedFloatBvh = 0;
#else
trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
trimeshData->m_quantizedDoubleBvh = 0;
#endif //BT_USE_DOUBLE_PRECISION
trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
trimeshData->m_quantizedDoubleBvh= 0;
#endif //BT_USE_DOUBLE_PRECISION
int sz = m_bvh->calculateSerializeBufferSizeNew();
btChunk* chunk = serializer->allocate(sz, 1);
btChunk* chunk = serializer->allocate(sz,1);
const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
serializer->finalizeChunk(chunk, structType, BT_QUANTIZED_BVH_CODE, m_bvh);
serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,m_bvh);
}
}
else
} else
{
trimeshData->m_quantizedFloatBvh = 0;
trimeshData->m_quantizedDoubleBvh = 0;
}
if (m_triangleInfoMap && !(serializer->getSerializationFlags() & BT_SERIALIZE_NO_TRIANGLEINFOMAP))
if (m_triangleInfoMap && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_TRIANGLEINFOMAP))
{
void* chunk = serializer->findPointer(m_triangleInfoMap);
if (chunk)
{
trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk;
}
else
} else
{
trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)serializer->getUniquePointer(m_triangleInfoMap);
int sz = m_triangleInfoMap->calculateSerializeBufferSize();
btChunk* chunk = serializer->allocate(sz, 1);
btChunk* chunk = serializer->allocate(sz,1);
const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
serializer->finalizeChunk(chunk, structType, BT_TRIANLGE_INFO_MAP, m_triangleInfoMap);
serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,m_triangleInfoMap);
}
}
else
} else
{
trimeshData->m_triangleInfoMap = 0;
}
// Fill padding with zeros to appease msan.
memset(trimeshData->m_pad3, 0, sizeof(trimeshData->m_pad3));
return "btTriangleMeshShapeData";
}
void btBvhTriangleMeshShape::serializeSingleBvh(btSerializer* serializer) const
void btBvhTriangleMeshShape::serializeSingleBvh(btSerializer* serializer) const
{
if (m_bvh)
{
int len = m_bvh->calculateSerializeBufferSizeNew(); //make sure not to use calculateSerializeBufferSize because it is used for in-place
btChunk* chunk = serializer->allocate(len, 1);
int len = m_bvh->calculateSerializeBufferSizeNew(); //make sure not to use calculateSerializeBufferSize because it is used for in-place
btChunk* chunk = serializer->allocate(len,1);
const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
serializer->finalizeChunk(chunk, structType, BT_QUANTIZED_BVH_CODE, (void*)m_bvh);
serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,(void*)m_bvh);
}
}
void btBvhTriangleMeshShape::serializeSingleTriangleInfoMap(btSerializer* serializer) const
void btBvhTriangleMeshShape::serializeSingleTriangleInfoMap(btSerializer* serializer) const
{
if (m_triangleInfoMap)
{
int len = m_triangleInfoMap->calculateSerializeBufferSize();
btChunk* chunk = serializer->allocate(len, 1);
btChunk* chunk = serializer->allocate(len,1);
const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
serializer->finalizeChunk(chunk, structType, BT_TRIANLGE_INFO_MAP, (void*)m_triangleInfoMap);
serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,(void*)m_triangleInfoMap);
}
}

View File

@@ -23,99 +23,103 @@ subject to the following restrictions:
///The btBvhTriangleMeshShape is a static-triangle mesh shape, it can only be used for fixed/non-moving objects.
///If you required moving concave triangle meshes, it is recommended to perform convex decomposition
///using HACD, see Bullet/Demos/ConvexDecompositionDemo.
///using HACD, see Bullet/Demos/ConvexDecompositionDemo.
///Alternatively, you can use btGimpactMeshShape for moving concave triangle meshes.
///btBvhTriangleMeshShape has several optimizations, such as bounding volume hierarchy and
///cache friendly traversal for PlayStation 3 Cell SPU.
///btBvhTriangleMeshShape has several optimizations, such as bounding volume hierarchy and
///cache friendly traversal for PlayStation 3 Cell SPU.
///It is recommended to enable useQuantizedAabbCompression for better memory usage.
///It takes a triangle mesh as input, for example a btTriangleMesh or btTriangleIndexVertexArray. The btBvhTriangleMeshShape class allows for triangle mesh deformations by a refit or partialRefit method.
///Instead of building the bounding volume hierarchy acceleration structure, it is also possible to serialize (save) and deserialize (load) the structure from disk.
///See Demos\ConcaveDemo\ConcavePhysicsDemo.cpp for an example.
ATTRIBUTE_ALIGNED16(class)
btBvhTriangleMeshShape : public btTriangleMeshShape
ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape
{
btOptimizedBvh* m_bvh;
btTriangleInfoMap* m_triangleInfoMap;
btOptimizedBvh* m_bvh;
btTriangleInfoMap* m_triangleInfoMap;
bool m_useQuantizedAabbCompression;
bool m_ownsBvh;
#ifdef __clang__
bool m_pad[11] __attribute__((unused)); ////need padding due to alignment
bool m_pad[11] __attribute__((unused));////need padding due to alignment
#else
bool m_pad[11]; ////need padding due to alignment
bool m_pad[11];////need padding due to alignment
#endif
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btBvhTriangleMeshShape(btStridingMeshInterface * meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true);
btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true);
///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
btBvhTriangleMeshShape(btStridingMeshInterface * meshInterface, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax, bool buildBvh = true);
btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true);
virtual ~btBvhTriangleMeshShape();
bool getOwnsBvh() const
bool getOwnsBvh () const
{
return m_ownsBvh;
}
void performRaycast(btTriangleCallback * callback, const btVector3& raySource, const btVector3& rayTarget);
void performConvexcast(btTriangleCallback * callback, const btVector3& boxSource, const btVector3& boxTarget, const btVector3& boxMin, const btVector3& boxMax);
virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
void performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget);
void performConvexcast (btTriangleCallback* callback, const btVector3& boxSource, const btVector3& boxTarget, const btVector3& boxMin, const btVector3& boxMax);
void refitTree(const btVector3& aabbMin, const btVector3& aabbMax);
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
void refitTree(const btVector3& aabbMin,const btVector3& aabbMax);
///for a fast incremental refit of parts of the tree. Note: the entire AABB of the tree will become more conservative, it never shrinks
void partialRefitTree(const btVector3& aabbMin, const btVector3& aabbMax);
void partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax);
//debugging
virtual const char* getName() const { return "BVHTRIANGLEMESH"; }
virtual const char* getName()const {return "BVHTRIANGLEMESH";}
virtual void setLocalScaling(const btVector3& scaling);
btOptimizedBvh* getOptimizedBvh()
virtual void setLocalScaling(const btVector3& scaling);
btOptimizedBvh* getOptimizedBvh()
{
return m_bvh;
}
void setOptimizedBvh(btOptimizedBvh * bvh, const btVector3& localScaling = btVector3(1, 1, 1));
void setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& localScaling=btVector3(1,1,1));
void buildOptimizedBvh();
void buildOptimizedBvh();
bool usesQuantizedAabbCompression() const
bool usesQuantizedAabbCompression() const
{
return m_useQuantizedAabbCompression;
return m_useQuantizedAabbCompression;
}
void setTriangleInfoMap(btTriangleInfoMap * triangleInfoMap)
void setTriangleInfoMap(btTriangleInfoMap* triangleInfoMap)
{
m_triangleInfoMap = triangleInfoMap;
}
const btTriangleInfoMap* getTriangleInfoMap() const
const btTriangleInfoMap* getTriangleInfoMap() const
{
return m_triangleInfoMap;
}
btTriangleInfoMap* getTriangleInfoMap()
{
return m_triangleInfoMap;
}
btTriangleInfoMap* getTriangleInfoMap()
{
return m_triangleInfoMap;
}
virtual int calculateSerializeBufferSize() const;
virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
virtual void serializeSingleBvh(btSerializer * serializer) const;
virtual void serializeSingleBvh(btSerializer* serializer) const;
virtual void serializeSingleTriangleInfoMap(btSerializer* serializer) const;
virtual void serializeSingleTriangleInfoMap(btSerializer * serializer) const;
};
// clang-format off
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
struct btTriangleMeshShapeData
{
@@ -134,11 +138,12 @@ struct btTriangleMeshShapeData
};
// clang-format on
SIMD_FORCE_INLINE int btBvhTriangleMeshShape::calculateSerializeBufferSize() const
SIMD_FORCE_INLINE int btBvhTriangleMeshShape::calculateSerializeBufferSize() const
{
return sizeof(btTriangleMeshShapeData);
}
#endif //BT_BVH_TRIANGLE_MESH_SHAPE_H
#endif //BT_BVH_TRIANGLE_MESH_SHAPE_H

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