Compare commits

..

231 Commits

Author SHA1 Message Date
360f831339 Apricot Branch
==============

Various changes from trunk that were somehow missed with merges, and
small code cleanups and fixes.
2008-09-04 15:45:25 +00:00
7e8a3aa0b1 svn merge -r 16334:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-09-04 00:32:15 +00:00
0d5ec24a05 Apricot Branch:
* Fix for wrong bone parent transform with duplis (multiplayer).
* Fix for crash on export when the bone in a bone parent relation
  does not exist anymore.
2008-09-04 00:16:34 +00:00
36d3ae12c6 svn merge -r 16328:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-09-02 06:36:19 +00:00
546127d964 svn merge -r 16297:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-09-01 07:03:09 +00:00
bb57536018 Apricot Branch: bugfix, setting manual glsl shaders did not release
displaylists, resulted in missing texture coordinates sometimes.
2008-08-29 14:13:26 +00:00
12200c39df Apricot Branch: better support for multiple scenes with glsl,
now it keeps shaders and lamps per scene.
2008-08-29 13:23:33 +00:00
87b7ba70a1 svn merge -r 16295:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-08-29 06:36:11 +00:00
4d368cb298 svn merge -r 16293:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-08-29 03:18:02 +00:00
7e4eb371fe svn merge -r 16287:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender still getting errors compiling blenderplayer 2008-08-28 23:12:29 +00:00
2b1c7fe4f9 Apricot Branch: didn't add these file in the last merge commit. 2008-08-28 11:26:40 +00:00
ce70b6bf3b Apricot Branch:
svn merge -r 16266:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender
2008-08-28 11:22:06 +00:00
1aa359ab7b Apricot Branch: bugfix for crash in shadow buffer rendering
combined with the shadow option for texfaces.
2008-08-27 19:12:08 +00:00
3a5b40d8f5 Apricot Branch: another fix for obcolor alpha - i can't seem
to get this right :).
2008-08-27 14:18:52 +00:00
7c9e742dce Apricot Branch: bugfix, broke bone parenting with yesterday's commit. 2008-08-27 13:10:16 +00:00
b5f48d78b4 Apricot Branch: still didn't get the glsl obcolor mixing right,
forgot why I did it the other way around before (because of alpha),
should work correct now.

Also, noticed I committed a bugfix before without knowing related
to creating material buckets with > 65k faces. The fix was provided
by Samuel Anjam, thanks!
2008-08-27 11:56:11 +00:00
b4680f5ca1 divide by zero for texture animation when start and end frames are the same 2008-08-27 07:12:07 +00:00
3b8ed715b6 svn merge -r 16246:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-08-27 03:41:29 +00:00
76f35a1e9a Apricot Branch: apply glsl object color before mist, makes more sense. 2008-08-26 17:53:04 +00:00
76d03839ac Apricot Branch: fix for a change I made to avoid doing where_is_pose
too often, didn't work correct for multiple objects sharing the same
armature.
2008-08-26 17:38:39 +00:00
4988a1b7f9 Apricot Branch: bugfix, crash in lights switching blender files,
accidentally removed a line of code that should have been kept.
2008-08-26 12:38:05 +00:00
01ba073f46 svn merge -r 16239:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-08-25 10:11:43 +00:00
b766ff4a00 svn merge -r 16227:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender
Thanks for bens state level commit will be able to clean up duplicate sensors a bit :)
http://members.optusnet.com.au/cjbarton/frank_logic.png
2008-08-24 02:46:03 +00:00
468b25e0f5 Apricot Branch: svn merge -r 16194:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-08-22 11:51:56 +00:00
8eedcfcc3f error in last commit 2008-08-22 02:33:19 +00:00
93fc6cb680 missing NULL check when game text meshes had no vertex colors 2008-08-22 00:54:22 +00:00
2d428a4061 partial merge because of conflicts
svn merge -16186:16194 https://svn.blender.org/svnroot/bf-blender/trunk/blender
2008-08-21 23:41:08 +00:00
2febacefe2 Apricot Branch: bugfix: glsl materials didn't get correct lights
when switching between blend files. Also took advantage of this
to remove some duplicate code related to accessing blender scenes.
2008-08-21 15:44:29 +00:00
c98ae55666 Apricot Branch: fix for bug #17435, only first 3 texture slots were
being used for finding second uv coordinate layer.
2008-08-21 13:40:40 +00:00
c594a6f25c Apricot Branch
==============

* Make lights and shadows work better with dupligroups, also in
  the game engine. Previously only one dupli would be created,
  and shadows didn't work well at all.
* Make normal maps + stencil work.
* Some glsl refresh and default material fixes.
2008-08-20 16:29:55 +00:00
2a9a2825f5 Apricot Branch: two bugfixes for issues with game engine draw
state switching textures and object color, showed as flickering.
2008-08-19 17:08:20 +00:00
10af2a3cd5 svn merge -r16186:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-08-19 12:19:38 +00:00
75570d9410 svn merge -r16170:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-08-19 04:00:22 +00:00
f98d21ca84 Apricot Branch
==============

* Added support for the realtime image "Anim" option for GLSL textures.
  Note that "Tiles" is not supported, i.e. it doesn't scale the texture
  for you, but that may even be desirable.
* Further there was some refactoring to remove duplicated and unused
  opengl texture code for GLSL.
2008-08-18 18:16:32 +00:00
9873352b02 Apricot Branch: fix some missing updates for GLSL materials
when changing world settings. Thanks Pablo for the patch,
though I implemented it a bit differently.
2008-08-18 13:25:27 +00:00
d535770c18 small error, stopped apricot building on linux-32bit 2008-08-18 13:06:33 +00:00
e174b34eef Apricot Branch
==============

svn merge -r16142:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender
2008-08-18 12:09:33 +00:00
9ffc3d065d Apricot Branch: bugfix, some meshes were not deforming anymore
after a recent commit.
2008-08-18 10:27:48 +00:00
009f826006 svn merge -r16106:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-08-17 01:24:40 +00:00
46131fbcd4 Apricot branch: a fix for flickering alpha, with multi-material
objects. Note that sorting is only between polygons with the same
material, so which material draws first is still arbitrary, but
consistent.
2008-08-14 17:12:40 +00:00
9cc4173c60 svn merge -r16064:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-08-14 09:18:57 +00:00
15fd22c6bd Apricot Branch
==============

svn merge -r16064:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender
2008-08-13 17:42:58 +00:00
b5fcdc4074 Apricot Branch
==============

Various cleanups and optimizations in the game engine:
* Remove some duplication in the RAS_RenderTools, and sync the blender
  and game player versions. Also avoid some opengl state changes.
* Don't make separate materials for triangles and quads, this distinction
  was moved to the mesh level. Also don't take some other irrelevant tface
  settings into account to avoid making more materials.
* Refactoring of mesh storage, should fix wrong normals on meshes that are
  reused. It also allows for joining together nearby meshes for speed, though
  that's disabled still because it doesn't work together correct yet with 
  ome features.
* Added a distinction for game objects to be either culled or set invisible,
  previously there was only one flag, which couldn't work correct.
* For parenting to bones, where_is_pose was executed multiple times per
  frame, now should be once per armature.
* Fix uninitialized intertia value in the physics system.
* Various warning fixes.
* Removed some conditionals in GLSL and other minor optimizations in the
  code. Also cache opengl uniform locations, and fix an invalid memory read.
* Avoid doing some math for GLSL lamps if it is not required.
2008-08-13 17:37:37 +00:00
17c81efced svn merge -r16009:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-08-12 12:57:18 +00:00
4043226064 svn merge -r15983:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-08-07 20:00:58 +00:00
81602d9b85 svn merge -r15968:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-08-06 00:37:27 +00:00
cd6cec0ebb svn merge -r15932:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-08-05 10:39:13 +00:00
56d3bfc28a apricot branch: fix a bug with the export of the second uv layer
to the game engine for GLSL.
2008-08-03 16:02:56 +00:00
0253b73fcb apricot branch: svn merge -r15868:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-08-03 14:46:34 +00:00
b818016d77 Apricot Branch
==============

svn merge -r15866:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender

Alpha blending and sorting changes, but also include some initial
support for GLSL lamps in dupligroups (only one duplicate works at
the moment).
2008-07-29 16:25:20 +00:00
c235327152 svn merge -r15780:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-07-29 15:27:03 +00:00
3131858792 svn merge -r15780:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-07-28 14:35:56 +00:00
42f957f910 svn merge -r15774:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-07-26 15:38:05 +00:00
b059a3c765 svn merge -r15731:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-07-26 04:36:09 +00:00
ad27c65d02 Apricot Branch: bugfix, don't let material ipo's update the
obcolor in the game engine, otherwise there's two ipo's
updating the same value, and which one is the final value is
undefined.
2008-07-25 10:55:10 +00:00
3801120669 Apricot Branch: GLSL
====================

* Added ObColor support, though it works different than for TexFaces.
  It used a new ObColor option in the materials, which will modulate
  the final color/alpha with the object color and alpha, also works
  in the render engine.
* Made GLSL check the ZTransp flag. A material is now only drawn
  transparent if this flag is enabled, a bit more consistent with the
  render engine.
* Fix for bug #17359: crash related subsurf + editmode GLSL.
2008-07-24 18:00:46 +00:00
848694370e svn merge -r15708:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-07-24 07:06:27 +00:00
3bb931789d Apricot Branch: fix for typo, no idea how this compiled with gcc.. 2008-07-23 22:23:28 +00:00
c6d799a3dc svn merge -r15698:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-07-23 07:17:20 +00:00
8c5249d9e1 these files missed the merge 2008-07-22 18:48:28 +00:00
788befdb57 svn merge -r15669:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-07-22 17:49:15 +00:00
2e695226d6 Apricot Branch: GLSL
====================

Added support for some world settings, updated docs.
* Ambient color
* Exposure/Range
* Mist (implementation should be optimized)

http://www.blender.org/development/current-projects/changes-since-246/realtime-glsl-materials/
2008-07-22 14:33:10 +00:00
c44670f6cd Apricot Branch
==============

* Made GLSL respect opaque/add/alpha/clip flags.
* Fix bug for all material types to correctly deal with
  different transp flags in a single mesh.
* Also made 3d view material alpha code a bit easier to
  understand.
2008-07-21 22:07:51 +00:00
4dc1ac2a7c Apricot Branch
==============

* More refactoring related to opengl lights, material state switching.
  Also moved init_gl_stuff into the gpu module and removed the copy in
  the game engine code.
* Fixed some issues with alpha drawing of GLSL materials in the 3d
  viewport, and fix a bug with alpha + xray drawing in the same scene,
  it should first do alpha, then xray, otherwise alpha doesn't blend
  correct with solid.
2008-07-21 19:27:59 +00:00
706c784b4c Apricot branch: missed file in last commit. 2008-07-21 15:56:42 +00:00
2b1c790951 Apricot Branch
==============

* Fix for crashes in last commit.
* Added "Refl" map input for textures.
2008-07-21 15:53:53 +00:00
63408f4e02 Apricot Branch
==============

* Refactoring in the texture and material drawing code, moving
  code into the gpu module, removing the duplicated versions
  in the game engine.
* Made game engine text drawing work with GLSL. It works based
  on filling in the default uv layer, so it requires a texture
  with the text image and mapped as uv's to work.
2008-07-21 15:35:11 +00:00
d09ce02613 svn merge -r15657:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blende 2008-07-21 13:11:56 +00:00
2c436f660b svn merge -r15643:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-07-20 17:25:12 +00:00
31cbb6060c svn merge -r15622:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-07-19 13:07:47 +00:00
d3758828b8 svn merge -r15608:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-07-18 13:06:49 +00:00
1a8fa0dd2a svn merge -r15597:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-07-16 23:02:23 +00:00
3e7c57098a Apricot: GLSL
=============

* Moved GLSL setting switching functions into the game engine
  python API so they work in the blender player, and can do
  better state switching.
* Also fixes bug #17331, error compiling with cmake.

* For the makers of test builds: it would be great if builds of
  this revision or newer for various platforms could be made
  available. We want to release a file to test and benchmark
  GLSL on different graphics cards, and we need test builds for
  this. Thanks!
2008-07-16 16:20:52 +00:00
42459bad2e Apricot Branch
==============

Fix for bug #17326: normal and tangents in the game engine
were computed different than other parts of Blender, this
makes the game engine use the same code as Blender.

Fix for part of bug #17307: normal maps not working correct
in editmode in some cases.

Fix for bug #17339: a crash on ATI cards in glTexSubImage1D
due to a mistake in the code. A patch to fix this was provided
by Yong Ch, thanks!
2008-07-16 13:53:39 +00:00
af4262d03f svn merge -r15566:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-07-16 07:10:33 +00:00
1c2fd65ddb Apricot Branch
==============

* Made in game switching of GLSL options work. There is still
  a one frame flicker that needs to be fixed.
* Added access to the estimated average framerate in the game
  engine: GameLogic.getAverageFrameRate().
* Added acces to the blender build info from python:
  Blender.Get("buildinfo")
* Various GLSL optimizations to allow more constant folding in
  the glsl compiler, use glsl shadow functions to do shadow,
  instead of own code, and fix an issue with opengl texture
  color range.
2008-07-15 21:59:46 +00:00
95fbf83423 Apricot: GLSL
=============

* Added options to disable lights, shaders, shadows, ramps,
  nodes and textures other than col/alpha for GLSL, in the
  Game menu.
* These have python access too to switch them in game, but
  it doesn't work correct yet with display lists enabled.
* Fix issue with light lagging behind, debug stats drawing in
  wrong color, and a number of other small fixes.
2008-07-14 23:26:38 +00:00
a1fea54c18 svn merge -r15560:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender
Also topology mirror crashed when using smooth + mirror. use eve->hash rather them eve->tmp.l for storing edit vert indices's.
2008-07-14 13:39:48 +00:00
00c4265bda svn merge -r15549:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender
- mainly to fix the free() crash with the file selector
2008-07-13 21:07:44 +00:00
151c8cc864 svn merge -r15528:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-07-12 13:41:18 +00:00
e84b2bd948 svn merge -r15518:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender
Also made shadow mesh draw in texture paint (venomGFX request)
2008-07-11 11:10:32 +00:00
06354f7f75 Apricot Branch
==============

svn merge -r15501:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender
2008-07-10 12:49:55 +00:00
ad103954e6 Apricot Branch: GLSL
====================

ATI fixes:
* Fix crash in glBitmap when rendering shadow buffers, it doesn't
  seem to like using that function with only a depth buffer.
* Workaround either a bug in the driver or Blender, but I couldn't
  find anything wrong, glVertexAttribPointerARB doesn't seem to
  work inside display lists, so now it uses immediate mode to
  create the list.
* Making deformable object for the game engine didn't check properly
  if there was actually a vertex group, causing some static objects
  to not use display lists.
* Also some cleanup in the game engine drawing code, replacing magic
  numbers with an enum.

The apricot demo seems to runs slightly faster on a ATI HD3750 than
NVidia 8800 GTS.
2008-07-09 19:15:15 +00:00
64e584fc0a svn merge -r15491:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender 2008-07-09 12:51:53 +00:00
437b207d3a Apricot Branch: GLSL
====================

* Some optimizations in the glsl shader code to avoid some
  matrix multiplications, and other floating point ops.
* Optimized game engine mesh deforming code a bit, and
  removed a bunch of unneeded/duplicated code.
* Fix for bugs #17289 and #17295, glsl compile errors.
2008-07-08 22:30:54 +00:00
f43c66f384 svn merge -r15478:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-07-08 18:32:42 +00:00
178be13f65 Apricot Branch: GLSL
====================

* Second attemp at solving exp/log incompatibility, some compilers
  don't seem to properly support preprocessor defines?
* Some simple optimizations to skip diffuse/specular/emit if they
  are set to zero.
2008-07-07 21:25:10 +00:00
9bf054b7a9 svn merge -r14639:14688 https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-07-07 21:18:30 +00:00
f26485d28d Apricot Branch: two minor optimizations to avoid unneeded shader
and opengl light state changes.
2008-07-07 17:14:44 +00:00
e232ea3a4f Apricot Branch:
Bugfix to make custom glsl shaders work with blender glsl shaders.
2008-07-07 15:12:42 +00:00
00703cc507 Apricot Branch
==============

Some optimizations:
* Only Apply mesh deformer if the mesh is actually modified, once
  per frame, this was done too often before.
* GLSL shader binding is now faster, only goes over dynamics inputs
  instead of all of them, and frees more memory after compiling too.
2008-07-07 13:57:29 +00:00
6f9c6e5c80 Apricot Branch: GLSL
====================

* Forgot to add/remove file in list commit.
* Game engine shadow optimization, don't use shaders for
  drawing into shadow buffer.
2008-07-07 11:58:09 +00:00
f78fb5d232 Apricot Branch: GLSL
====================

* Added a separate "Layer" option for lamp shadows, that only
  restricts which objects cast shadow, instead of receive light
  and shadow.
* Added exp/log compatibility for GLSL versions < 1.10.
* Check for depth texture extension before using it.
2008-07-07 10:52:09 +00:00
264546961a these escaped the merge 2008-07-06 15:02:21 +00:00
68927fdeb6 svn merge -r15426:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-07-06 14:38:27 +00:00
7499860e80 svn merge -r15399:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/
manually merged source/gameengine
2008-07-04 10:31:21 +00:00
9907889c8f svn merge -r15389:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-07-01 17:01:14 +00:00
f7d704fcf9 svn merge -r15360:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-06-29 22:08:23 +00:00
bca0d2d3e8 svn merge -r15355:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-06-26 12:43:10 +00:00
3282d85627 svn merge -r15339:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-06-25 16:25:01 +00:00
cf8807581e svn merge -r15309:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/
Note the mail message failed to come through for 15309 which was just a merge from trunk.
2008-06-24 05:02:01 +00:00
8a7eab4e56 Apricot Branch: bug in GLSL code generation for nodes. 2008-06-23 18:09:51 +00:00
Nathan Letwory
0a92399afd * 22:51 < ideasman-42> jesterKing, dude you totally over did it :0
- the solution was longer than needed. A simple letter addition (r) would've been enough.
2008-06-22 20:24:27 +00:00
Nathan Letwory
ef8d649815 * fix path problems when running .py scripts through menus
- \'s were not escaped, confusing execfile()
* small indentation fix in btools.py
2008-06-22 19:49:48 +00:00
deabd2a280 svn merge -r15265:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-06-22 18:12:46 +00:00
3afb8c19a3 Apricot Branch: fix bug with shaders going black. 2008-06-21 14:31:38 +00:00
b474283367 Apricot Branch: GLSL
====================

* Added initial support for shadow buffers, works in the 3d view and the
  game engine, but has known issues still:
	* Shadow buffers are made again for each 3d viewport unnecessarily.
	* No filtering.
	* There was a bug with some shaders going black, but can't reproduce
	  it anymore?

* Added support for layer lamps, though they're still always computed
  in the shader, this needs to be optimized.
* Added support for animating lamp position/rotation in the game engine.

* Fix issue with lamps giving negative light on the backside.
* Fix issue with specular + orthographic camera.
* Fix square spotlights.
* Potential workaround for a bug in the nvidia drivers with shader linking.
2008-06-21 10:33:12 +00:00
c302bfcb7c length of matrix was incorrect, some scripts may depend on this not sure if we can make the change in trunk. 2008-06-20 16:58:41 +00:00
13d00b5dcd Apricot Branch: issue in last commit with disabling/enabling GLSL
shaders, now it remembers the last one, should be more reliable.
2008-06-18 14:56:12 +00:00
ccc58f4491 Apricot Branch: Various Fixes
=============================

* Make GLSL shaders work in the game player.
* In the game engine with GLSL and no material assigned, it now falls
  back to texface materials. Not in the 3d view yet ..
* Fix memory when using the default material for GLSL.
* Fix another use of the builtin "smooth" name as a variable in the
  GLSL code, gives issue on ATI.
* Fix problem with the armature deform being applied to only one
  material bucket, gave floating triangles.
* Fix crash when setting .timeOffset through python without a parent.
* Use only gl*ARB functions so that GLSL also works on graphics cards
  that do not have opengl 2.0 but do have the extensions.
* Fix use of unitialized variable for render memory usage stats.
2008-06-18 13:44:29 +00:00
a790d75dc8 Apricot Branch: missed some files in last commit. 2008-06-18 11:16:40 +00:00
00b742cf20 Apricot Branch: svn merge -r 15249:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/
(game engine shape keys!)
2008-06-18 11:04:30 +00:00
dc8776cafb Apricot Branch: GLSL
====================

* Added GLSL vertex color support in the game engine.
* Added VCol Paint and VCol Light options.
2008-06-17 23:25:20 +00:00
8fd0b50602 Apricot Branch: GLSL
====================

* GLSL in the game engine now uses the second uv layer too.
2008-06-17 22:03:17 +00:00
a379a50f2b Apricot Branch: GLSL
====================

* Added support for the Material and Extended Material nodes.
* Added support for node groups.
* All nodes except Dynamic are now supported.
2008-06-17 21:23:51 +00:00
0fc753cfc5 Apricot Branch: GLSL
====================

* Internal change only: now it compiles the functions separately
  once and then links them together with the generated code, instead
  of appending the code and compiling them again for each material.
  Gives only slight compilation speedup unfortunately.
2008-06-17 18:36:29 +00:00
0b02b01892 Apricot Branch: GLSL
====================

* Added support for Ramps, diffuse + specular, all inputs
  and blending methods are supported.
2008-06-17 17:32:12 +00:00
3caa27fa24 Apricot Branch: GLSL
====================

* Added support for the ColorRamp node.
* Added less than / greather than in the Math node.
* Added support for all blend modes of the Mix node and
  all blend modes in the texture stack.
* Added more Map To support, now available:
  Col, Nor, Csp, Ref, Spec, Amb, Hard, Alpha, Emit.

* Possible fix for a GLEW / opengl include conflict on
  Mac OS X in playanim.c
2008-06-17 14:21:33 +00:00
e414d79808 Apricot Branch: svn merge -r 15241:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-06-17 10:16:52 +00:00
39cecc6044 Apricot Branch
==============

Refactoring of the use of opengl extensions and other drawing code
in the game engine, and cleaning up some hacks related to GLSL
integration. These changes will be merged into trunk too after this.

The game engine graphics demos & apricot level survived my tests,
but this could use some good testing of course.

For uses: please test with the options "Generate Display Lists" and
"Vertex Arrays" enabled, these should be the fastest and are supposed
to be "unreliable", but if that's the case that's probably due to bugs
that can be fixed.

* The game engine now also uses GLEW for extensions, replacing the
  custom opengl extensions code that was there. This means also that
  all extensions will now always be compiled in, regardless of the
  glext.h on the platform where compilation happens. Removes a lot
  of #ifdef's, but the runtime checks stay of course.
* Removed the WITHOUT_GLEXT environment variable. This was added to
  work around a specific bug and only disabled multitexturing anyway.
  It might also have caused a slowdown since it was retrieving the
  environment variable for every vertex in immediate mode (bug #13680).

* Refactored the code to allow drawing skinned meshes with vertex
  arrays too, removing some specific immediate mode drawing functions
  for this that only did extra normal calculation. Now it always splits
  vertices of flat faces instead.
* Refactored normal recalculation with some minor optimizations,
  required for the above change.
* Removed some outdated code behind the __NLA_OLDDEFORM #ifdef.
* Fixed various bugs in setting of multitexture coordinates and vertex
  attributes for vertex arrays. These were not being enabled/disabled
  correct according to the opengl spec, leading to crashes. Also tangent
  attributes used an immediate mode call for vertex arrays, which can't
  work.
* Fixed use of uninitialized variable in RAS_TexVert.

* Also in the GLSL shaders, removed conditional returns since some
  graphics cards don't support this. And fix a bug with orco's not
  being created in textured mode.
2008-06-16 16:58:12 +00:00
9725cb1186 svn merge -r15232:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-06-16 09:23:14 +00:00
6df6d6be72 Fix msvc compile error, reported by Wahooney 2008-06-15 17:55:23 +00:00
f1aa2edca3 svn merge -r15228:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-06-15 09:49:18 +00:00
38fa819cbd Apricot Branch:
Some optimizations to decrease game engine startup time:
* Exporting skinned meshes was doing O(n^2) lookups for vertices and
  deform weights, now uses same trick as regular meshes.
* Share GLSL shaders with the game engine so they don't have to be
  recompiled. This required changes to the rasterization in the game
  engine to add an option to use attributes instead of texture 
  coordinates.
* Some small optimizations in bullet BVH building, though could be
  improved more, since it takes about 50% of startup time still in
  my test .blend.
2008-06-14 23:51:01 +00:00
07e5dc0b96 svn merge -r15223:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-06-14 22:37:33 +00:00
38fe96e1ad svn merge -r15209:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-06-14 18:13:02 +00:00
6d62a18a51 Apricot Branch: GLSL
====================

* Added support for lamps and shaders. All material diffuse and
  specular shaders are supported, for lamps especially area light
  support is not there yet.

* Added support for these GLSL shaders in the game engine, though
  it is incomplete and somewhat of a hack. Specifically all the
  variables are completely static, which means moving lights, or
  animating material properties will not work.

* Enabling GLSL shaders is now different. They work in textured
  drawmode, and can be enabled in the Game menu with the option
  "Blender GLSL Materials"

Known issues:
* The GLSL shaders don't always update correct on light changes.
* The game player appears to crash with these GLSL shaders, while
  regular blender works fine.
2008-06-13 21:24:21 +00:00
9fb4cbc668 missing call to EM_free_index_arrays() 2008-06-13 12:54:44 +00:00
a40c48ce78 Topology Mirror. Find mirror verts based on topology, ignoring vertex location,
Currently works with transform and weight painting.
Tested with 5 peach characters and Suzanne (without eyes), rely's on both verts being uniquely positioned in relation to the surrounding edge topology. useful when weight painting asymmetric characters.
2008-06-13 12:33:35 +00:00
82863827ca svn merge -r15173:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-06-12 15:05:52 +00:00
8a84639207 moved uv_center from drawimage.c to editface.c, removed extern defines needed for transform, also replaced G.vd->around with t->around 2008-06-11 05:46:10 +00:00
02ca9d55e6 fix for some errors with UV mirror when the face/vertex connection map could not be generated. 2008-06-10 10:32:16 +00:00
3304f85e0a UV Mirror now detects the bounding box of UV islands to get the mirror center
Access mirror now from the UVs menu (dont use mesh mirror)
Added vertical mirroring (can only do U or V mirror)
 - mirror dosnt work with quad constrained or PET yet.
2008-06-10 09:42:33 +00:00
88dd8e21d1 svn merge -r15165:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-06-09 15:55:04 +00:00
a2147e1089 ipo ghosting option, request from venomgfx to help adjusting ipos with a reference to the original (enable in the view menu -> Ghost Editmode) 2008-06-08 20:47:34 +00:00
e7fc44da7e svn merge -r15150:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-06-08 20:43:22 +00:00
3ac5c5e770 edge loop side/del uv only worked with a maximum of 4 faces connected to a vert.
now make a list that can have any number of face/uvs.
2008-06-08 02:38:38 +00:00
326f7060f3 evil tri-count stats, game people want, counts tri's while drawing, but no other fast way to do this. 2008-06-08 01:00:09 +00:00
444318431b flag name should be UVCALC_TRANSFORM_CORRECT rather then UVCALC_NO_TRANSFORM_CORRECT 2008-06-07 18:19:27 +00:00
e6c26fbb4e Option to correct for UV distortion when edge sliding when the surrounding faces share the same UV location (else uv interpolation is ignored for that vert).
Enable this from the UV Calculation panel, "Transform Correction" button.
This also means deleting edge loops keeps uvs where possible (even when Transform Correction isnt enabled).
Works for multiple UV layers.
2008-06-07 17:48:35 +00:00
dafafabc7c svn merge -r15143:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-06-07 17:39:01 +00:00
94a087ce54 missed this file 2008-06-05 23:01:03 +00:00
516635ea76 svn merge -r15122:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-06-05 22:18:13 +00:00
beafbe21f4 Apricot Branch: add -fvisibility=hidden if supported, to prevent conflicts
with bullet symbols used by b2cs. Note msvc does this already. Support was
added to Make/CMake/Scons, though it's pretty ugly code with shell commands,
couldn't figure out how to do it nicer.
2008-06-04 21:29:47 +00:00
449dc4951c svn merge -r15115:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-06-04 16:41:09 +00:00
fedaaa1629 venomgfx needs a center other then 0.5 for some UV maps, use the 2d cursor as a temp soluition 2008-06-04 15:06:24 +00:00
d3f6b7e6a7 UV transform X axis mirror 2008-06-04 14:57:06 +00:00
dfbdaabef8 svn merge -r15095:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-06-04 12:32:47 +00:00
6b4d33b634 experemental support for key up events with space handelers. 2008-06-04 12:27:32 +00:00
7e714967e9 undo temp change to try and solve [#13605] GameEngine corrupts Pose data 2008-06-03 10:05:09 +00:00
3a4f0bcda2 svn merge -r15057:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-06-03 09:42:18 +00:00
1911f3f8ed bugfix, one texture was placed in the list twice 2008-06-02 16:29:48 +00:00
72166c2192 Remove extra semi-colon (MSVC was shocking on that, probably thinking it was a null instruction mixed with variables or some other silly reasons). 2008-05-31 11:11:51 +00:00
2ae427d55f Apricot Branch: refactoring of the glsl code, removing unused code
and changing code generation to require fewer function calls.
2008-05-30 14:56:23 +00:00
555dff358f svn merge -r14995:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-05-30 09:20:34 +00:00
39da0b7619 Apricot Branch: basic material texture alpha support. 2008-05-29 13:07:45 +00:00
0d44ba56bb Transform Snap
Editmode snapping to derived mesh.

Now all the fun snapping options (snapping to faces, verts, edges) are supported inside edit mode and you can also snap to subsurfed faces, virtual array copies, ... from inside edit mode.
2008-05-29 10:51:10 +00:00
1aff5de748 Small fix to derivedmesh for snapping: don't create origindex for
editmesh derivedmesh since it's not being filled correct anyway.
2008-05-29 09:23:18 +00:00
0b01c20bed fixes from trunk 2008-05-27 15:15:50 +00:00
81cbfc5c9e Fixing snapping normal alignment for non-uniformly scaled objects. 2008-05-27 14:31:29 +00:00
c5cc2d8fc2 Fix for #12633: crash with scaling of non power of two textures in
the apricot glsl code.
2008-05-27 10:17:25 +00:00
6ab7d3e1b1 svn merge -r14980:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/
also removed some old transform snap stuff that isnt needed now.
2008-05-27 09:22:59 +00:00
1a91266864 uv snapping feature for venomgfx, this snaps selected UV coords to
visible,unselected coords. access from the shift+s menu
2008-05-26 14:38:51 +00:00
f36b06e17a svn merge -r14921:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-05-26 13:14:19 +00:00
ff0833412c added uvlayer and material support for grid reduction, (for apricot
terrain)
2008-05-24 22:38:02 +00:00
9c8bec4aec fix for triangle lightmap packing and remove some prints 2008-05-23 00:04:31 +00:00
d34091386e added a fairly spesific function to Mesh.c that gets the contrast of the texture under a face (should move to Image.c)
added an option for lightmap UV packer that scales down faces with low light contrast for 2Pass-Adaptive-ShadowMapsTM :)
2008-05-22 23:25:32 +00:00
3dcdf75f50 object: ray - boundbox intersection test
snap: use the above instead (giving up padding but getting rid of stupid projection problems)
2008-05-22 15:20:14 +00:00
3f303b092b experemental ID versioning to know what data has changed to avoid re-exporting entire levels. (with py api)
also scriptlinks for lamps and material updates.
2008-05-22 13:32:51 +00:00
2bab988b85 merge from trunk for venomgfx 2008-05-22 09:29:42 +00:00
59fd401ddf Apricot Branch: svn merge -r 14899:HEAD 2008-05-22 09:11:52 +00:00
829ad0e999 tool to interactively propotype animations using python and the NLA 2008-05-22 09:07:37 +00:00
4dd421204b Snaping
Bypass boundbox test if camera is inside bounding box
2008-05-21 16:42:46 +00:00
06cee7fef9 mesh check for duplis, when snapping 2008-05-21 13:43:39 +00:00
10f7cb934f Snapping on duplis 2008-05-21 12:57:22 +00:00
baf0b79446 +comment 2008-05-21 10:44:25 +00:00
61fa2043e5 Apricot Branch
==============

Fixes for compiling on Windows related to glew, snprintf
and the outliner, tested with CMake + MSVC 2008.
2008-05-20 13:31:31 +00:00
edbd5d9d42 Apricot Branch
==============

- CMake build system support for GLSL.
2008-05-20 12:45:54 +00:00
94028bc126 Apricot Branch: svn merge -r 14875:HEAD 2008-05-19 18:41:13 +00:00
30142a3b92 Apricot Branch
==============

- Memory usage limit for undo, specified in megabytes, the default 0
  means unlimited.
- Multiple undo levels for image painting. Works separate from global
  undo similar to editmode undo, and undo for multiple images is
  supported.
2008-05-19 18:37:31 +00:00
c29a95acf9 Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily)

* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.

Removing ugly apricot hack for drop to ground (YAY!)
2008-05-19 14:16:18 +00:00
ee74a440eb Arith:
- axis angle to quat conversion function
	- short to float / float to short normals conversion function (eventually, we could go over the go and replace copy/pasted code everywhere)
	- ray triangle intersection (to complement the line triangle intersection function)
	
View:
	- viewray / viewline (get near plane point under mouse and ray normal/far point)


Particles:
	- extract viewline from brush_add function
2008-05-19 10:13:16 +00:00
ee1bb9e26d added option to apply a spacialy divided grid of images and UV's per mesh. useful for baking terrain in apricot 2008-05-17 00:02:08 +00:00
b8f1393d4e Apricot Branch: svn merge -r 14866:HEAD 2008-05-16 21:38:51 +00:00
fe78d082bd added library loading where you can select many libraries or a directory of libs and load them without appending or linking anything.
This is so the outliner can be used to link in data from existing libraries without having to open each blend file.
2008-05-16 20:21:40 +00:00
7861cd7c1b Centralize handling of individual center for rotations 2008-05-16 15:00:21 +00:00
c3bb4e1961 Apricot Branch: svn merge -r 14842:HEAD 2008-05-16 11:05:50 +00:00
03d1ef41c7 Merging libmp3lamp from trunk (slipped between the cracks) 2008-05-16 10:43:49 +00:00
defc4d2dc7 first layer icon displayed lighter 2008-05-16 10:23:18 +00:00
d721c743cb added a menu for selecting which types to draw for outliner library members 2008-05-16 09:30:07 +00:00
f9b0ba6ef3 basic support for browsing libraries from the outliner, clicking on a group links it in and applies it to the active object as a dupli or adds the object if none are
active.
also made dupligroup drawing use the most basic drawtype from teh dupli of the object that instances it. this is so apricot can have low poly objects as lods but not 
have overlaping rendering.
2008-05-15 23:49:43 +00:00
56cba0bb76 Apricot Branch
==============

svn merge -r 14780:HEAD
2008-05-14 16:59:17 +00:00
e66002841d make smooth work with mirror option 2008-05-12 21:41:00 +00:00
cff63412cc fix for error when resolving conflicts 2008-05-12 21:19:24 +00:00
8e4f1a7705 merge 14760:HEAD 2008-05-10 17:32:31 +00:00
6546305b60 merge from trunk 2008-05-09 11:10:37 +00:00
3181fcb984 svn merge -r14718:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender/ 2008-05-08 07:57:39 +00:00
7d7991ccaf apricot request layer colors for active/used/empty color channels, colors are not that nice at the moment, so lucky we have artists! 2008-05-07 21:21:48 +00:00
f969d560c0 svn merge -r 14688:HEAD 2008-05-07 08:59:43 +00:00
7fbf8080e6 Apricot Branch
==============

svn merge -r 14688:14706

Also, use vertex arrays for drawing points, and a temporary hack to
reduce the number of points.
2008-05-06 16:01:31 +00:00
70f7b998fc Apricot branch bugfix: texture slots changes had a bug that could make
drawing them crash.
2008-05-05 19:19:27 +00:00
63b73469d8 raised maximum texture slots to 18 2008-05-05 15:40:16 +00:00
7bb6187209 merge from trunk 2008-05-05 13:35:12 +00:00
5c97dfbca1 moved snap button to ground into header until it can be integrated with snap or put elsewhere.
needed to move KX_BlenderGL.cpp include to compile
2008-05-01 13:02:16 +00:00
c97975e879 Apricot Branch
==============

svn merge -r 14561:14620
2008-04-30 12:27:13 +00:00
5e0e27a180 make translate view zoom use grid size 2008-04-28 12:22:28 +00:00
4b7c271311 fixes from trunk 2008-04-27 20:43:45 +00:00
9e07b7fdfd Apricot Branch
==============

svn merge -r 14561:14567
2008-04-27 18:45:33 +00:00
8999c3d6dd changes from trunk 2008-04-27 15:00:31 +00:00
2ff5edc2a0 changes from trunk 2008-04-26 14:02:41 +00:00
6bfa99e695 Apricot Branch
==============

- Added basic cook-torrance specular to the GLSL material.
2008-04-25 17:39:40 +00:00
79280bb4c7 Apricot Branch
==============

GLSL materials:
- Basic support for normal maps, though it looks quite flat with
  the current solid mode lighting.
2008-04-25 16:58:32 +00:00
228132ca55 Apricot Branch
==============

GLSL materials:
- Added the beginning of texture stack evaluation, only a few options
  are supported.
- Added a few lines of code to display non-node materials, with solid
  mode lighting to at least see something.
2008-04-25 13:46:14 +00:00
7a23da05d3 caedes needed this fix for exporting 2008-04-25 10:25:17 +00:00
0821fc4377 Apricot Branch: material GLSL shaders
=====================================

- Currently only supports node-based materials, with some nodes,
  main purpose of this commit is to get the infrastructure in
  place, more material options will be added in the following weeks.
- Supported shader nodes: camera, curves, geometry (everything
  except global and front/back), curves (partially), huesatval,
  invert, mapping, math, mix/add/mult/sub/div, math, vector math,
  normal, output, rgb, separate/combine rgb, squeeze, basic image
  textures, value and output.
- Lights and shaders are still missing, but since the SoC project
  had these working quite far it should be possible to reuse that
  code.

- Enable using "GL Shaded Mode" in the user preferences. It will
  replace regular shaded mode with glsl shaders.
- If the material is not node based or has an error in it, it will
  revert to solid shading. Need to do this kind of error handling
  better and make it posssible to still run even with some
  functionality not supported.
- Integration with texture loading in textured mode is very poor,
  needs to be revised.

- Only added support for Scons and Makefiles.
- Added GLEW in extern/. There were some conflicts with the game
  engine opengl extensions but managed to solve them. Still, it
  would be good to use single mechanism for opengl extensions.
- Added a "gpu" module in source/blender. It has quite a lot of
  code with much of it uncommented as well, some of that will
  become used and some it will be removed later.
- OpenGL shader code is currently converted to a C file with
  datatoc (which now 0-terminates the arrays), but this has to
  be done manually still, need to figure out a better way or
  integrate it into the build systems.
2008-04-24 20:21:33 +00:00
9fdd01d3e5 changes from trunk 2008-04-23 21:11:02 +00:00
35536cfc48 dupliGroup instance offset, so a library of objects can be stored on 1 layer without placing each groups members over the world 0,0,0 point. 2008-04-23 11:38:10 +00:00
5644546c5a Request from Chris Plush, poly reduction tool that maintains face loops and gives pradictable results for terrain, this could evolve into an UnSubsurf tool.
Currently face flipping is incorrect and UV's are lost.
2008-04-23 10:16:59 +00:00
41bf809327 merge from trunk 2008-04-22 14:40:24 +00:00
071c679093 added comments for bad transform stuff 2008-04-21 09:50:26 +00:00
5333d4855d ground clamp during transform for speedy level editing,
The way this is integrated into transform code is really unacceptable, tried making this integrate into snap and retopo, but neither are good fits. - Will discuss with Theeth how this might best fit in.
2008-04-21 09:13:56 +00:00
e3ebe509e2 merge from trunk + some own stuff commented 2008-04-20 18:26:06 +00:00
1f1fdf1d7b changes from trunk 2008-04-19 11:26:51 +00:00
3a14f1d601 fix for last commit, inverted zoom 2008-04-18 21:33:38 +00:00
c44bffaf90 apricot request, continues view translates the offset (like fly mode) when auto depth enabled, probably will need a nicer solution for this in trunk. 2008-04-18 21:28:41 +00:00
7fd7d080a2 changes from trunk as well as ipo transform bugfix with NLA scale 2008-04-18 20:54:17 +00:00
f6a2f47cfe warning fix from trunk 2008-04-17 21:15:53 +00:00
fa66376e36 Make scripts stay in the windows when LOAD UI is disabled 2008-04-17 16:28:29 +00:00
1d03d93e39 Auto Depth didnt work in ortho perspective 2008-04-17 12:51:22 +00:00
67a506401a Option improved view navigation with large scenes. - "Auto Depth" in the view settings.
This works around the annoying problem where you cant zoom in any further by using the depth under the mouse to set the zoom endpoint.
It also sets the view rotation pivot to be under the mouse and works well with "Zoom to Mouse Position"
2008-04-17 09:49:15 +00:00
9a86799f1d branch for the apricot project 2008-04-17 08:35:47 +00:00
680 changed files with 19367 additions and 48506 deletions

View File

@@ -39,9 +39,7 @@ ENDMACRO(BLENDERLIB)
MACRO(SETUP_LIBDIRS)
# see "cmake --help-policy CMP0003"
if(COMMAND cmake_policy)
CMAKE_POLICY(SET CMP0003 NEW)
endif(COMMAND cmake_policy)
CMAKE_POLICY(SET CMP0003 NEW)
LINK_DIRECTORIES(${PYTHON_LIBPATH} ${SDL_LIBPATH} ${JPEG_LIBPATH} ${PNG_LIBPATH} ${ZLIB_LIBPATH} ${ICONV_LIBPATH} ${OPENEXR_LIBPATH} ${QUICKTIME_LIBPATH} ${FFMPEG_LIBPATH})
IF(WITH_INTERNATIONAL)
LINK_DIRECTORIES(${GETTEXT_LIBPATH})

View File

@@ -64,7 +64,6 @@ OPTION(WITH_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" ON)
OPTION(WITH_FFMPEG "Enable FFMPeg Support (http://ffmpeg.mplayerhq.hu/)" OFF)
OPTION(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON)
OPTION(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" OFF)
OPTION(WITH_WEBPLUGIN "Enable Web Plugin (Mozilla-Unix only)" OFF)
IF(NOT WITH_GAMEENGINE AND WITH_PLAYER)
MESSAGE("WARNING: WITH_PLAYER needs WITH_GAMEENGINE")
@@ -188,12 +187,19 @@ IF(UNIX)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp")
ENDIF(WITH_OPENMP)
SET(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing -DXP_UNIX -Wno-char-subscripts")
SET(PLATFORM_LINKFLAGS "-pthread")
INCLUDE_DIRECTORIES(/usr/include /usr/local/include)
# msvc already hides symbols, for others do it if the compiler supports it
EXECUTE_PROCESS(COMMAND echo "int main() { return 0; }" COMMAND ${CMAKE_C_COMPILER} -fvisibility=hidden -o /dev/null -xc - RESULT_VARIABLE VISIBILITY_RESULT OUTPUT_QUIET ERROR_QUIET)
IF(NOT VISIBILITY_RESULT)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden -DGCC_HASCLASSVISIBILITY")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -DGCC_HASCLASSVISIBILITY")
ENDIF(NOT VISIBILITY_RESULT)
ENDIF(UNIX)
IF(WIN32)
@@ -412,6 +418,14 @@ IF(APPLE)
SET(TIFF_INC ${TIFF}/include)
SET(EXETYPE MACOSX_BUNDLE)
# msvc already hides symbols, for others do it if the compiler supports it
EXECUTE_PROCESS(COMMAND echo "int main() { return 0; }" COMMAND ${CMAKE_C_COMPILER} -fvisibility=hidden -o /dev/null -xc - RESULT_VARIABLE VISIBILITY_RESULT OUTPUT_QUIET ERROR_QUIET)
IF(NOT VISIBILITY_RESULT)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden -DGCC_HASCLASSVISIBILITY")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -DGCC_HASCLASSVISIBILITY")
ENDIF(NOT VISIBILITY_RESULT)
ENDIF(APPLE)
IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
@@ -457,13 +471,6 @@ SUBDIRS(
# Blender Application
SUBDIRS(source/creator)
#-----------------------------------------------------------------------------
# Blender WebPlugin
IF(WITH_WEBPLUGIN)
SET(MOZILLA_DIR "${CMAKE_SOURCE_DIR}/../gecko-sdk/" CACHE PATH "Gecko SDK path")
SET(WITH_PLAYER ON)
ENDIF(WITH_WEBPLUGIN)
#-----------------------------------------------------------------------------
# Blender Player
IF(WITH_PLAYER)

View File

@@ -36,6 +36,7 @@ import string
import shutil
import glob
import re
import commands
from tempfile import mkdtemp
import tools.Blender
@@ -236,18 +237,23 @@ if env['OURPLATFORM'] == 'linux2' :
os.rmdir(os.path.join(root, name))
if root: os.rmdir(root)
# msvc already hides symbols, for others do it if the compiler supports it
if env['OURPLATFORM'] != 'win32-vc':
def check_option(cc, option):
cmd = "echo \"int main() { return 0; }\" | " + cc + " " + option + " -o /dev/null -xc -"
return (commands.getstatusoutput(cmd)[0] == 0)
if check_option(env['CC'], '-fvisibility=hidden'):
env['CPPFLAGS'].extend(['-fvisibility=hidden', '-DGCC_HASCLASSVISIBILITY'])
env['CXXFLAGS'].extend(['-fvisibility=hidden', '-DGCC_HASCLASSVISIBILITY'])
env['CCFLAGS'].extend(['-fvisibility=hidden', '-DGCC_HASCLASSVISIBILITY'])
if len(B.quickdebug) > 0 and printdebug != 0:
print B.bc.OKGREEN + "Buildings these libs with debug symbols:" + B.bc.ENDC
for l in B.quickdebug:
print "\t" + l
# remove stdc++ from LLIBS if we are building a statc linked CXXFLAGS
if env['WITH_BF_STATICCXX']:
if 'stdc++' in env['LLIBS']:
env['LLIBS'] = env['LLIBS'].replace('stdc++', ' ')
else:
print '\tcould not remove stdc++ library from LLIBS, WITH_BF_STATICCXX may not work for your platform'
# check target for blenderplayer. Set WITH_BF_PLAYER if found on cmdline
if 'blenderplayer' in B.targets:
env['WITH_BF_PLAYER'] = True
@@ -255,31 +261,6 @@ if 'blenderplayer' in B.targets:
if 'blendernogame' in B.targets:
env['WITH_BF_GAMEENGINE'] = False
if 'blenderlite' in B.targets:
env['WITH_BF_GAMEENGINE'] = False
env['WITH_BF_OPENAL'] = False
env['WITH_BF_OPENEXR'] = False
env['WITH_BF_ICONV'] = False
env['WITH_BF_INTERNATIONAL'] = False
env['WITH_BF_OPENJPEG'] = False
env['WITH_BF_FFMPEG'] = False
env['WITH_BF_QUICKTIME'] = False
env['WITH_BF_YAFRAY'] = False
env['WITH_BF_REDCODE'] = False
env['WITH_BF_FTGL'] = False
env['WITH_BF_DDS'] = False
env['WITH_BF_ZLIB'] = False
env['WITH_BF_SDL'] = False
env['WITH_BF_JPEG'] = False
env['WITH_BF_PNG'] = False
env['WITH_BF_ODE'] = False
env['WITH_BF_BULLET'] = False
env['WITH_BF_BINRELOC'] = False
env['BF_BUILDINFO'] = False
env['BF_NO_ELBEEM'] = True
# lastly we check for root_build_dir ( we should not do before, otherwise we might do wrong builddir
#B.root_build_dir = B.arguments.get('BF_BUILDDIR', '..'+os.sep+'build'+os.sep+platform+os.sep)
B.root_build_dir = env['BF_BUILDDIR']
@@ -422,26 +403,6 @@ if env['OURPLATFORM']!='darwin':
source=[dp+os.sep+f for f in df]
scriptinstall.append(env.Install(dir=dir,source=source))
#-- icons
if env['OURPLATFORM']=='linux2':
iconlist = []
icontargetlist = []
for tp, tn, tf in os.walk('release/freedesktop/icons'):
if 'CVS' in tn:
tn.remove('CVS')
if '.svn' in tn:
tn.remove('.svn')
for f in tf:
print ">>>", env['BF_INSTALLDIR'], tp, f
iconlist.append(tp+os.sep+f)
icontargetlist.append(env['BF_INSTALLDIR']+tp[19:]+os.sep+f)
iconinstall = []
for targetdir,srcfile in zip(icontargetlist, iconlist):
td, tf = os.path.split(targetdir)
iconinstall.append(env.Install(dir=td, source=srcfile))
#-- plugins
pluglist = []
plugtargetlist = []
@@ -490,8 +451,6 @@ textinstall = env.Install(dir=env['BF_INSTALLDIR'], source=textlist)
if env['OURPLATFORM']=='darwin':
allinstall = [blenderinstall, plugininstall, textinstall]
elif env['OURPLATFORM']=='linux2':
allinstall = [blenderinstall, dotblenderinstall, scriptinstall, plugininstall, textinstall, iconinstall]
else:
allinstall = [blenderinstall, dotblenderinstall, scriptinstall, plugininstall, textinstall]
@@ -542,10 +501,6 @@ if not env['WITH_BF_GAMEENGINE']:
blendernogame = env.Alias('blendernogame', B.program_list)
Depends(blendernogame,installtarget)
if 'blenderlite' in B.targets:
blenderlite = env.Alias('blenderlite', B.program_list)
Depends(blenderlite,installtarget)
Depends(nsiscmd, allinstall)
Default(B.program_list)

View File

@@ -86,7 +86,6 @@ IF(UNIX)
bf_oglrasterizer
bf_expressions
bf_scenegraph
bf_IK
bf_moto
bf_soundsystem
bf_kernel

View File

@@ -87,18 +87,10 @@ if MAC_PROC == 'powerpc':
BF_OPENAL = '#../lib/darwin-8.0.0-powerpc/openal'
else :
BF_OPENAL = LIBDIR + '/openal'
WITH_BF_STATICOPENAL = 'false'
BF_OPENAL_INC = '${BF_OPENAL}/include'
BF_OPENAL_LIB = 'openal'
BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
# Warning, this static lib configuration is untested! users of this OS please confirm.
BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
# Warning, this static lib configuration is untested! users of this OS please confirm.
BF_CXX = '/usr'
WITH_BF_STATICCXX = 'false'
BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
WITH_BF_SDL = 'true'
BF_SDL = LIBDIR + '/sdl' #$(shell sdl-config --prefix)
@@ -110,13 +102,10 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'true'
WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = '${LCGDIR}/openexr'
BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR'
BF_OPENEXR_LIB = ' Iex Half IlmImf Imath IlmThread'
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
# Warning, this static lib configuration is untested! users of this OS please confirm.
BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
WITH_BF_DDS = 'true'

View File

@@ -6,28 +6,18 @@ BF_VERSE_INCLUDE = "#extern/verse/dist"
BF_PYTHON = '/usr'
BF_PYTHON_VERSION = '2.5'
WITH_BF_STATICPYTHON = 'false'
BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}'
BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}'
BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' #BF_PYTHON+'/lib/python'+BF_PYTHON_VERSION+'/config/libpython'+BF_PYTHON_VERSION+'.a'
BF_PYTHON_LINKFLAGS = ['-Xlinker', '-export-dynamic']
BF_PYTHON_LIB_STATIC = '${BF_PYTHON}/lib/libpython${BF_PYTHON_VERSION}.a'
WITH_BF_OPENAL = 'true'
WITH_BF_STATICOPENAL = 'false'
BF_OPENAL = '/usr'
BF_OPENAL_INC = '${BF_OPENAL}/include'
BF_OPENAL_LIB = 'openal'
BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
# some distros have a separate libalut
# if you get linker complaints, you need to uncomment the line below
# BF_OPENAL_LIB = 'openal alut'
# BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a ${BF_OPENAL}/lib/libalut.a'
BF_CXX = '/usr'
WITH_BF_STATICCXX = 'false'
BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
WITH_BF_SDL = 'true'
BF_SDL = '/usr' #$(shell sdl-config --prefix)
@@ -38,17 +28,14 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'true'
WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = '/usr'
# when compiling with your own openexr lib you might need to set...
# BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR ${BF_OPENEXR}/include'
BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR'
BF_OPENEXR_LIB = 'Half IlmImf Iex Imath '
BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
# BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
WITH_BF_DDS = 'true'
WITH_BF_JPEG = 'true'
@@ -179,8 +166,8 @@ CCFLAGS = ['-pipe','-fPIC','-funsigned-char','-fno-strict-aliasing']
CPPFLAGS = ['-DXP_UNIX']
CXXFLAGS = ['-pipe','-fPIC','-funsigned-char','-fno-strict-aliasing']
REL_CFLAGS = ['-O3']
REL_CCFLAGS = ['-O3']
REL_CFLAGS = ['-O2']
REL_CCFLAGS = ['-O2']
##BF_DEPEND = 'true'
##
##AR = ar

View File

@@ -14,18 +14,10 @@ BF_PYTHON_LIB = 'python25'
BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib'
WITH_BF_OPENAL = 'true'
WITH_BF_STATICOPENAL = 'false'
BF_OPENAL = LIBDIR + '/openal'
BF_OPENAL_INC = '${BF_OPENAL}/include'
BF_OPENAL_LIB = 'openal_static'
BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
# Warning, this static lib configuration is untested! users of this OS please confirm.
BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
# Warning, this static lib configuration is untested! users of this OS please confirm.
BF_CXX = '/usr'
WITH_BF_STATICCXX = 'false'
BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
WITH_BF_SDL = 'true'
BF_SDL = LIBDIR + '/sdl'
@@ -42,13 +34,10 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'true'
WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = LIBDIR + '/gcc/openexr'
BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR'
BF_OPENEXR_LIB = ' Half IlmImf Iex '
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
# Warning, this static lib configuration is untested! users of this OS please confirm.
BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
WITH_BF_DDS = 'true'

View File

@@ -9,12 +9,10 @@ BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}'
BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/python${BF_PYTHON_VERSION}/config'
WITH_BF_OPENAL = 'false'
# WITH_BF_STATICOPENAL = 'false'
#BF_OPENAL = LIBDIR + '/openal'
#BF_OPENAL_INC = '${BF_OPENAL}/include'
#BF_OPENAL_LIB = 'openal'
#BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
#BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
WITH_BF_SDL = 'true'
BF_SDL = '/usr/local' #$(shell sdl-config --prefix)
@@ -26,12 +24,9 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'false'
WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = '/usr/local'
BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR'
BF_OPENEXR_LIB = 'Half IlmImf Iex Imath '
# Warning, this static lib configuration is untested! users of this OS please confirm.
BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
WITH_BF_DDS = 'true'

View File

@@ -9,18 +9,10 @@ BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' #BF_PYTHON+'/lib/python'+BF_PYTHON_
BF_PYTHON_LINKFLAGS = ['-Xlinker', '-export-dynamic']
WITH_BF_OPENAL = 'true'
WITH_BF_STATICOPENAL = 'false'
BF_OPENAL = '/usr/local'
BF_OPENAL_INC = '${BF_OPENAL}/include'
BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
BF_OPENAL_LIB = 'openal'
# Warning, this static lib configuration is untested! users of this OS please confirm.
BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
# Warning, this static lib configuration is untested! users of this OS please confirm.
BF_CXX = '/usr'
WITH_BF_STATICCXX = 'false'
BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
WITH_BF_SDL = 'true'
BF_SDL = '/usr/local' #$(shell sdl-config --prefix)
@@ -32,13 +24,10 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'true'
WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = '/usr/local'
BF_OPENEXR_INC = ['${BF_OPENEXR}/include', '${BF_OPENEXR}/include/OpenEXR' ]
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
BF_OPENEXR_LIB = 'Half IlmImf Iex Imath '
# Warning, this static lib configuration is untested! users of this OS please confirm.
BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
WITH_BF_DDS = 'true'

View File

@@ -12,13 +12,10 @@ BF_PYTHON_LIB = 'python25'
BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib'
WITH_BF_OPENAL = 'true'
WITH_BF_STATICOPENAL = 'false'
BF_OPENAL = LIBDIR + '/openal'
BF_OPENAL_INC = '${BF_OPENAL}/include'
BF_OPENAL_LIB = 'dxguid openal_static'
BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
# Warning, this static lib configuration is untested! users of this OS please confirm.
BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
WITH_BF_FFMPEG = 'false'
BF_FFMPEG_LIB = 'avformat swscale avcodec avutil xvidcore x264'
@@ -40,13 +37,10 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'true'
WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = LIBDIR + '/gcc/openexr'
BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR'
BF_OPENEXR_LIB = ' Half IlmImf Iex '
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
# Warning, this static lib configuration is untested! users of this OS please confirm.
BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
WITH_BF_DDS = 'true'

View File

@@ -19,18 +19,10 @@ BF_PYTHON_LIB = 'python25'
BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib'
WITH_BF_OPENAL = 'true'
WITH_BF_STATICOPENAL = 'false'
BF_OPENAL = LIBDIR + '/openal'
BF_OPENAL_INC = '${BF_OPENAL}/include ${BF_OPENAL}/include/AL '
BF_OPENAL_LIB = 'dxguid openal_static'
BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
# Warning, this static lib configuration is untested! users of this OS please confirm.
BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
# TODO - are these useful on win32?
# BF_CXX = '/usr'
# WITH_BF_STATICCXX = 'false'
# BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
WITH_BF_ICONV = 'true'
BF_ICONV = LIBDIR + '/iconv'
@@ -53,13 +45,10 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'true'
WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = LIBDIR + '/openexr'
BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/IlmImf ${BF_OPENEXR}/include/Iex ${BF_OPENEXR}/include/Imath '
BF_OPENEXR_LIB = ' Iex Half IlmImf Imath IlmThread '
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib_msvc'
# Warning, this static lib configuration is untested! users of this OS please confirm.
BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
WITH_BF_DDS = 'true'

View File

@@ -35,7 +35,6 @@ FILE(GLOB SRC
src/BulletDynamics/ConstraintSolver/*.cpp
src/BulletDynamics/Vehicle/*.cpp
src/BulletDynamics/Dynamics/*.cpp
src/BulletSoftBody/*.cpp
)
ADD_DEFINITIONS(-D_LIB)

View File

@@ -40,8 +40,7 @@ BulletCollision/NarrowPhaseCollision \
BulletCollision//CollisionDispatch \
BulletDynamics/ConstraintSolver \
BulletDynamics/Vehicle \
BulletDynamics/Dynamics \
BulletSoftBody
BulletDynamics/Dynamics
include nan_subdirs.mk

View File

@@ -58,11 +58,9 @@ IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\C
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\Dynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\Vehicle MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Vehicle
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\LinearMath MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\LinearMath
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletSoftBody MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletSoftBody
XCOPY /Y ..\..\src\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include
XCOPY /Y ..\..\src\LinearMath\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\LinearMath
XCOPY /Y ..\..\src\BulletSoftBody\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletSoftBody
XCOPY /Y ..\..\src\BulletCollision\BroadphaseCollision\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\BroadphaseCollision
XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision
XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision
@@ -396,24 +394,12 @@ ECHO Done
<File
RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btSequentialImpulseConstraintSolver.h">
</File>
<File
RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btSliderConstraint.cpp">
</File>
<File
RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btSliderConstraint.h">
</File>
<File
RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btSolve2LinearConstraint.cpp">
</File>
<File
RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btSolve2LinearConstraint.h">
</File>
<File
RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btSolverBody.h">
</File>
<File
RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btSolverConstraint.h">
</File>
<File
RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btTypedConstraint.cpp">
</File>
@@ -424,12 +410,6 @@ ECHO Done
<Filter
Name="Dynamics"
Filter="">
<File
RelativePath="..\..\src\BulletDynamics\Dynamics\btContinuousDynamicsWorld.cpp">
</File>
<File
RelativePath="..\..\src\BulletDynamics\Dynamics\btContinuousDynamicsWorld.h">
</File>
<File
RelativePath="..\..\src\BulletDynamics\Dynamics\btDiscreteDynamicsWorld.cpp">
</File>
@@ -502,45 +482,18 @@ ECHO Done
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btCollisionAlgorithm.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btDbvt.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btDbvt.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btDbvtBroadphase.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btDbvtBroadphase.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btDispatcher.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btDispatcher.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btMultiSapBroadphase.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btMultiSapBroadphase.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btOverlappingPairCache.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btOverlappingPairCache.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btOverlappingPairCallback.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btQuantizedBvh.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btQuantizedBvh.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btSimpleBroadphase.cpp">
</File>
@@ -581,12 +534,6 @@ ECHO Done
<File
RelativePath="..\..\src\BulletCollision\NarrowPhaseCollision\btGjkEpa.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\NarrowPhaseCollision\btGjkEpa2.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\NarrowPhaseCollision\btGjkEpa2.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\NarrowPhaseCollision\btGjkEpaPenetrationDepthSolver.cpp">
</File>
@@ -642,21 +589,6 @@ ECHO Done
<Filter
Name="CollisionDispatch"
Filter="">
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btBoxBoxCollisionAlgorithm.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btBoxBoxCollisionAlgorithm.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btBoxBoxDetector.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btBoxBoxDetector.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btCollisionConfiguration.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btCollisionCreateFunc.h">
</File>
@@ -696,18 +628,6 @@ ECHO Done
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btConvexConvexAlgorithm.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btConvexPlaneCollisionAlgorithm.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btConvexPlaneCollisionAlgorithm.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btDefaultCollisionConfiguration.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btDefaultCollisionConfiguration.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btEmptyCollisionAlgorithm.cpp">
</File>
@@ -811,12 +731,6 @@ ECHO Done
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btConvexHullShape.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btConvexInternalShape.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btConvexInternalShape.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btConvexShape.cpp">
</File>
@@ -847,21 +761,12 @@ ECHO Done
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btHeightfieldTerrainShape.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btMaterial.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btMinkowskiSumShape.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btMinkowskiSumShape.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btMultimaterialTriangleMeshShape.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btMultimaterialTriangleMeshShape.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btMultiSphereShape.cpp">
</File>
@@ -880,18 +785,6 @@ ECHO Done
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btPolyhedralConvexShape.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btScaledBvhTriangleMeshShape.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btScaledBvhTriangleMeshShape.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btShapeHull.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btShapeHull.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btSphereShape.cpp">
</File>
@@ -934,12 +827,6 @@ ECHO Done
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btTriangleIndexVertexArray.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btTriangleIndexVertexMaterialArray.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btTriangleIndexVertexMaterialArray.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btTriangleMesh.cpp">
</File>
@@ -955,12 +842,6 @@ ECHO Done
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btTriangleShape.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btUniformScalingShape.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btUniformScalingShape.h">
</File>
</Filter>
</Filter>
<Filter
@@ -978,12 +859,6 @@ ECHO Done
<File
RelativePath="..\..\src\LinearMath\btAlignedObjectArray.h">
</File>
<File
RelativePath="..\..\src\LinearMath\btConvexHull.cpp">
</File>
<File
RelativePath="..\..\src\LinearMath\btConvexHull.h">
</File>
<File
RelativePath="..\..\src\LinearMath\btDefaultMotionState.h">
</File>
@@ -993,9 +868,6 @@ ECHO Done
<File
RelativePath="..\..\src\LinearMath\btGeometryUtil.h">
</File>
<File
RelativePath="..\..\src\LinearMath\btHashMap.h">
</File>
<File
RelativePath="..\..\src\LinearMath\btIDebugDraw.h">
</File>
@@ -1014,9 +886,6 @@ ECHO Done
<File
RelativePath="..\..\src\LinearMath\btPoint3.h">
</File>
<File
RelativePath="..\..\src\LinearMath\btPoolAllocator.h">
</File>
<File
RelativePath="..\..\src\LinearMath\btQuadWord.h">
</File>
@@ -1035,6 +904,9 @@ ECHO Done
<File
RelativePath="..\..\src\LinearMath\btScalar.h">
</File>
<File
RelativePath="..\..\src\LinearMath\btSimdMinMax.h">
</File>
<File
RelativePath="..\..\src\LinearMath\btStackAlloc.h">
</File>
@@ -1048,58 +920,6 @@ ECHO Done
RelativePath="..\..\src\LinearMath\btVector3.h">
</File>
</Filter>
<Filter
Name="BulletSoftBody"
Filter="">
<File
RelativePath="..\..\src\BulletSoftBody\btSoftBody.cpp">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftBody.h">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftBodyConcaveCollisionAlgorithm.cpp">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftBodyConcaveCollisionAlgorithm.h">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftBodyHelpers.cpp">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftBodyHelpers.h">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftBodyInternals.h">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftBodyRigidBodyCollisionConfiguration.cpp">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftBodyRigidBodyCollisionConfiguration.h">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftRigidCollisionAlgorithm.cpp">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftRigidCollisionAlgorithm.h">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftRigidDynamicsWorld.cpp">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftRigidDynamicsWorld.h">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftSoftCollisionAlgorithm.cpp">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftSoftCollisionAlgorithm.h">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSparseSDF.h">
</File>
</Filter>
</Filter>
</Files>
<Globals>

View File

@@ -1,8 +1,3 @@
***
Apply bullet_compound_raycast.patch if not already applied in Bullet source
This patch is needed to return correct raycast results on compound shape.
/ben
*** These files in extern/bullet2 are NOT part of the Blender build yet ***

View File

@@ -23,153 +23,15 @@ subject to the following restrictions:
#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 */
PL_DECLARE_HANDLE(plPhysicsSdkHandle);
/* Dynamics world, belonging to some physics SDK */
PL_DECLARE_HANDLE(plDynamicsWorldHandle);
/* Rigid Body that can be part of a Dynamics World */
PL_DECLARE_HANDLE(plRigidBodyHandle);
/* Collision Shape/Geometry, property of a Rigid Body */
PL_DECLARE_HANDLE(plCollisionShapeHandle);
/* Constraint for Rigid Bodies */
PL_DECLARE_HANDLE(plConstraintHandle);
/* Triangle Mesh interface */
PL_DECLARE_HANDLE(plMeshInterfaceHandle);
/* Broadphase Scene/Proxy Handles */
PL_DECLARE_HANDLE(plCollisionBroadphaseHandle);
PL_DECLARE_HANDLE(plBroadphaseProxyHandle);
PL_DECLARE_HANDLE(plCollisionWorldHandle);
/*
Create and Delete a Physics SDK
*/
extern plPhysicsSdkHandle plNewBulletSdk(); //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();
extern void plAddChildShape(plCollisionShapeHandle compoundShape,plCollisionShapeHandle childShape, plVector3 childPos,plQuaternion childOrn);
extern void plDeleteShape(plCollisionShapeHandle shape);
/* Convex Meshes */
extern plCollisionShapeHandle plNewConvexHullShape();
extern void plAddVertex(plCollisionShapeHandle convexHull, plReal x,plReal y,plReal z);
/* Concave static triangle meshes */
extern plMeshInterfaceHandle plNewMeshInterface();
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);
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]);
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]);
#ifdef __cplusplus
}
#endif
#endif //BULLET_C_API_H

View File

@@ -21,18 +21,640 @@
#include <assert.h>
btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache)
:btAxisSweep3Internal<unsigned short int>(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache)
#ifdef DEBUG_BROADPHASE
#include <stdio.h>
void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinality)
{
// 1 handle is reserved as sentinel
btAssert(maxHandles > 1 && maxHandles < 32767);
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)
assert(numEdges == m_numHandles*2+1);
}
#endif //DEBUG_BROADPHASE
btBroadphaseProxy* btAxisSweep3::createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask)
{
(void)shapeType;
BP_FP_INT_TYPE handleId = addHandle(min,max, userPtr,collisionFilterGroup,collisionFilterMask);
Handle* handle = getHandle(handleId);
return handle;
}
void btAxisSweep3::destroyProxy(btBroadphaseProxy* proxy)
{
Handle* handle = static_cast<Handle*>(proxy);
removeHandle(handle->m_handleId);
}
void btAxisSweep3::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax)
{
Handle* handle = static_cast<Handle*>(proxy);
updateHandle(handle->m_handleId,aabbMin,aabbMax);
}
bt32BitAxisSweep3::bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache )
:btAxisSweep3Internal<unsigned int>(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache)
btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles)
:btOverlappingPairCache()
{
m_invalidPair = 0;
//assert(bounds.HasVolume());
// 1 handle is reserved as sentinel
btAssert(maxHandles > 1 && maxHandles < 2147483647);
btAssert(maxHandles > 1 && maxHandles < BP_MAX_HANDLES);
// init bounds
m_worldAabbMin = worldAabbMin;
m_worldAabbMax = worldAabbMax;
btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin;
BP_FP_INT_TYPE maxInt = BP_HANDLE_SENTINEL;
m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize;
// allocate handles buffer 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(i + 1);
m_pHandles[maxHandles - 1].SetNextFree(0);
}
{
// allocate edge buffers
for (int i = 0; i < 3; i++)
m_pEdges[i] = new 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 = BP_HANDLE_SENTINEL;
m_pEdges[axis][1].m_handle = 0;
#ifdef DEBUG_BROADPHASE
debugPrintAxis(axis);
#endif //DEBUG_BROADPHASE
}
}
btAxisSweep3::~btAxisSweep3()
{
for (int i = 2; i >= 0; i--)
delete[] m_pEdges[i];
delete[] m_pHandles;
}
void btAxisSweep3::quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const
{
btPoint3 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() & BP_HANDLE_MASK) | isMax);
out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & BP_HANDLE_MASK) | isMax);
out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & BP_HANDLE_MASK) | isMax);
}
BP_FP_INT_TYPE btAxisSweep3::allocHandle()
{
assert(m_firstFreeHandle);
BP_FP_INT_TYPE handle = m_firstFreeHandle;
m_firstFreeHandle = getHandle(handle)->GetNextFree();
m_numHandles++;
return handle;
}
void btAxisSweep3::freeHandle(BP_FP_INT_TYPE handle)
{
assert(handle > 0 && handle < m_maxHandles);
getHandle(handle)->SetNextFree(m_firstFreeHandle);
m_firstFreeHandle = handle;
m_numHandles--;
}
BP_FP_INT_TYPE btAxisSweep3::addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask)
{
// 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();
assert(handle!= 0xcdcd);
Handle* pHandle = getHandle(handle);
pHandle->m_handleId = 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 = 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] = limit - 1;
pHandle->m_maxEdges[axis] = limit;
}
// now sort the new edges to their correct position
sortMinDown(0, pHandle->m_minEdges[0], false);
sortMaxDown(0, pHandle->m_maxEdges[0], false);
sortMinDown(1, pHandle->m_minEdges[1], false);
sortMaxDown(1, pHandle->m_maxEdges[1], false);
sortMinDown(2, pHandle->m_minEdges[2], true);
sortMaxDown(2, pHandle->m_maxEdges[2], true);
return handle;
}
void btAxisSweep3::removeHandle(BP_FP_INT_TYPE handle)
{
Handle* pHandle = getHandle(handle);
//explicitly remove the pairs containing the proxy
//we could do it also in the sortMinUp (passing true)
//todo: compare performance
removeOverlappingPairsContainingProxy(pHandle);
// compute current limit of edge arrays
int limit = 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 = BP_HANDLE_SENTINEL;
sortMaxUp(axis,max,false);
BP_FP_INT_TYPE i = pHandle->m_minEdges[axis];
pEdges[i].m_pos = BP_HANDLE_SENTINEL;
sortMinUp(axis,i,false);
pEdges[limit-1].m_handle = 0;
pEdges[limit-1].m_pos = BP_HANDLE_SENTINEL;
#ifdef DEBUG_BROADPHASE
debugPrintAxis(axis,false);
#endif //DEBUG_BROADPHASE
}
// free the handle
freeHandle(handle);
}
extern int gOverlappingPairs;
void btAxisSweep3::refreshOverlappingPairs()
{
}
void btAxisSweep3::processAllOverlappingPairs(btOverlapCallback* callback)
{
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
m_overlappingPairArray.heapSort(btBroadphasePairSortPredicate());
//remove the 'invalid' ones
#ifdef USE_POPBACK_REMOVAL
while (m_invalidPair>0)
{
m_invalidPair--;
m_overlappingPairArray.pop_back();
}
#else
m_overlappingPairArray.resize(m_overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
#endif
int i;
btBroadphasePair previousPair;
previousPair.m_pProxy0 = 0;
previousPair.m_pProxy1 = 0;
previousPair.m_algorithm = 0;
for (i=0;i<m_overlappingPairArray.size();i++)
{
btBroadphasePair& pair = m_overlappingPairArray[i];
bool isDuplicate = (pair == previousPair);
previousPair = pair;
bool needsRemoval = false;
if (!isDuplicate)
{
bool hasOverlap = testOverlap(pair.m_pProxy0,pair.m_pProxy1);
if (hasOverlap)
{
needsRemoval = callback->processOverlap(pair);
} else
{
needsRemoval = true;
}
} else
{
//remove duplicate
needsRemoval = true;
//should have no algorithm
btAssert(!pair.m_algorithm);
}
if (needsRemoval)
{
cleanOverlappingPair(pair);
// m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
// m_overlappingPairArray.pop_back();
pair.m_pProxy0 = 0;
pair.m_pProxy1 = 0;
m_invalidPair++;
gOverlappingPairs--;
}
}
}
bool btAxisSweep3::testOverlap(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;
}
bool btAxisSweep3::testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB)
{
//optimization 1: check the array index (memory address), instead of the m_pos
for (int axis = 0; axis < 3; axis++)
{
if (axis != ignoreAxis)
{
if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] ||
pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis])
{
return false;
}
}
}
//optimization 2: only 2 axis need to be tested (conflicts with 'delayed removal' optimization)
/*for (int axis = 0; axis < 3; axis++)
{
if (m_pEdges[axis][pHandleA->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleB->m_minEdges[axis]].m_pos ||
m_pEdges[axis][pHandleB->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleA->m_minEdges[axis]].m_pos)
{
return false;
}
}
*/
return true;
}
void btAxisSweep3::updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax)
{
// assert(bounds.IsFinite());
//assert(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);
if (dmax > 0)
sortMaxUp(axis, emax);
// shrink (only removes overlaps)
if (dmin > 0)
sortMinUp(axis, emin);
if (dmax < 0)
sortMaxDown(axis, emax);
#ifdef DEBUG_BROADPHASE
debugPrintAxis(axis);
#endif //DEBUG_BROADPHASE
}
}
// sorting a min edge downwards can only ever *add* overlaps
void btAxisSweep3::sortMinDown(int axis, BP_FP_INT_TYPE edge, 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
if (updateOverlaps && testOverlap(axis,pHandleEdge, pHandlePrev))
{
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
void btAxisSweep3::sortMinUp(int axis, BP_FP_INT_TYPE edge, 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())
{
// if next edge is maximum remove any overlap between the two handles
if (updateOverlaps)
{
/*
Handle* handle0 = getHandle(pEdge->m_handle);
Handle* handle1 = getHandle(pNext->m_handle);
btBroadphasePair tmpPair(*handle0,*handle1);
removeOverlappingPair(tmpPair);
*/
}
// 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
void btAxisSweep3::sortMaxDown(int axis, BP_FP_INT_TYPE edge, 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
if (updateOverlaps)
{
//this is done during the overlappingpairarray iteration/narrowphase collision
/*
Handle* handle0 = getHandle(pEdge->m_handle);
Handle* handle1 = getHandle(pPrev->m_handle);
btBroadphasePair* pair = findPair(handle0,handle1);
//assert(pair);
if (pair)
{
removeOverlappingPair(*pair);
}
*/
}
// 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
void btAxisSweep3::sortMaxUp(int axis, BP_FP_INT_TYPE edge, 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())
{
// if next edge is a minimum check the bounds and add an overlap if necessary
if (updateOverlaps && testOverlap(axis, pHandleEdge, pHandleNext))
{
Handle* handle0 = getHandle(pEdge->m_handle);
Handle* handle1 = getHandle(pNext->m_handle);
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++;
}
}

View File

@@ -19,26 +19,34 @@
#ifndef AXIS_SWEEP_3_H
#define AXIS_SWEEP_3_H
#include "LinearMath/btPoint3.h"
#include "LinearMath/btVector3.h"
#include "../../LinearMath/btPoint3.h"
#include "../../LinearMath/btVector3.h"
#include "btOverlappingPairCache.h"
#include "btBroadphaseInterface.h"
#include "btBroadphaseProxy.h"
#include "btOverlappingPairCallback.h"
//Enable BP_USE_FIXEDPOINT_INT_32 if you need more then 32767 objects
//#define BP_USE_FIXEDPOINT_INT_32 1
#ifdef BP_USE_FIXEDPOINT_INT_32
#define BP_FP_INT_TYPE unsigned int
#define BP_MAX_HANDLES 1500000 //arbitrary maximum number of handles
#define BP_HANDLE_SENTINEL 0x7fffffff
#define BP_HANDLE_MASK 0xfffffffe
#else
#define BP_FP_INT_TYPE unsigned short int
#define BP_MAX_HANDLES 32767
#define BP_HANDLE_SENTINEL 0xffff
#define BP_HANDLE_MASK 0xfffe
#endif //BP_USE_FIXEDPOINT_INT_32
//#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
/// btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase.
/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using integer coordinates instead of floats.
/// The testOverlap check is optimized to check the array index, rather then the actual AABB coordinates/pos
class btAxisSweep3 : public btOverlappingPairCache
{
protected:
BP_FP_INT_TYPE m_bpHandleMask;
BP_FP_INT_TYPE m_handleSentinel;
public:
@@ -49,57 +57,47 @@ 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);}
BP_FP_INT_TYPE IsMax() const {return m_pos & 1;}
};
public:
class Handle : public btBroadphaseProxy
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;
BP_FP_INT_TYPE m_handleId;
BP_FP_INT_TYPE m_pad;
//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];}
inline void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;}
inline BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];}
}; // 24 bytes + 24 for Edge structures = 44 bytes total per entry
protected:
private:
btPoint3 m_worldAabbMin; // overall system bounds
btPoint3 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
int 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;
int m_invalidPair;
// 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);
bool testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB);
#ifdef DEBUG_BROADPHASE
void debugPrintAxis(int axis,bool checkCardinality=true);
@@ -110,803 +108,29 @@ protected:
void quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const;
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 );
void sortMinDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true);
void sortMinUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true);
void sortMaxDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true);
void sortMaxUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true);
public:
btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles = 16384);
virtual ~btAxisSweep3();
btAxisSweep3Internal(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache=0);
virtual ~btAxisSweep3Internal();
BP_FP_INT_TYPE getNumHandles() const
{
return m_numHandles;
}
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
virtual void refreshOverlappingPairs();
BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
void removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher);
void updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher);
SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;}
BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask);
void removeHandle(BP_FP_INT_TYPE handle);
void updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax);
inline Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;}
void processAllOverlappingPairs(btOverlapCallback* callback);
//Broadphase Interface
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);
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)
assert(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,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy)
{
(void)shapeType;
BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,multiSapProxy);
Handle* handle = getHandle(handleId);
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);
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);
updateHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), aabbMin, aabbMax,dispatcher);
}
template <typename BP_FP_INT_TYPE>
btAxisSweep3Internal<BP_FP_INT_TYPE>::btAxisSweep3Internal(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache )
:m_bpHandleMask(handleMask),
m_handleSentinel(handleSentinel),
m_pairCache(pairCache),
m_userPairCallback(0),
m_ownsPairCache(false),
m_invalidPair(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;
}
//assert(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()
{
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 btPoint3& point, int isMax) const
{
btPoint3 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);
}
template <typename BP_FP_INT_TYPE>
BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::allocHandle()
{
assert(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)
{
assert(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 btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy)
{
// 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;
pHandle->m_multiSapParentProxy = multiSapProxy;
// 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);
}
extern int gOverlappingPairs;
//#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)
{
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++;
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.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 btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher)
{
// assert(bounds.IsFinite());
//assert(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++;
}
}
////////////////////////////////////////////////////////////////////
/// The btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase.
/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats.
/// For large worlds and many objects, use bt32BitAxisSweep3 or btDbvtBroadphase instead. bt32BitAxisSweep3 has higher precision and allows more then 16384 objects at the cost of more memory and bit of performance.
class btAxisSweep3 : public btAxisSweep3Internal<unsigned short int>
{
public:
btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0);
};
/// The bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune.
/// This comes at the cost of more memory per handle, and a bit slower performance.
/// It uses arrays rather then lists for storage of the 3 axis.
class bt32BitAxisSweep3 : public btAxisSweep3Internal<unsigned int>
{
public:
bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0);
virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask);
virtual void destroyProxy(btBroadphaseProxy* proxy);
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax);
bool testOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
};

View File

@@ -20,34 +20,20 @@ subject to the following restrictions:
struct btDispatcherInfo;
class btDispatcher;
#include "btBroadphaseProxy.h"
class btOverlappingPairCache;
struct btBroadphaseProxy;
#include "../../LinearMath/btVector3.h"
#include "LinearMath/btVector3.h"
///The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs.
///Some implementations for this broadphase interface include btAxisSweep3, bt32BitAxisSweep3 and btDbvtBroadphase.
///The actual overlapping pair management, storage, adding and removing of pairs is dealt by the btOverlappingPairCache class.
///BroadphaseInterface for aabb-overlapping object pairs
class btBroadphaseInterface
{
public:
virtual ~btBroadphaseInterface() {}
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 btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) =0;
virtual void destroyProxy(btBroadphaseProxy* proxy)=0;
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax)=0;
virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy)=0;
///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
virtual void calculateOverlappingPairs(btDispatcher* dispatcher)=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 printStats() = 0;
};

View File

@@ -16,8 +16,7 @@ subject to the following restrictions:
#ifndef BROADPHASE_PROXY_H
#define BROADPHASE_PROXY_H
#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE
#include "LinearMath/btAlignedAllocator.h"
#include "../../LinearMath/btScalar.h" //for SIMD_FORCE_INLINE
/// btDispatcher uses these types
@@ -39,7 +38,6 @@ IMPLICIT_CONVEX_SHAPES_START_HERE,
CONE_SHAPE_PROXYTYPE,
CONVEX_SHAPE_PROXYTYPE,
CYLINDER_SHAPE_PROXYTYPE,
UNIFORM_SCALING_SHAPE_PROXYTYPE,
MINKOWSKI_SUM_SHAPE_PROXYTYPE,
MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE,
//concave shapes
@@ -52,8 +50,6 @@ CONCAVE_SHAPES_START_HERE,
TERRAIN_SHAPE_PROXYTYPE,
///Used for GIMPACT Trimesh integration
GIMPACT_SHAPE_PROXYTYPE,
///Multimaterial mesh
MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE,
EMPTY_SHAPE_PROXYTYPE,
STATIC_PLANE_PROXYTYPE,
@@ -61,18 +57,13 @@ CONCAVE_SHAPES_END_HERE,
COMPOUND_SHAPE_PROXYTYPE,
SOFTBODY_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
///btBroadphaseProxy
struct btBroadphaseProxy
{
BT_DECLARE_ALIGNED_ALLOCATOR();
///optional filtering to cull potential collisions
enum CollisionFilterGroups
@@ -82,60 +73,44 @@ BT_DECLARE_ALIGNED_ALLOCATOR();
KinematicFilter = 4,
DebrisFilter = 8,
SensorTrigger = 16,
AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
AllFilter = DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
};
//Usually the client btCollisionObject or Rigidbody class
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.
SIMD_FORCE_INLINE int getUid() const
{
return m_uniqueId;
}
//used for memory pools
btBroadphaseProxy() :m_clientObject(0),m_multiSapParentProxy(0)
{
}
btBroadphaseProxy() :m_clientObject(0){}
btBroadphaseProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0)
btBroadphaseProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask)
:m_clientObject(userPtr),
m_collisionFilterGroup(collisionFilterGroup),
m_collisionFilterMask(collisionFilterMask)
{
m_multiSapParentProxy = multiSapParentProxy;
}
static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType)
static inline bool isPolyhedral(int proxyType)
{
return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE);
}
static SIMD_FORCE_INLINE bool isConvex(int proxyType)
static inline bool isConvex(int proxyType)
{
return (proxyType < CONCAVE_SHAPES_START_HERE);
}
static SIMD_FORCE_INLINE bool isConcave(int proxyType)
static inline bool isConcave(int proxyType)
{
return ((proxyType > CONCAVE_SHAPES_START_HERE) &&
(proxyType < CONCAVE_SHAPES_END_HERE));
}
static SIMD_FORCE_INLINE bool isCompound(int proxyType)
static inline bool isCompound(int proxyType)
{
return (proxyType == COMPOUND_SHAPE_PROXYTYPE);
}
static SIMD_FORCE_INLINE bool isInfinite(int proxyType)
static inline bool isInfinite(int proxyType)
{
return (proxyType == STATIC_PLANE_PROXYTYPE);
}
@@ -149,9 +124,8 @@ 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
/// contains a pair of aabb-overlapping objects
struct btBroadphasePair
{
btBroadphasePair ()
:
@@ -162,8 +136,6 @@ ATTRIBUTE_ALIGNED16(struct) btBroadphasePair
{
}
BT_DECLARE_ALIGNED_ALLOCATOR();
btBroadphasePair(const btBroadphasePair& other)
: m_pProxy0(other.m_pProxy0),
m_pProxy1(other.m_pProxy1),
@@ -209,7 +181,6 @@ SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePa
*/
class btBroadphasePairSortPredicate
{
public:

View File

@@ -18,6 +18,6 @@ subject to the following restrictions:
btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
{
m_dispatcher = ci.m_dispatcher1;
m_dispatcher = ci.m_dispatcher;
}

View File

@@ -16,8 +16,7 @@ subject to the following restrictions:
#ifndef COLLISION_ALGORITHM_H
#define COLLISION_ALGORITHM_H
#include "LinearMath/btScalar.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "../../LinearMath/btScalar.h"
struct btBroadphaseProxy;
class btDispatcher;
@@ -26,22 +25,21 @@ class btCollisionObject;
struct btDispatcherInfo;
class btPersistentManifold;
typedef btAlignedObjectArray<btPersistentManifold*> btManifoldArray;
struct btCollisionAlgorithmConstructionInfo
{
btCollisionAlgorithmConstructionInfo()
:m_dispatcher1(0),
:m_dispatcher(0),
m_manifold(0)
{
}
btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp)
:m_dispatcher1(dispatcher)
:m_dispatcher(dispatcher)
{
(void)temp;
}
btDispatcher* m_dispatcher1;
btDispatcher* m_dispatcher;
btPersistentManifold* m_manifold;
int getDispatcherId();
@@ -73,7 +71,6 @@ public:
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
virtual void getAllContactManifolds(btManifoldArray& manifoldArray) = 0;
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,547 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 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.
*/
///btDbvtBroadphase implementation by Nathanael Presson
#include "btDbvtBroadphase.h"
//
// Profiling
//
#if DBVT_BP_PROFILE||DBVT_BP_ENABLE_BENCHMARK
#include <stdio.h>
#endif
#if DBVT_BP_PROFILE
struct ProfileScope
{
__forceinline ProfileScope(btClock& clock,unsigned long& value) :
m_clock(&clock),m_value(&value),m_base(clock.getTimeMicroseconds())
{
}
__forceinline ~ProfileScope()
{
(*m_value)+=m_clock->getTimeMicroseconds()-m_base;
}
btClock* m_clock;
unsigned long* m_value;
unsigned long m_base;
};
#define SPC(_value_) ProfileScope spc_scope(m_clock,_value_)
#else
#define SPC(_value_)
#endif
//
// Helpers
//
//
template <typename T>
static inline void listappend(T* item,T*& list)
{
item->links[0]=0;
item->links[1]=list;
if(list) list->links[0]=item;
list=item;
}
//
template <typename T>
static inline void listremove(T* item,T*& list)
{
if(item->links[0]) item->links[0]->links[1]=item->links[1]; else list=item->links[1];
if(item->links[1]) item->links[1]->links[0]=item->links[0];
}
//
template <typename T>
static inline int listcount(T* root)
{
int n=0;
while(root) { ++n;root=root->links[1]; }
return(n);
}
//
template <typename T>
static inline void clear(T& value)
{
static const struct ZeroDummy : T {} zerodummy;
value=zerodummy;
}
//
// Colliders
//
/* Tree collider */
struct btDbvtTreeCollider : btDbvt::ICollide
{
btDbvtBroadphase* pbp;
btDbvtProxy* proxy;
btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {}
void Process(const btDbvtNode* na,const btDbvtNode* nb)
{
if(na!=nb)
{
btDbvtProxy* pa=(btDbvtProxy*)na->data;
btDbvtProxy* pb=(btDbvtProxy*)nb->data;
#if DBVT_BP_SORTPAIRS
if(pa>pb) btSwap(pa,pb);
#endif
pbp->m_paircache->addOverlappingPair(pa,pb);
++pbp->m_newpairs;
}
}
void Process(const btDbvtNode* n)
{
Process(n,proxy->leaf);
}
};
//
// btDbvtBroadphase
//
//
btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache)
{
m_deferedcollide = true;//false;
m_needcleanup = true;
m_releasepaircache = (paircache!=0)?false:true;
m_prediction = 1/(btScalar)2;
m_stageCurrent = 0;
m_fixedleft = 0;
m_fupdates = 1;
m_dupdates = 0;
m_cupdates = 10;
m_newpairs = 1;
m_updates_call = 0;
m_updates_done = 0;
m_updates_ratio = 0;
m_paircache = paircache?
paircache :
new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
m_gid = 0;
m_pid = 0;
m_cid = 0;
for(int i=0;i<=STAGECOUNT;++i)
{
m_stageRoots[i]=0;
}
#if DBVT_BP_PROFILE
clear(m_profiling);
#endif
}
//
btDbvtBroadphase::~btDbvtBroadphase()
{
if(m_releasepaircache)
{
m_paircache->~btOverlappingPairCache();
btAlignedFree(m_paircache);
}
}
//
btBroadphaseProxy* btDbvtBroadphase::createProxy( const btVector3& aabbMin,
const btVector3& aabbMax,
int /*shapeType*/,
void* userPtr,
short int collisionFilterGroup,
short int collisionFilterMask,
btDispatcher* dispatcher,
void* /*multiSapProxy*/)
{
btDbvtProxy* proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy( userPtr,
collisionFilterGroup,
collisionFilterMask);
proxy->aabb = btDbvtVolume::FromMM(aabbMin,aabbMax);
proxy->stage = m_stageCurrent;
proxy->m_uniqueId = ++m_gid;
proxy->leaf = m_sets[0].insert(proxy->aabb,proxy);
listappend(proxy,m_stageRoots[m_stageCurrent]);
if(!m_deferedcollide)
{
btDbvtTreeCollider collider(this);
collider.proxy=proxy;
btDbvt::collideTV(m_sets[0].m_root,proxy->aabb,collider);
}
return(proxy);
}
//
void btDbvtBroadphase::destroyProxy( btBroadphaseProxy* absproxy,
btDispatcher* dispatcher)
{
btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
if(proxy->stage==STAGECOUNT)
m_sets[1].remove(proxy->leaf);
else
m_sets[0].remove(proxy->leaf);
listremove(proxy,m_stageRoots[proxy->stage]);
m_paircache->removeOverlappingPairsContainingProxy(proxy,dispatcher);
btAlignedFree(proxy);
m_needcleanup=true;
}
//
void btDbvtBroadphase::setAabb( btBroadphaseProxy* absproxy,
const btVector3& aabbMin,
const btVector3& aabbMax,
btDispatcher* /*dispatcher*/)
{
btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
ATTRIBUTE_ALIGNED16(btDbvtVolume) aabb=btDbvtVolume::FromMM(aabbMin,aabbMax);
#if DBVT_BP_PREVENTFALSEUPDATE
if(NotEqual(aabb,proxy->leaf->volume))
#endif
{
bool docollide=false;
if(proxy->stage==STAGECOUNT)
{/* fixed -> dynamic set */
m_sets[1].remove(proxy->leaf);
proxy->leaf=m_sets[0].insert(aabb,proxy);
docollide=true;
}
else
{/* dynamic set */
++m_updates_call;
if(Intersect(proxy->leaf->volume,aabb))
{/* Moving */
const btVector3 delta=aabbMin-proxy->aabb.Mins();
btVector3 velocity(aabb.Extents()*m_prediction);
if(delta[0]<0) velocity[0]=-velocity[0];
if(delta[1]<0) velocity[1]=-velocity[1];
if(delta[2]<0) velocity[2]=-velocity[2];
if (
#ifdef DBVT_BP_MARGIN
m_sets[0].update(proxy->leaf,aabb,velocity,DBVT_BP_MARGIN)
#else
m_sets[0].update(proxy->leaf,aabb,velocity)
#endif
)
{
++m_updates_done;
docollide=true;
}
}
else
{/* Teleporting */
m_sets[0].update(proxy->leaf,aabb);
++m_updates_done;
docollide=true;
}
}
listremove(proxy,m_stageRoots[proxy->stage]);
proxy->aabb = aabb;
proxy->stage = m_stageCurrent;
listappend(proxy,m_stageRoots[m_stageCurrent]);
if(docollide)
{
m_needcleanup=true;
if(!m_deferedcollide)
{
btDbvtTreeCollider collider(this);
btDbvt::collideTT(m_sets[1].m_root,proxy->leaf,collider);
btDbvt::collideTT(m_sets[0].m_root,proxy->leaf,collider);
}
}
}
}
//
void btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
{
collide(dispatcher);
#if DBVT_BP_PROFILE
if(0==(m_pid%DBVT_BP_PROFILING_RATE))
{
printf("fixed(%u) dynamics(%u) pairs(%u)\r\n",m_sets[1].m_leaves,m_sets[0].m_leaves,m_paircache->getNumOverlappingPairs());
unsigned int total=m_profiling.m_total;
if(total<=0) total=1;
printf("ddcollide: %u%% (%uus)\r\n",(50+m_profiling.m_ddcollide*100)/total,m_profiling.m_ddcollide/DBVT_BP_PROFILING_RATE);
printf("fdcollide: %u%% (%uus)\r\n",(50+m_profiling.m_fdcollide*100)/total,m_profiling.m_fdcollide/DBVT_BP_PROFILING_RATE);
printf("cleanup: %u%% (%uus)\r\n",(50+m_profiling.m_cleanup*100)/total,m_profiling.m_cleanup/DBVT_BP_PROFILING_RATE);
printf("total: %uus\r\n",total/DBVT_BP_PROFILING_RATE);
const unsigned long sum=m_profiling.m_ddcollide+
m_profiling.m_fdcollide+
m_profiling.m_cleanup;
printf("leaked: %u%% (%uus)\r\n",100-((50+sum*100)/total),(total-sum)/DBVT_BP_PROFILING_RATE);
printf("job counts: %u%%\r\n",(m_profiling.m_jobcount*100)/((m_sets[0].m_leaves+m_sets[1].m_leaves)*DBVT_BP_PROFILING_RATE));
clear(m_profiling);
m_clock.reset();
}
#endif
}
//
void btDbvtBroadphase::collide(btDispatcher* dispatcher)
{
SPC(m_profiling.m_total);
/* optimize */
m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100);
if(m_fixedleft)
{
const int count=1+(m_sets[1].m_leaves*m_fupdates)/100;
m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100);
m_fixedleft=btMax<int>(0,m_fixedleft-count);
}
/* dynamic -> fixed set */
m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT;
btDbvtProxy* current=m_stageRoots[m_stageCurrent];
if(current)
{
btDbvtTreeCollider collider(this);
do {
btDbvtProxy* next=current->links[1];
listremove(current,m_stageRoots[current->stage]);
listappend(current,m_stageRoots[STAGECOUNT]);
#if DBVT_BP_ACCURATESLEEPING
m_paircache->removeOverlappingPairsContainingProxy(current,dispatcher);
collider.proxy=current;
btDbvt::collideTV(m_sets[0].m_root,current->aabb,collider);
btDbvt::collideTV(m_sets[1].m_root,current->aabb,collider);
#endif
m_sets[0].remove(current->leaf);
current->leaf = m_sets[1].insert(current->aabb,current);
current->stage = STAGECOUNT;
current = next;
} while(current);
m_fixedleft=m_sets[1].m_leaves;
m_needcleanup=true;
}
/* collide dynamics */
{
btDbvtTreeCollider collider(this);
if(m_deferedcollide)
{
SPC(m_profiling.m_fdcollide);
btDbvt::collideTT(m_sets[0].m_root,m_sets[1].m_root,collider);
}
if(m_deferedcollide)
{
SPC(m_profiling.m_ddcollide);
btDbvt::collideTT(m_sets[0].m_root,m_sets[0].m_root,collider);
}
}
/* clean up */
if(m_needcleanup)
{
SPC(m_profiling.m_cleanup);
btBroadphasePairArray& pairs=m_paircache->getOverlappingPairArray();
if(pairs.size()>0)
{
const int ci=pairs.size();
int ni=btMin(ci,btMax<int>(m_newpairs,(ci*m_cupdates)/100));
for(int i=0;i<ni;++i)
{
btBroadphasePair& p=pairs[(m_cid+i)%ci];
btDbvtProxy* pa=(btDbvtProxy*)p.m_pProxy0;
btDbvtProxy* pb=(btDbvtProxy*)p.m_pProxy1;
if(!Intersect(pa->leaf->volume,pb->leaf->volume))
{
#if DBVT_BP_SORTPAIRS
if(pa>pb) btSwap(pa,pb);
#endif
m_paircache->removeOverlappingPair(pa,pb,dispatcher);
--ni;--i;
}
}
if(pairs.size()>0) m_cid=(m_cid+ni)%pairs.size(); else m_cid=0;
}
}
++m_pid;
m_newpairs=1;
m_needcleanup=false;
if(m_updates_call>0)
{ m_updates_ratio=m_updates_done/(btScalar)m_updates_call; }
else
{ m_updates_ratio=0; }
m_updates_done/=2;
m_updates_call/=2;
}
//
void btDbvtBroadphase::optimize()
{
m_sets[0].optimizeTopDown();
m_sets[1].optimizeTopDown();
}
//
btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache()
{
return(m_paircache);
}
//
const btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() const
{
return(m_paircache);
}
//
void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
{
ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds;
if(!m_sets[0].empty())
if(!m_sets[1].empty()) Merge( m_sets[0].m_root->volume,
m_sets[1].m_root->volume,bounds);
else
bounds=m_sets[0].m_root->volume;
else if(!m_sets[1].empty()) bounds=m_sets[1].m_root->volume;
else
bounds=btDbvtVolume::FromCR(btVector3(0,0,0),0);
aabbMin=bounds.Mins();
aabbMax=bounds.Maxs();
}
//
void btDbvtBroadphase::printStats()
{}
//
#if DBVT_BP_ENABLE_BENCHMARK
struct btBroadphaseBenchmark
{
struct Experiment
{
const char* name;
int object_count;
int update_count;
int spawn_count;
int iterations;
btScalar speed;
btScalar amplitude;
};
struct Object
{
btVector3 center;
btVector3 extents;
btBroadphaseProxy* proxy;
btScalar time;
void update(btScalar speed,btScalar amplitude,btBroadphaseInterface* pbi)
{
time += speed;
center[0] = btCos(time*(btScalar)2.17)*amplitude+
btSin(time)*amplitude/2;
center[1] = btCos(time*(btScalar)1.38)*amplitude+
btSin(time)*amplitude;
center[2] = btSin(time*(btScalar)0.777)*amplitude;
pbi->setAabb(proxy,center-extents,center+extents,0);
}
};
static int UnsignedRand(int range=RAND_MAX-1) { return(rand()%(range+1)); }
static btScalar UnitRand() { return(UnsignedRand(16384)/(btScalar)16384); }
static void OutputTime(const char* name,btClock& c,unsigned count=0)
{
const unsigned long us=c.getTimeMicroseconds();
const unsigned long ms=(us+500)/1000;
const btScalar sec=us/(btScalar)(1000*1000);
if(count>0)
printf("%s : %u us (%u ms), %.2f/s\r\n",name,us,ms,count/sec);
else
printf("%s : %u us (%u ms)\r\n",name,us,ms);
}
};
void btDbvtBroadphase::benchmark(btBroadphaseInterface* pbi)
{
static const btBroadphaseBenchmark::Experiment experiments[]=
{
{"1024o.10%",1024,10,0,8192,(btScalar)0.005,(btScalar)100},
/*{"4096o.10%",4096,10,0,8192,(btScalar)0.005,(btScalar)100},
{"8192o.10%",8192,10,0,8192,(btScalar)0.005,(btScalar)100},*/
};
static const int nexperiments=sizeof(experiments)/sizeof(experiments[0]);
btAlignedObjectArray<btBroadphaseBenchmark::Object*> objects;
btClock wallclock;
/* Begin */
for(int iexp=0;iexp<nexperiments;++iexp)
{
const btBroadphaseBenchmark::Experiment& experiment=experiments[iexp];
const int object_count=experiment.object_count;
const int update_count=(object_count*experiment.update_count)/100;
const int spawn_count=(object_count*experiment.spawn_count)/100;
const btScalar speed=experiment.speed;
const btScalar amplitude=experiment.amplitude;
printf("Experiment #%u '%s':\r\n",iexp,experiment.name);
printf("\tObjects: %u\r\n",object_count);
printf("\tUpdate: %u\r\n",update_count);
printf("\tSpawn: %u\r\n",spawn_count);
printf("\tSpeed: %f\r\n",speed);
printf("\tAmplitude: %f\r\n",amplitude);
srand(180673);
/* Create objects */
wallclock.reset();
objects.reserve(object_count);
for(int i=0;i<object_count;++i)
{
btBroadphaseBenchmark::Object* po=new btBroadphaseBenchmark::Object();
po->center[0]=btBroadphaseBenchmark::UnitRand()*50;
po->center[1]=btBroadphaseBenchmark::UnitRand()*50;
po->center[2]=btBroadphaseBenchmark::UnitRand()*50;
po->extents[0]=btBroadphaseBenchmark::UnitRand()*2+2;
po->extents[1]=btBroadphaseBenchmark::UnitRand()*2+2;
po->extents[2]=btBroadphaseBenchmark::UnitRand()*2+2;
po->time=btBroadphaseBenchmark::UnitRand()*2000;
po->proxy=pbi->createProxy(po->center-po->extents,po->center+po->extents,0,po,1,1,0,0);
objects.push_back(po);
}
btBroadphaseBenchmark::OutputTime("\tInitialization",wallclock);
/* First update */
wallclock.reset();
for(int i=0;i<objects.size();++i)
{
objects[i]->update(speed,amplitude,pbi);
}
btBroadphaseBenchmark::OutputTime("\tFirst update",wallclock);
/* Updates */
wallclock.reset();
for(int i=0;i<experiment.iterations;++i)
{
for(int j=0;j<update_count;++j)
{
objects[j]->update(speed,amplitude,pbi);
}
pbi->calculateOverlappingPairs(0);
}
btBroadphaseBenchmark::OutputTime("\tUpdate",wallclock,experiment.iterations);
/* Clean up */
wallclock.reset();
for(int i=0;i<objects.size();++i)
{
pbi->destroyProxy(objects[i]->proxy,0);
delete objects[i];
}
objects.resize(0);
btBroadphaseBenchmark::OutputTime("\tRelease",wallclock);
}
}
#else
void btDbvtBroadphase::benchmark(btBroadphaseInterface*)
{}
#endif
#if DBVT_BP_PROFILE
#undef SPC
#endif

View File

@@ -1,117 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 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.
*/
///btDbvtBroadphase implementation by Nathanael Presson
#ifndef BT_DBVT_BROADPHASE_H
#define BT_DBVT_BROADPHASE_H
#include "BulletCollision/BroadphaseCollision/btDbvt.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
//
// Compile time config
//
#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
#if DBVT_BP_PROFILE
#define DBVT_BP_PROFILING_RATE 256
#include "LinearMath/btQuickprof.h"
#endif
//
// btDbvtProxy
//
struct btDbvtProxy : btBroadphaseProxy
{
/* Fields */
btDbvtAabbMm aabb;
btDbvtNode* leaf;
btDbvtProxy* links[2];
int stage;
/* ctor */
btDbvtProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) :
btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask)
{
links[0]=links[1]=0;
}
};
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
{
/* 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?
bool m_initialize; // Initialization
#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;
#endif
/* Methods */
btDbvtBroadphase(btOverlappingPairCache* paircache=0);
~btDbvtBroadphase();
void collide(btDispatcher* dispatcher);
void optimize();
/* btBroadphaseInterface Implementation */
btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
void calculateOverlappingPairs(btDispatcher* dispatcher);
btOverlappingPairCache* getOverlappingPairCache();
const btOverlappingPairCache* getOverlappingPairCache() const;
void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const;
void printStats();
static void benchmark(btBroadphaseInterface*);
};
#endif

View File

@@ -16,7 +16,7 @@ subject to the following restrictions:
#ifndef _DISPATCHER_H
#define _DISPATCHER_H
#include "LinearMath/btScalar.h"
#include "../../LinearMath/btScalar.h"
class btCollisionAlgorithm;
struct btBroadphaseProxy;
@@ -43,9 +43,7 @@ struct btDispatcherInfo
m_useContinuous(false),
m_debugDraw(0),
m_enableSatConvex(false),
m_enableSPU(true),
m_useEpa(true),
m_allowedCcdPenetration(btScalar(0.04)),
m_enableSPU(false),
m_stackAllocator(0)
{
@@ -53,19 +51,17 @@ struct btDispatcherInfo
btScalar m_timeStep;
int m_stepCount;
int m_dispatchFunc;
mutable btScalar m_timeOfImpact;
btScalar m_timeOfImpact;
bool m_useContinuous;
class btIDebugDraw* m_debugDraw;
bool m_enableSatConvex;
bool m_enableSPU;
bool m_useEpa;
btScalar m_allowedCcdPenetration;
btStackAlloc* m_stackAllocator;
};
///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).
/// btDispatcher can be used in combination with broadphase to dispatch overlapping pairs.
/// For example for pairwise collision detection or user callbacks (game logic).
class btDispatcher
{
@@ -85,18 +81,12 @@ public:
virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0;
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) =0;
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo)=0;
virtual int getNumManifolds() const = 0;
virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0;
virtual btPersistentManifold** getInternalManifoldPointer() = 0;
virtual void* allocateCollisionAlgorithm(int size) = 0;
virtual void freeCollisionAlgorithm(void* ptr) = 0;
};

View File

@@ -1,466 +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 "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();
}
//#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);
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 )
{
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();
}
*/
}

View File

@@ -1,144 +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_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 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(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);
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(-1e30f,-1e30f,-1e30f);
aabbMax.setValue(1e30f,1e30f,1e30f);
}
void buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax);
virtual void printStats();
void quicksort (btBroadphasePairArray& a, int lo, int hi);
};
#endif //BT_MULTI_SAP_BROADPHASE

View File

@@ -1,3 +1,4 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
@@ -20,43 +21,44 @@ subject to the following restrictions:
#include "btDispatcher.h"
#include "btCollisionAlgorithm.h"
#include <stdio.h>
int gOverlappingPairs = 0;
int gRemovePairs =0;
int gAddedPairs =0;
int gFindPairs =0;
btHashedOverlappingPairCache::btHashedOverlappingPairCache():
m_overlapFilterCallback(0),
m_blockedForChanges(false)
btOverlappingPairCache::btOverlappingPairCache():
m_blockedForChanges(false),
m_overlapFilterCallback(0)
//m_NumOverlapBroadphasePair(0)
{
int initialAllocatedSize= 2;
m_overlappingPairArray.reserve(initialAllocatedSize);
growTables();
}
btHashedOverlappingPairCache::~btHashedOverlappingPairCache()
btOverlappingPairCache::~btOverlappingPairCache()
{
//todo/test: show we erase/delete data, or is it automatic
}
void btOverlappingPairCache::removeOverlappingPair(btBroadphasePair& findPair)
{
int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
if (findIndex < m_overlappingPairArray.size())
{
gOverlappingPairs--;
btBroadphasePair& pair = m_overlappingPairArray[findIndex];
cleanOverlappingPair(pair);
m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.size()-1);
m_overlappingPairArray.pop_back();
}
}
void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
void btOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair)
{
if (pair.m_algorithm)
{
{
pair.m_algorithm->~btCollisionAlgorithm();
dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
delete pair.m_algorithm;;
pair.m_algorithm=0;
}
}
@@ -65,370 +67,20 @@ void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,b
void btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
{
class CleanPairCallback : public btOverlapCallback
{
btBroadphaseProxy* m_cleanProxy;
btOverlappingPairCache* m_pairCache;
btDispatcher* m_dispatcher;
public:
CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
:m_cleanProxy(cleanProxy),
m_pairCache(pairCache),
m_dispatcher(dispatcher)
{
}
virtual bool processOverlap(btBroadphasePair& pair)
{
if ((pair.m_pProxy0 == m_cleanProxy) ||
(pair.m_pProxy1 == m_cleanProxy))
{
m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
}
return false;
}
};
CleanPairCallback cleanPairs(proxy,this,dispatcher);
processAllOverlappingPairs(&cleanPairs,dispatcher);
}
void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
{
class RemovePairCallback : public btOverlapCallback
{
btBroadphaseProxy* m_obsoleteProxy;
public:
RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
:m_obsoleteProxy(obsoleteProxy)
{
}
virtual bool processOverlap(btBroadphasePair& pair)
{
return ((pair.m_pProxy0 == m_obsoleteProxy) ||
(pair.m_pProxy1 == m_obsoleteProxy));
}
};
RemovePairCallback removeCallback(proxy);
processAllOverlappingPairs(&removeCallback,dispatcher);
}
btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
{
gFindPairs++;
if(proxy0>proxy1) 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));
if (hash >= m_hashTable.size())
{
return NULL;
}
int index = m_hashTable[hash];
while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
{
index = m_next[index];
}
if (index == BT_NULL_PAIR)
{
return NULL;
}
btAssert(index < m_overlappingPairArray.size());
return &m_overlappingPairArray[index];
}
//#include <stdio.h>
void btHashedOverlappingPairCache::growTables()
{
int newCapacity = m_overlappingPairArray.capacity();
if (m_hashTable.size() < newCapacity)
{
//grow hashtable and next table
int curHashtableSize = m_hashTable.size();
m_hashTable.resize(newCapacity);
m_next.resize(newCapacity);
int i;
for (i= 0; i < newCapacity; ++i)
{
m_hashTable[i] = BT_NULL_PAIR;
}
for (i = 0; i < newCapacity; ++i)
{
m_next[i] = BT_NULL_PAIR;
}
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
m_next[i] = m_hashTable[hashValue];
m_hashTable[hashValue] = i;
}
}
}
btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
{
if(proxy0>proxy1) 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
btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
if (pair != NULL)
{
return pair;
}
/*for(int i=0;i<m_overlappingPairArray.size();++i)
{
if( (m_overlappingPairArray[i].m_pProxy0==proxy0)&&
(m_overlappingPairArray[i].m_pProxy1==proxy1))
{
printf("Adding duplicated %u<>%u\r\n",proxyId1,proxyId2);
internalFindPair(proxy0, proxy1, hash);
}
}*/
int count = m_overlappingPairArray.size();
int oldCapacity = m_overlappingPairArray.capacity();
void* mem = &m_overlappingPairArray.expand();
int newCapacity = m_overlappingPairArray.capacity();
if (oldCapacity < newCapacity)
{
growTables();
//hash with new capacity
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->m_algorithm = 0;
pair->m_userInfo = 0;
m_next[count] = m_hashTable[hash];
m_hashTable[hash] = count;
return pair;
}
void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
{
gRemovePairs++;
if(proxy0>proxy1) 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));
btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
if (pair == NULL)
{
return 0;
}
cleanOverlappingPair(*pair,dispatcher);
void* userData = pair->m_userInfo;
btAssert(pair->m_pProxy0->getUid() == proxyId1);
btAssert(pair->m_pProxy1->getUid() == proxyId2);
int pairIndex = int(pair - &m_overlappingPairArray[0]);
btAssert(pairIndex < m_overlappingPairArray.size());
// Remove the pair from the hash table.
int index = m_hashTable[hash];
btAssert(index != BT_NULL_PAIR);
int previous = BT_NULL_PAIR;
while (index != pairIndex)
{
previous = index;
index = m_next[index];
}
if (previous != BT_NULL_PAIR)
{
btAssert(m_next[previous] == pairIndex);
m_next[previous] = m_next[pairIndex];
}
else
{
m_hashTable[hash] = m_next[pairIndex];
}
// We now move the last pair into spot of the
// pair being removed. We need to fix the hash
// table indices to support the move.
int lastPairIndex = m_overlappingPairArray.size() - 1;
// If the removed pair is the last pair, we are done.
if (lastPairIndex == pairIndex)
{
m_overlappingPairArray.pop_back();
return userData;
}
// 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));
index = m_hashTable[lastHash];
btAssert(index != BT_NULL_PAIR);
previous = BT_NULL_PAIR;
while (index != lastPairIndex)
{
previous = index;
index = m_next[index];
}
if (previous != BT_NULL_PAIR)
{
btAssert(m_next[previous] == lastPairIndex);
m_next[previous] = m_next[lastPairIndex];
}
else
{
m_hashTable[lastHash] = m_next[lastPairIndex];
}
// Copy the last pair into the remove pair's spot.
m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex];
// Insert the last pair into the hash table
m_next[pairIndex] = m_hashTable[lastHash];
m_hashTable[lastHash] = pairIndex;
m_overlappingPairArray.pop_back();
return userData;
}
//#include <stdio.h>
void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
{
int i;
// 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);
gOverlappingPairs--;
} else
{
i++;
}
}
}
void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1, btDispatcher* dispatcher )
{
if (!hasDeferredRemoval())
{
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_userInfo;
cleanOverlappingPair(pair,dispatcher);
m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1);
m_overlappingPairArray.pop_back();
return userData;
}
}
return 0;
}
btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
void btOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
//don't add overlap with own
assert(proxy0 != proxy1);
if (!needsBroadphaseCollision(proxy0,proxy1))
return 0;
return;
btBroadphasePair pair(*proxy0,*proxy1);
void* mem = &m_overlappingPairArray.expand();
btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
m_overlappingPairArray.push_back(pair);
gOverlappingPairs++;
gAddedPairs++;
return pair;
}
@@ -436,7 +88,7 @@ btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseP
///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* btOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
if (!needsBroadphaseCollision(proxy0,proxy1))
return 0;
@@ -457,81 +109,18 @@ btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseP
//#include <stdio.h>
void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
{
int i;
for (i=0;i<m_overlappingPairArray.size();)
{
btBroadphasePair* pair = &m_overlappingPairArray[i];
if (callback->processOverlap(*pair))
{
cleanOverlappingPair(*pair,dispatcher);
m_overlappingPairArray.swap(i,m_overlappingPairArray.capacity()-1);
m_overlappingPairArray.pop_back();
gOverlappingPairs--;
} else
{
i++;
}
}
}
btSortedOverlappingPairCache::btSortedOverlappingPairCache():
m_blockedForChanges(false),
m_hasDeferredRemoval(true),
m_overlapFilterCallback(0)
{
int initialAllocatedSize= 2;
m_overlappingPairArray.reserve(initialAllocatedSize);
}
btSortedOverlappingPairCache::~btSortedOverlappingPairCache()
{
//todo/test: show we erase/delete data, or is it automatic
}
void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
{
if (pair.m_algorithm)
{
{
pair.m_algorithm->~btCollisionAlgorithm();
dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
pair.m_algorithm=0;
gRemovePairs--;
}
}
}
void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
void btOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy)
{
class CleanPairCallback : public btOverlapCallback
{
btBroadphaseProxy* m_cleanProxy;
btOverlappingPairCache* m_pairCache;
btDispatcher* m_dispatcher;
public:
CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache)
:m_cleanProxy(cleanProxy),
m_pairCache(pairCache),
m_dispatcher(dispatcher)
m_pairCache(pairCache)
{
}
virtual bool processOverlap(btBroadphasePair& pair)
@@ -539,21 +128,22 @@ void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,
if ((pair.m_pProxy0 == m_cleanProxy) ||
(pair.m_pProxy1 == m_cleanProxy))
{
m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
m_pairCache->cleanOverlappingPair(pair);
}
return false;
}
};
CleanPairCallback cleanPairs(proxy,this,dispatcher);
CleanPairCallback cleanPairs(proxy,this);
processAllOverlappingPairs(&cleanPairs,dispatcher);
processAllOverlappingPairs(&cleanPairs);
}
void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
void btOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy)
{
class RemovePairCallback : public btOverlapCallback
@@ -573,7 +163,34 @@ void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroad
};
RemovePairCallback removeCallback(proxy);
processAllOverlappingPairs(&removeCallback,dispatcher);
processAllOverlappingPairs(&removeCallback);
}
void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback)
{
int i;
for (i=0;i<m_overlappingPairArray.size();)
{
btBroadphasePair* pair = &m_overlappingPairArray[i];
if (callback->processOverlap(*pair))
{
cleanOverlappingPair(*pair);
m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
m_overlappingPairArray.pop_back();
gOverlappingPairs--;
} else
{
i++;
}
}
}

View File

@@ -1,3 +1,4 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
@@ -19,13 +20,9 @@ subject to the following restrictions:
#include "btBroadphaseInterface.h"
#include "btBroadphaseProxy.h"
#include "btOverlappingPairCallback.h"
#include "../../LinearMath/btPoint3.h"
#include "../../LinearMath/btAlignedObjectArray.h"
#include "LinearMath/btPoint3.h"
#include "LinearMath/btAlignedObjectArray.h"
class btDispatcher;
typedef btAlignedObjectArray<btBroadphasePair> btBroadphasePairArray;
struct btOverlapCallback
{
@@ -33,7 +30,6 @@ struct btOverlapCallback
{}
//return true for deletion of the pair
virtual bool processOverlap(btBroadphasePair& pair) = 0;
};
struct btOverlapFilterCallback
@@ -44,261 +40,38 @@ struct btOverlapFilterCallback
virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0;
};
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 btBroadphasePair* getOverlappingPairArrayPtr() = 0;
virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0;
virtual btBroadphasePairArray& getOverlappingPairArray() = 0;
virtual void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0;
virtual int getNumOverlappingPairs() const = 0;
virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) = 0;
virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0;
virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0;
virtual bool hasDeferredRemoval() = 0;
};
/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
class btHashedOverlappingPairCache : public btOverlappingPairCache
{
btBroadphasePairArray m_overlappingPairArray;
btOverlapFilterCallback* m_overlapFilterCallback;
bool m_blockedForChanges;
public:
btHashedOverlappingPairCache();
virtual ~btHashedOverlappingPairCache();
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
{
if (m_overlapFilterCallback)
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)
{
gAddedPairs++;
if (!needsBroadphaseCollision(proxy0,proxy1))
return 0;
return internalAddPair(proxy0,proxy1);
}
void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
virtual btBroadphasePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
const btBroadphasePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
btBroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
const btBroadphasePairArray& getOverlappingPairArray() const
{
return m_overlappingPairArray;
}
void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
int GetCount() const { return m_overlappingPairArray.size(); }
// btBroadphasePair* GetPairs() { return m_pairs; }
btOverlapFilterCallback* getOverlapFilterCallback()
{
return m_overlapFilterCallback;
}
void setOverlapFilterCallback(btOverlapFilterCallback* callback)
{
m_overlapFilterCallback = callback;
}
int getNumOverlappingPairs() const
{
return m_overlappingPairArray.size();
}
private:
btBroadphasePair* internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
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;
}
/*
// Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm
// This assumes proxyId1 and proxyId2 are 16-bit.
SIMD_FORCE_INLINE int getHash(int proxyId1, int proxyId2)
{
int key = (proxyId2 << 16) | proxyId1;
key = ~key + (key << 15);
key = key ^ (key >> 12);
key = key + (key << 2);
key = key ^ (key >> 4);
key = key * 2057;
key = key ^ (key >> 16);
return key;
}
*/
SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
{
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 << 11);
key ^= (key >> 16);
return static_cast<unsigned int>(key);
}
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 (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);
#endif
int index = m_hashTable[hash];
while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
{
index = m_next[index];
}
if ( index == BT_NULL_PAIR )
{
return NULL;
}
btAssert(index < m_overlappingPairArray.size());
return &m_overlappingPairArray[index];
}
virtual bool hasDeferredRemoval()
{
return false;
}
public:
btAlignedObjectArray<int> m_hashTable;
btAlignedObjectArray<int> m_next;
};
///btSortedOverlappingPairCache maintains the objects with overlapping AABB
///btOverlappingPairCache maintains the objects with overlapping AABB
///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase
class btSortedOverlappingPairCache : public btOverlappingPairCache
class btOverlappingPairCache : public btBroadphaseInterface
{
protected:
//avoid brute-force finding all the time
btBroadphasePairArray m_overlappingPairArray;
btAlignedObjectArray<btBroadphasePair> m_overlappingPairArray;
//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;
//if set, use the callback instead of the built in filter in needBroadphaseCollision
btOverlapFilterCallback* m_overlapFilterCallback;
public:
btSortedOverlappingPairCache();
virtual ~btSortedOverlappingPairCache();
btOverlappingPairCache();
virtual ~btOverlappingPairCache();
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
virtual void processAllOverlappingPairs(btOverlapCallback*);
void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
void removeOverlappingPair(btBroadphasePair& pair);
void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
void cleanOverlappingPair(btBroadphasePair& pair);
btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
void addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
void cleanProxyFromPairs(btBroadphaseProxy* proxy);
void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy);
inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
@@ -311,19 +84,10 @@ class btSortedOverlappingPairCache : public btOverlappingPairCache
return collides;
}
btBroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
const btBroadphasePairArray& getOverlappingPairArray() const
{
return m_overlappingPairArray;
}
virtual void refreshOverlappingPairs() =0;
btBroadphasePair* getOverlappingPairArrayPtr()
{
@@ -350,88 +114,7 @@ class btSortedOverlappingPairCache : public btOverlappingPairCache
m_overlapFilterCallback = callback;
}
virtual bool hasDeferredRemoval()
{
return m_hasDeferredRemoval;
}
};
///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and testing.
class btNullPairCache : public btOverlappingPairCache
{
btBroadphasePairArray m_overlappingPairArray;
public:
virtual btBroadphasePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
const btBroadphasePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
btBroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/)
{
}
virtual int getNumOverlappingPairs() const
{
return 0;
}
virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
{
}
virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
{
}
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/)
{
}
virtual btBroadphasePair* findPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/)
{
return 0;
}
virtual bool hasDeferredRemoval()
{
return true;
}
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/)
{
return 0;
}
virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/,btDispatcher* /*dispatcher*/)
{
return 0;
}
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/)
{
}
};
#endif //OVERLAPPING_PAIR_CACHE_H

View File

@@ -1,40 +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 OVERLAPPING_PAIR_CALLBACK_H
#define OVERLAPPING_PAIR_CALLBACK_H
class btDispatcher;
struct btBroadphasePair;
///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
class btOverlappingPairCallback
{
public:
virtual ~btOverlappingPairCallback()
{
}
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0;
virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) = 0;
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) = 0;
};
#endif //OVERLAPPING_PAIR_CALLBACK_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,486 +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 QUANTIZED_BVH_H
#define QUANTIZED_BVH_H
//#define DEBUG_CHECK_DEQUANTIZATION 1
#ifdef DEBUG_CHECK_DEQUANTIZATION
#ifdef __SPU__
#define printf spu_printf
#endif //__SPU__
#include <stdio.h>
#include <stdlib.h>
#endif //DEBUG_CHECK_DEQUANTIZATION
#include "LinearMath/btVector3.h"
#include "LinearMath/btAlignedAllocator.h"
//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
// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
// actually) triangles each (since the sign bit is reserved
#define MAX_NUM_PARTS_IN_BITS 10
///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
{
BT_DECLARE_ALIGNED_ALLOCATOR();
//12 bytes
unsigned short int m_quantizedAabbMin[3];
unsigned short int m_quantizedAabbMax[3];
//4 bytes
int m_escapeIndexOrTriangleIndex;
bool isLeafNode() const
{
//skipindex is negative (internal node), triangleindex >=0 (leafnode)
return (m_escapeIndexOrTriangleIndex >= 0);
}
int getEscapeIndex() const
{
btAssert(!isLeafNode());
return -m_escapeIndexOrTriangleIndex;
}
int getTriangleIndex() const
{
btAssert(isLeafNode());
// Get only the lower bits where the triangle index is stored
return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS)));
}
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));
}
}
;
/// 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
{
BT_DECLARE_ALIGNED_ALLOCATOR();
//32 bytes
btVector3 m_aabbMinOrg;
btVector3 m_aabbMaxOrg;
//4
int m_escapeIndex;
//8
//for child nodes
int m_subPart;
int m_triangleIndex;
int m_padding[5];//bad, due to alignment
};
///btBvhSubtreeInfo provides info to gather a subtree of limited size
ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo
{
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
//12 bytes
unsigned short int m_quantizedAabbMin[3];
unsigned short int m_quantizedAabbMax[3];
//4 bytes, points to the root of the subtree
int m_rootNodeIndex;
//4 bytes
int m_subtreeSize;
int m_padding[3];
btBvhSubtreeInfo()
{
//memset(&m_padding[0], 0, sizeof(m_padding));
}
void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode)
{
m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2];
m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0];
m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
}
}
;
class btNodeOverlapCallback
{
public:
virtual ~btNodeOverlapCallback() {};
virtual void processNode(int subPart, int triangleIndex) = 0;
};
#include "LinearMath/btAlignedAllocator.h"
#include "LinearMath/btAlignedObjectArray.h"
///for code readability:
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, and by the btMultiSapBroadphase.
///It is recommended to use quantization for better performance and lower memory requirements.
ATTRIBUTE_ALIGNED16(class) btQuantizedBvh
{
protected:
NodeArray m_leafNodes;
NodeArray m_contiguousNodes;
QuantizedNodeArray m_quantizedLeafNodes;
QuantizedNodeArray m_quantizedContiguousNodes;
int m_curNodeIndex;
//quantization data
bool m_useQuantization;
btVector3 m_bvhAabbMin;
btVector3 m_bvhAabbMax;
btVector3 m_bvhQuantization;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
enum btTraversalMode
{
TRAVERSAL_STACKLESS = 0,
TRAVERSAL_STACKLESS_CACHE_FRIENDLY,
TRAVERSAL_RECURSIVE
};
protected:
btTraversalMode m_traversalMode;
BvhSubtreeInfoArray m_SubtreeHeaders;
//This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray
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)
{
if (m_useQuantization)
{
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0);
} else
{
m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
}
}
void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax)
{
if (m_useQuantization)
{
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1);
} else
{
m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
}
}
btVector3 getAabbMin(int nodeIndex) const
{
if (m_useQuantization)
{
return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]);
}
//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)
{
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)
{
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++)
{
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
{
//non-quantized
m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
}
}
void swapLeafNodes(int firstIndex,int secondIndex);
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 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;
///tree traversal designed for small-memory processors like PS3 SPU
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;
///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const;
#define USE_BANCHLESS 1
#ifdef USE_BANCHLESS
//This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360)
SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const
{
return static_cast<unsigned int>(btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0])
& (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2])
& (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
1, 0));
}
#else
SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const
{
bool overlap = true;
overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
return overlap;
}
#endif //USE_BANCHLESS
void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex);
public:
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; }
///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
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;
SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const
{
btAssert(m_useQuantization);
btAssert(point.getX() <= m_bvhAabbMax.getX());
btAssert(point.getY() <= m_bvhAabbMax.getY());
btAssert(point.getZ() <= m_bvhAabbMax.getZ());
btAssert(point.getX() >= m_bvhAabbMin.getX());
btAssert(point.getY() >= m_bvhAabbMin.getY());
btAssert(point.getZ() >= m_bvhAabbMin.getZ());
btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization;
///Make sure rounding is done in a way that unQuantize(quantizeWithClamp(...)) is conservative
///end-points always set the first bit, so that they are sorted properly (so that neighbouring AABBs overlap properly)
///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()) & 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());
}
if (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());
}
} else
{
if (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());
}
if (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
}
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);
}
SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const
{
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;
}
///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)
{
m_traversalMode = traversalMode;
}
SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
{
return m_quantizedContiguousNodes;
}
SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
{
return m_SubtreeHeaders;
}
/////Calculate space needed to store BVH for serialization
unsigned calculateSerializeBufferSize();
/// Data buffer MUST be 16 byte aligned
virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian);
///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 unsigned int getAlignmentSerializationPadding();
SIMD_FORCE_INLINE bool isQuantized()
{
return m_useQuantization;
}
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);
}
;
#endif //QUANTIZED_BVH_H

View File

@@ -14,84 +14,83 @@ subject to the following restrictions:
*/
#include "btSimpleBroadphase.h"
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include <BulletCollision/BroadphaseCollision/btDispatcher.h>
#include <BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h>
#include "LinearMath/btVector3.h"
#include "LinearMath/btTransform.h"
#include "LinearMath/btMatrix3x3.h"
#include <new>
extern int gOverlappingPairs;
void btSimpleBroadphase::validate()
{
for (int i=0;i<m_numHandles;i++)
for (int i=0;i<m_numProxies;i++)
{
for (int j=i+1;j<m_numHandles;j++)
for (int j=i+1;j<m_numProxies;j++)
{
btAssert(&m_pHandles[i] != &m_pHandles[j]);
assert(m_pProxies[i] != m_pProxies[j]);
}
}
}
btSimpleBroadphase::btSimpleBroadphase(int maxProxies, btOverlappingPairCache* overlappingPairCache)
:m_pairCache(overlappingPairCache),
m_ownsPairCache(false),
m_invalidPair(0)
btSimpleBroadphase::btSimpleBroadphase(int maxProxies)
:btOverlappingPairCache(),
m_firstFreeProxy(0),
m_numProxies(0),
m_maxProxies(maxProxies)
{
if (!overlappingPairCache)
{
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_maxHandles = maxProxies;
m_numHandles = 0;
m_firstFreeHandle = 0;
m_proxies = new btSimpleBroadphaseProxy[maxProxies];
m_freeProxies = new int[maxProxies];
m_pProxies = new btSimpleBroadphaseProxy*[maxProxies];
int i;
for (i=0;i<m_maxProxies;i++)
{
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[maxProxies - 1].SetNextFree(0);
m_freeProxies[i] = i;
}
}
btSimpleBroadphase::~btSimpleBroadphase()
{
btAlignedFree(m_pHandlesRawPtr);
delete[] m_proxies;
delete []m_freeProxies;
delete [] m_pProxies;
if (m_ownsPairCache)
/*int i;
for (i=m_numProxies-1;i>=0;i--)
{
m_pairCache->~btOverlappingPairCache();
btAlignedFree(m_pairCache);
BP_Proxy* proxy = m_pProxies[i];
destroyProxy(proxy);
}
*/
}
btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* /*dispatcher*/,void* multiSapProxy)
btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask)
{
if (m_numHandles >= m_maxHandles)
if (m_numProxies >= m_maxProxies)
{
btAssert(0);
assert(0);
return 0; //should never happen, but don't let the game crash ;-)
}
assert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]);
assert(min[0]<= max[0] && min[1]<= max[1] && min[2]<= max[2]);
int newHandleIndex = allocHandle();
btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy);
int freeIndex= m_freeProxies[m_firstFreeProxy];
btSimpleBroadphaseProxy* proxy = new (&m_proxies[freeIndex])btSimpleBroadphaseProxy(min,max,shapeType,userPtr,collisionFilterGroup,collisionFilterMask);
m_firstFreeProxy++;
btSimpleBroadphaseProxy* proxy1 = &m_proxies[0];
int index = int(proxy - proxy1);
btAssert(index == freeIndex);
m_pProxies[m_numProxies] = proxy;
m_numProxies++;
//validate();
return proxy;
}
@@ -125,19 +124,34 @@ protected:
};
};
void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* dispatcher)
void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg)
{
int i;
btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxyOrg);
freeHandle(proxy0);
m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher);
btSimpleBroadphaseProxy* proxy1 = &m_proxies[0];
int index = int(proxy0 - proxy1);
btAssert (index < m_maxProxies);
m_freeProxies[--m_firstFreeProxy] = index;
removeOverlappingPairsContainingProxy(proxyOrg);
for (i=0;i<m_numProxies;i++)
{
if (m_pProxies[i] == proxyOrg)
{
m_pProxies[i] = m_pProxies[m_numProxies-1];
break;
}
}
m_numProxies--;
//validate();
}
void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* /*dispatcher*/)
void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax)
{
btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
sbp->m_min = aabbMin;
@@ -172,129 +186,37 @@ public:
}
};
void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
void btSimpleBroadphase::refreshOverlappingPairs()
{
//first check for new overlapping pairs
int i,j;
if (m_numHandles >= 0)
for (i=0;i<m_numProxies;i++)
{
for (i=0;i<m_numHandles;i++)
btBroadphaseProxy* proxy0 = m_pProxies[i];
for (j=i+1;j<m_numProxies;j++)
{
btSimpleBroadphaseProxy* proxy0 = &m_pHandles[i];
btBroadphaseProxy* proxy1 = m_pProxies[j];
btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
for (j=i+1;j<m_numHandles;j++)
if (aabbOverlap(p0,p1))
{
btSimpleBroadphaseProxy* proxy1 = &m_pHandles[j];
btAssert(proxy0 != proxy1);
btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
if (aabbOverlap(p0,p1))
if ( !findPair(proxy0,proxy1))
{
if ( !m_pairCache->findPair(proxy0,proxy1))
{
m_pairCache->addOverlappingPair(proxy0,proxy1);
}
} else
{
if (!m_pairCache->hasDeferredRemoval())
{
if ( m_pairCache->findPair(proxy0,proxy1))
{
m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher);
}
}
addOverlappingPair(proxy0,proxy1);
}
}
}
if (m_ownsPairCache && 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;
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)
{
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++;
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.quickSort(btBroadphasePairSortPredicate());
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
#endif//CLEAN_INVALID_PAIRS
}
}
CheckOverlapCallback checkOverlap;
processAllOverlappingPairs(&checkOverlap);
}
bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
return aabbOverlap(p0,p1);
}

View File

@@ -24,69 +24,35 @@ struct btSimpleBroadphaseProxy : public btBroadphaseProxy
{
btVector3 m_min;
btVector3 m_max;
int m_nextFree;
// int m_handleId;
btSimpleBroadphaseProxy() {};
btSimpleBroadphaseProxy(const btPoint3& minpt,const btPoint3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,void* multiSapProxy)
:btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy),
btSimpleBroadphaseProxy(const btPoint3& minpt,const btPoint3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask)
:btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask),
m_min(minpt),m_max(maxpt)
{
(void)shapeType;
}
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
///SimpleBroadphase is a brute force aabb culling broadphase based on O(n^2) aabb checks
class btSimpleBroadphase : public btOverlappingPairCache
{
protected:
int m_numHandles; // number of active handles
int m_maxHandles; // max number of handles
btSimpleBroadphaseProxy* m_proxies;
int* m_freeProxies;
int m_firstFreeProxy;
btSimpleBroadphaseProxy** m_pProxies;
int m_numProxies;
btSimpleBroadphaseProxy* m_pHandles; // handles pool
void* m_pHandlesRawPtr;
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++;
return freeHandle;
}
void freeHandle(btSimpleBroadphaseProxy* proxy)
{
int handle = int(proxy-m_pHandles);
btAssert(handle >= 0 && handle < m_maxHandles);
proxy->SetNextFree(m_firstFreeHandle);
m_firstFreeHandle = handle;
m_numHandles--;
}
btOverlappingPairCache* m_pairCache;
bool m_ownsPairCache;
int m_invalidPair;
int m_maxProxies;
inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy)
@@ -101,48 +67,26 @@ protected:
protected:
virtual void refreshOverlappingPairs();
public:
btSimpleBroadphase(int maxProxies=16384,btOverlappingPairCache* overlappingPairCache=0);
btSimpleBroadphase(int maxProxies=16384);
virtual ~btSimpleBroadphase();
static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1);
virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy);
virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask);
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 destroyProxy(btBroadphaseProxy* proxy);
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax);
btOverlappingPairCache* getOverlappingPairCache()
{
return m_pairCache;
}
const btOverlappingPairCache* getOverlappingPairCache() const
{
return m_pairCache;
}
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
{
aabbMin.setValue(-1e30f,-1e30f,-1e30f);
aabbMax.setValue(1e30f,1e30f,1e30f);
}
virtual void printStats()
{
// printf("btSimpleBroadphase.h\n");
// printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
}
};

View File

@@ -5,149 +5,56 @@ ${BULLET_PHYSICS_SOURCE_DIR}/src }
ADD_LIBRARY(LibBulletCollision
BroadphaseCollision/btAxisSweep3.cpp
BroadphaseCollision/btAxisSweep3.h
BroadphaseCollision/btBroadphaseProxy.cpp
BroadphaseCollision/btBroadphaseProxy.h
BroadphaseCollision/btCollisionAlgorithm.cpp
BroadphaseCollision/btCollisionAlgorithm.h
BroadphaseCollision/btDispatcher.cpp
BroadphaseCollision/btDispatcher.h
BroadphaseCollision/btDbvtBroadphase.cpp
BroadphaseCollision/btDbvtBroadphase.h
BroadphaseCollision/btDbvt.cpp
BroadphaseCollision/btDbvt.h
BroadphaseCollision/btMultiSapBroadphase.cpp
BroadphaseCollision/btMultiSapBroadphase.h
BroadphaseCollision/btOverlappingPairCache.cpp
BroadphaseCollision/btOverlappingPairCache.h
BroadphaseCollision/btOverlappingPairCallback.h
BroadphaseCollision/btQuantizedBvh.cpp
BroadphaseCollision/btQuantizedBvh.h
BroadphaseCollision/btSimpleBroadphase.cpp
BroadphaseCollision/btSimpleBroadphase.h
CollisionDispatch/btCollisionDispatcher.cpp
CollisionDispatch/btCollisionDispatcher.h
CollisionDispatch/btCollisionObject.cpp
CollisionDispatch/btCollisionObject.h
CollisionDispatch/btCollisionWorld.cpp
CollisionDispatch/btCollisionWorld.h
CollisionDispatch/btCompoundCollisionAlgorithm.cpp
CollisionDispatch/btCompoundCollisionAlgorithm.h
CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
CollisionDispatch/btDefaultCollisionConfiguration.cpp
CollisionDispatch/btDefaultCollisionConfiguration.h
CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
CollisionDispatch/btSphereSphereCollisionAlgorithm.h
CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
CollisionDispatch/btBoxBoxCollisionAlgorithm.h
CollisionDispatch/btBoxBoxDetector.cpp
CollisionDispatch/btBoxBoxDetector.h
CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
CollisionDispatch/btSphereBoxCollisionAlgorithm.h
CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
CollisionDispatch/btConvexConvexAlgorithm.cpp
CollisionDispatch/btConvexConvexAlgorithm.h
CollisionDispatch/btEmptyCollisionAlgorithm.cpp
CollisionDispatch/btEmptyCollisionAlgorithm.h
CollisionDispatch/btManifoldResult.cpp
CollisionDispatch/btManifoldResult.h
CollisionDispatch/btSimulationIslandManager.cpp
CollisionDispatch/btSimulationIslandManager.h
CollisionDispatch/btUnionFind.cpp
CollisionDispatch/btUnionFind.h
CollisionDispatch/SphereTriangleDetector.cpp
CollisionDispatch/SphereTriangleDetector.h
CollisionShapes/btBoxShape.cpp
CollisionShapes/btBoxShape.h
CollisionShapes/btBvhTriangleMeshShape.cpp
CollisionShapes/btBvhTriangleMeshShape.h
CollisionShapes/btCapsuleShape.cpp
CollisionShapes/btCapsuleShape.h
CollisionShapes/btCollisionShape.cpp
CollisionShapes/btCollisionShape.h
CollisionShapes/btCompoundShape.cpp
CollisionShapes/btCompoundShape.h
CollisionShapes/btConcaveShape.cpp
CollisionShapes/btConcaveShape.h
CollisionShapes/btConeShape.cpp
CollisionShapes/btConeShape.h
CollisionShapes/btConvexHullShape.cpp
CollisionShapes/btConvexHullShape.h
CollisionShapes/btConvexShape.cpp
CollisionShapes/btConvexShape.h
CollisionShapes/btConvexInternalShape.cpp
CollisionShapes/btConvexInternalShape.h
CollisionShapes/btConvexTriangleMeshShape.cpp
CollisionShapes/btConvexTriangleMeshShape.h
CollisionShapes/btCylinderShape.cpp
CollisionShapes/btCylinderShape.h
CollisionShapes/btEmptyShape.cpp
CollisionShapes/btEmptyShape.h
CollisionShapes/btHeightfieldTerrainShape.cpp
CollisionShapes/btHeightfieldTerrainShape.h
CollisionShapes/btMinkowskiSumShape.cpp
CollisionShapes/btMinkowskiSumShape.h
CollisionShapes/btMaterial.h
CollisionShapes/btMultimaterialTriangleMeshShape.cpp
CollisionShapes/btMultimaterialTriangleMeshShape.h
CollisionShapes/btMultiSphereShape.cpp
CollisionShapes/btMultiSphereShape.h
CollisionShapes/btOptimizedBvh.cpp
CollisionShapes/btOptimizedBvh.h
CollisionShapes/btPolyhedralConvexShape.cpp
CollisionShapes/btPolyhedralConvexShape.h
CollisionShapes/btScaledBvhTriangleMeshShape.cpp
CollisionShapes/btScaledBvhTriangleMeshShape.h
CollisionShapes/btTetrahedronShape.cpp
CollisionShapes/btTetrahedronShape.h
CollisionShapes/btSphereShape.cpp
CollisionShapes/btSphereShape.h
CollisionShapes/btShapeHull.h
CollisionShapes/btShapeHull.cpp
CollisionShapes/btStaticPlaneShape.cpp
CollisionShapes/btStaticPlaneShape.h
CollisionShapes/btStridingMeshInterface.cpp
CollisionShapes/btStridingMeshInterface.h
CollisionShapes/btTriangleCallback.cpp
CollisionShapes/btTriangleCallback.h
CollisionShapes/btTriangleBuffer.cpp
CollisionShapes/btTriangleBuffer.h
CollisionShapes/btTriangleIndexVertexArray.cpp
CollisionShapes/btTriangleIndexVertexArray.h
CollisionShapes/btTriangleIndexVertexMaterialArray.h
CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
CollisionShapes/btTriangleMesh.cpp
CollisionShapes/btTriangleMesh.h
CollisionShapes/btTriangleMeshShape.cpp
CollisionShapes/btTriangleMeshShape.h
CollisionShapes/btUniformScalingShape.cpp
CollisionShapes/btUniformScalingShape.h
NarrowPhaseCollision/btContinuousConvexCollision.cpp
NarrowPhaseCollision/btContinuousConvexCollision.h
NarrowPhaseCollision/btGjkEpa.cpp
NarrowPhaseCollision/btGjkEpa.h
NarrowPhaseCollision/btGjkEpa2.cpp
NarrowPhaseCollision/btGjkEpa2.h
NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h
NarrowPhaseCollision/btConvexCast.cpp
NarrowPhaseCollision/btConvexCast.h
NarrowPhaseCollision/btGjkConvexCast.cpp
NarrowPhaseCollision/btGjkConvexCast.h
NarrowPhaseCollision/btGjkPairDetector.cpp
NarrowPhaseCollision/btGjkPairDetector.h
NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h
NarrowPhaseCollision/btPersistentManifold.cpp
NarrowPhaseCollision/btPersistentManifold.h
NarrowPhaseCollision/btRaycastCallback.cpp
NarrowPhaseCollision/btRaycastCallback.h
NarrowPhaseCollision/btSubSimplexConvexCast.cpp
NarrowPhaseCollision/btSubSimplexConvexCast.h
NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
NarrowPhaseCollision/btVoronoiSimplexSolver.h
)

View File

@@ -26,7 +26,7 @@ m_triangle(triangle)
}
void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults)
void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw)
{
(void)debugDraw;
@@ -42,16 +42,7 @@ void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Res
if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact))
{
if (swapResults)
{
btVector3 normalOnB = transformB.getBasis()*normal;
btVector3 normalOnA = -normalOnB;
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);
}
}
@@ -62,8 +53,6 @@ void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Res
// 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) {
btVector3 diff = p - from;
btVector3 v = to - from;

View File

@@ -16,8 +16,8 @@ subject to the following restrictions:
#ifndef SPHERE_TRIANGLE_DETECTOR_H
#define SPHERE_TRIANGLE_DETECTOR_H
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
#include "LinearMath/btPoint3.h"
#include "../NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
#include "../../LinearMath/btPoint3.h"
class btSphereShape;
@@ -28,7 +28,7 @@ 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);
SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle);

View File

@@ -1,85 +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 "btBoxBoxCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "btBoxBoxDetector.h"
#define USE_PERSISTENT_CONTACTS 1
btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1)
: btCollisionAlgorithm(ci),
m_ownManifold(false),
m_manifoldPtr(mf)
{
if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1))
{
m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1);
m_ownManifold = true;
}
}
btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm()
{
if (m_ownManifold)
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}
}
void btBoxBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
return;
btCollisionObject* col0 = body0;
btCollisionObject* col1 = body1;
btBoxShape* box0 = (btBoxShape*)col0->getCollisionShape();
btBoxShape* box1 = (btBoxShape*)col1->getCollisionShape();
/// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->setPersistentManifold(m_manifoldPtr);
#ifndef USE_PERSISTENT_CONTACTS
m_manifoldPtr->clearManifold();
#endif //USE_PERSISTENT_CONTACTS
btDiscreteCollisionDetectorInterface::ClosestPointInput input;
input.m_maximumDistanceSquared = 1e30f;
input.m_transformA = body0->getWorldTransform();
input.m_transformB = body1->getWorldTransform();
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
if (m_ownManifold)
{
resultOut->refreshContactPoints();
}
#endif //USE_PERSISTENT_CONTACTS
}
btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
{
//not yet
return 1.f;
}

View File

@@ -1,66 +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 BOX_BOX__COLLISION_ALGORITHM_H
#define BOX_BOX__COLLISION_ALGORITHM_H
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
class btPersistentManifold;
///box-box collision detection
class btBoxBoxCollisionAlgorithm : public btCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
public:
btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btCollisionAlgorithm(ci) {}
virtual void processCollision (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,btCollisionObject* body0,btCollisionObject* body1);
virtual ~btBoxBoxCollisionAlgorithm();
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
int bbsize = sizeof(btBoxBoxCollisionAlgorithm);
void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0,body1);
}
};
};
#endif //BOX_BOX__COLLISION_ALGORITHM_H

View File

@@ -1,683 +0,0 @@
/*
* Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
* Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
* All rights reserved. Email: russ@q12.org Web: www.q12.org
Bullet Continuous Collision Detection and Physics Library
Bullet is 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.
*/
///ODE box-box collision detection is adapted to work with Bullet
#include "btBoxBoxDetector.h"
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include <float.h>
#include <string.h>
btBoxBoxDetector::btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2)
: m_box1(box1),
m_box2(box2)
{
}
// given two boxes (p1,R1,side1) and (p2,R2,side2), collide them together and
// generate contact points. this returns 0 if there is no contact otherwise
// it returns the number of contacts generated.
// `normal' returns the contact normal.
// `depth' returns the maximum penetration depth along that normal.
// `return_code' returns a number indicating the type of contact that was
// detected:
// 1,2,3 = box 2 intersects with a face of box 1
// 4,5,6 = box 1 intersects with a face of box 2
// 7..15 = edge-edge contact
// `maxc' is the maximum number of contacts allowed to be generated, i.e.
// the size of the `contact' array.
// `contact' and `skip' are the contact array information provided to the
// collision functions. this function only fills in the position and depth
// fields.
struct dContactGeom;
#define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)])
#define dInfinity FLT_MAX
/*PURE_INLINE btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
PURE_INLINE btScalar dDOT13 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,3); }
PURE_INLINE btScalar dDOT31 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,1); }
PURE_INLINE btScalar dDOT33 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,3); }
*/
static btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
static btScalar dDOT44 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,4); }
static btScalar dDOT41 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,1); }
static btScalar dDOT14 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,4); }
#define dMULTIPLYOP1_331(A,op,B,C) \
{\
(A)[0] op dDOT41((B),(C)); \
(A)[1] op dDOT41((B+1),(C)); \
(A)[2] op dDOT41((B+2),(C)); \
}
#define dMULTIPLYOP0_331(A,op,B,C) \
{ \
(A)[0] op dDOT((B),(C)); \
(A)[1] op dDOT((B+4),(C)); \
(A)[2] op dDOT((B+8),(C)); \
}
#define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C)
#define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C)
typedef btScalar dMatrix3[4*3];
void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
const btVector3& pb, const btVector3& ub,
btScalar *alpha, btScalar *beta);
void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
const btVector3& pb, const btVector3& ub,
btScalar *alpha, btScalar *beta)
{
btVector3 p;
p[0] = pb[0] - pa[0];
p[1] = pb[1] - pa[1];
p[2] = pb[2] - pa[2];
btScalar uaub = dDOT(ua,ub);
btScalar q1 = dDOT(ua,p);
btScalar q2 = -dDOT(ub,p);
btScalar d = 1-uaub*uaub;
if (d <= btScalar(0.0001f)) {
// @@@ this needs to be made more robust
*alpha = 0;
*beta = 0;
}
else {
d = 1.f/d;
*alpha = (q1 + uaub*q2)*d;
*beta = (uaub*q1 + q2)*d;
}
}
// find all the intersection points between the 2D rectangle with vertices
// at (+/-h[0],+/-h[1]) and the 2D quadrilateral with vertices (p[0],p[1]),
// (p[2],p[3]),(p[4],p[5]),(p[6],p[7]).
//
// the intersection points are returned as x,y pairs in the 'ret' array.
// the number of intersection points is returned by the function (this will
// be in the range 0 to 8).
static int intersectRectQuad2 (btScalar h[2], btScalar p[8], btScalar ret[16])
{
// q (and r) contain nq (and nr) coordinate points for the current (and
// chopped) polygons
int nq=4,nr=0;
btScalar buffer[16];
btScalar *q = p;
btScalar *r = ret;
for (int dir=0; dir <= 1; dir++) {
// direction notation: xy[0] = x axis, xy[1] = y axis
for (int sign=-1; sign <= 1; sign += 2) {
// chop q along the line xy[dir] = sign*h[dir]
btScalar *pq = q;
btScalar *pr = r;
nr = 0;
for (int i=nq; i > 0; i--) {
// go through all points in q and all lines between adjacent points
if (sign*pq[dir] < h[dir]) {
// this point is inside the chopping line
pr[0] = pq[0];
pr[1] = pq[1];
pr += 2;
nr++;
if (nr & 8) {
q = r;
goto done;
}
}
btScalar *nextq = (i > 1) ? pq+2 : q;
if ((sign*pq[dir] < h[dir]) ^ (sign*nextq[dir] < h[dir])) {
// this line crosses the chopping line
pr[1-dir] = pq[1-dir] + (nextq[1-dir]-pq[1-dir]) /
(nextq[dir]-pq[dir]) * (sign*h[dir]-pq[dir]);
pr[dir] = sign*h[dir];
pr += 2;
nr++;
if (nr & 8) {
q = r;
goto done;
}
}
pq += 2;
}
q = r;
r = (q==ret) ? buffer : ret;
nq = nr;
}
}
done:
if (q != ret) memcpy (ret,q,nr*2*sizeof(btScalar));
return nr;
}
#define M__PI 3.14159265f
// given n points in the plane (array p, of size 2*n), generate m points that
// best represent the whole set. the definition of 'best' here is not
// predetermined - the idea is to select points that give good box-box
// collision detection behavior. the chosen point indexes are returned in the
// array iret (of size m). 'i0' is always the first entry in the array.
// n must be in the range [1..8]. m must be in the range [1..n]. i0 must be
// in the range [0..n-1].
void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]);
void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[])
{
// compute the centroid of the polygon in cx,cy
int i,j;
btScalar a,cx,cy,q;
if (n==1) {
cx = p[0];
cy = p[1];
}
else if (n==2) {
cx = btScalar(0.5)*(p[0] + p[2]);
cy = btScalar(0.5)*(p[1] + p[3]);
}
else {
a = 0;
cx = 0;
cy = 0;
for (i=0; i<(n-1); i++) {
q = p[i*2]*p[i*2+3] - p[i*2+2]*p[i*2+1];
a += q;
cx += q*(p[i*2]+p[i*2+2]);
cy += q*(p[i*2+1]+p[i*2+3]);
}
q = p[n*2-2]*p[1] - p[0]*p[n*2-1];
a = 1.f/(btScalar(3.0)*(a+q));
cx = a*(cx + q*(p[n*2-2]+p[0]));
cy = a*(cy + q*(p[n*2-1]+p[1]));
}
// compute the angle of each point w.r.t. the centroid
btScalar A[8];
for (i=0; i<n; i++) A[i] = btAtan2(p[i*2+1]-cy,p[i*2]-cx);
// search for points that have angles closest to A[i0] + i*(2*pi/m).
int avail[8];
for (i=0; i<n; i++) avail[i] = 1;
avail[i0] = 0;
iret[0] = i0;
iret++;
for (j=1; j<m; j++) {
a = btScalar(j)*(2*M__PI/m) + A[i0];
if (a > M__PI) a -= 2*M__PI;
btScalar maxdiff=1e9,diff;
#if defined(DEBUG) || defined (_DEBUG)
*iret = i0; // iret is not allowed to keep this value
#endif
for (i=0; i<n; i++) {
if (avail[i]) {
diff = btFabs (A[i]-a);
if (diff > M__PI) diff = 2*M__PI - diff;
if (diff < maxdiff) {
maxdiff = diff;
*iret = i;
}
}
}
#if defined(DEBUG) || defined (_DEBUG)
btAssert (*iret != i0); // ensure iret got set
#endif
avail[*iret] = 0;
iret++;
}
}
int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
const btVector3& side1, const btVector3& p2,
const dMatrix3 R2, const btVector3& side2,
btVector3& normal, btScalar *depth, int *return_code,
int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output);
int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
const btVector3& side1, const btVector3& p2,
const dMatrix3 R2, const btVector3& side2,
btVector3& normal, btScalar *depth, int *return_code,
int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output)
{
const btScalar fudge_factor = btScalar(1.05);
btVector3 p,pp,normalC;
const btScalar *normalR = 0;
btScalar A[3],B[3],R11,R12,R13,R21,R22,R23,R31,R32,R33,
Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33,s,s2,l;
int i,j,invert_normal,code;
// get vector from centers of box 1 to box 2, relative to box 1
p = p2 - p1;
dMULTIPLY1_331 (pp,R1,p); // get pp = p relative to body 1
// get side lengths / 2
A[0] = side1[0]*btScalar(0.5);
A[1] = side1[1]*btScalar(0.5);
A[2] = side1[2]*btScalar(0.5);
B[0] = side2[0]*btScalar(0.5);
B[1] = side2[1]*btScalar(0.5);
B[2] = side2[2]*btScalar(0.5);
// Rij is R1'*R2, i.e. the relative rotation between R1 and R2
R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2);
R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2);
R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2);
Q11 = btFabs(R11); Q12 = btFabs(R12); Q13 = btFabs(R13);
Q21 = btFabs(R21); Q22 = btFabs(R22); Q23 = btFabs(R23);
Q31 = btFabs(R31); Q32 = btFabs(R32); Q33 = btFabs(R33);
// for all 15 possible separating axes:
// * see if the axis separates the boxes. if so, return 0.
// * find the depth of the penetration along the separating axis (s2)
// * if this is the largest depth so far, record it.
// the normal vector will be set to the separating axis with the smallest
// depth. note: normalR is set to point to a column of R1 or R2 if that is
// the smallest depth normal so far. otherwise normalR is 0 and normalC is
// set to a vector relative to body 1. invert_normal is 1 if the sign of
// the normal should be flipped.
#define TST(expr1,expr2,norm,cc) \
s2 = btFabs(expr1) - (expr2); \
if (s2 > 0) return 0; \
if (s2 > s) { \
s = s2; \
normalR = norm; \
invert_normal = ((expr1) < 0); \
code = (cc); \
}
s = -dInfinity;
invert_normal = 0;
code = 0;
// separating axis = u1,u2,u3
TST (pp[0],(A[0] + B[0]*Q11 + B[1]*Q12 + B[2]*Q13),R1+0,1);
TST (pp[1],(A[1] + B[0]*Q21 + B[1]*Q22 + B[2]*Q23),R1+1,2);
TST (pp[2],(A[2] + B[0]*Q31 + B[1]*Q32 + B[2]*Q33),R1+2,3);
// separating axis = v1,v2,v3
TST (dDOT41(R2+0,p),(A[0]*Q11 + A[1]*Q21 + A[2]*Q31 + B[0]),R2+0,4);
TST (dDOT41(R2+1,p),(A[0]*Q12 + A[1]*Q22 + A[2]*Q32 + B[1]),R2+1,5);
TST (dDOT41(R2+2,p),(A[0]*Q13 + A[1]*Q23 + A[2]*Q33 + B[2]),R2+2,6);
// note: cross product axes need to be scaled when s is computed.
// normal (n1,n2,n3) is relative to box 1.
#undef TST
#define TST(expr1,expr2,n1,n2,n3,cc) \
s2 = btFabs(expr1) - (expr2); \
if (s2 > 0) return 0; \
l = btSqrt((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \
if (l > 0) { \
s2 /= l; \
if (s2*fudge_factor > s) { \
s = s2; \
normalR = 0; \
normalC[0] = (n1)/l; normalC[1] = (n2)/l; normalC[2] = (n3)/l; \
invert_normal = ((expr1) < 0); \
code = (cc); \
} \
}
// separating axis = u1 x (v1,v2,v3)
TST(pp[2]*R21-pp[1]*R31,(A[1]*Q31+A[2]*Q21+B[1]*Q13+B[2]*Q12),0,-R31,R21,7);
TST(pp[2]*R22-pp[1]*R32,(A[1]*Q32+A[2]*Q22+B[0]*Q13+B[2]*Q11),0,-R32,R22,8);
TST(pp[2]*R23-pp[1]*R33,(A[1]*Q33+A[2]*Q23+B[0]*Q12+B[1]*Q11),0,-R33,R23,9);
// separating axis = u2 x (v1,v2,v3)
TST(pp[0]*R31-pp[2]*R11,(A[0]*Q31+A[2]*Q11+B[1]*Q23+B[2]*Q22),R31,0,-R11,10);
TST(pp[0]*R32-pp[2]*R12,(A[0]*Q32+A[2]*Q12+B[0]*Q23+B[2]*Q21),R32,0,-R12,11);
TST(pp[0]*R33-pp[2]*R13,(A[0]*Q33+A[2]*Q13+B[0]*Q22+B[1]*Q21),R33,0,-R13,12);
// separating axis = u3 x (v1,v2,v3)
TST(pp[1]*R11-pp[0]*R21,(A[0]*Q21+A[1]*Q11+B[1]*Q33+B[2]*Q32),-R21,R11,0,13);
TST(pp[1]*R12-pp[0]*R22,(A[0]*Q22+A[1]*Q12+B[0]*Q33+B[2]*Q31),-R22,R12,0,14);
TST(pp[1]*R13-pp[0]*R23,(A[0]*Q23+A[1]*Q13+B[0]*Q32+B[1]*Q31),-R23,R13,0,15);
#undef TST
if (!code) return 0;
// if we get to this point, the boxes interpenetrate. compute the normal
// in global coordinates.
if (normalR) {
normal[0] = normalR[0];
normal[1] = normalR[4];
normal[2] = normalR[8];
}
else {
dMULTIPLY0_331 (normal,R1,normalC);
}
if (invert_normal) {
normal[0] = -normal[0];
normal[1] = -normal[1];
normal[2] = -normal[2];
}
*depth = -s;
// compute contact point(s)
if (code > 6) {
// an edge from box 1 touches an edge from box 2.
// find a point pa on the intersecting edge of box 1
btVector3 pa;
btScalar sign;
for (i=0; i<3; i++) pa[i] = p1[i];
for (j=0; j<3; j++) {
sign = (dDOT14(normal,R1+j) > 0) ? btScalar(1.0) : btScalar(-1.0);
for (i=0; i<3; i++) pa[i] += sign * A[j] * R1[i*4+j];
}
// find a point pb on the intersecting edge of box 2
btVector3 pb;
for (i=0; i<3; i++) pb[i] = p2[i];
for (j=0; j<3; j++) {
sign = (dDOT14(normal,R2+j) > 0) ? btScalar(-1.0) : btScalar(1.0);
for (i=0; i<3; i++) pb[i] += sign * B[j] * R2[i*4+j];
}
btScalar alpha,beta;
btVector3 ua,ub;
for (i=0; i<3; i++) ua[i] = R1[((code)-7)/3 + i*4];
for (i=0; i<3; i++) ub[i] = R2[((code)-7)%3 + i*4];
dLineClosestApproach (pa,ua,pb,ub,&alpha,&beta);
for (i=0; i<3; i++) pa[i] += ua[i]*alpha;
for (i=0; i<3; i++) pb[i] += ub[i]*beta;
{
//contact[0].pos[i] = btScalar(0.5)*(pa[i]+pb[i]);
//contact[0].depth = *depth;
btVector3 pointInWorld;
#ifdef USE_CENTER_POINT
for (i=0; i<3; i++)
pointInWorld[i] = (pa[i]+pb[i])*btScalar(0.5);
output.addContactPoint(-normal,pointInWorld,-*depth);
#else
output.addContactPoint(-normal,pb,-*depth);
#endif //
*return_code = code;
}
return 1;
}
// okay, we have a face-something intersection (because the separating
// axis is perpendicular to a face). define face 'a' to be the reference
// face (i.e. the normal vector is perpendicular to this) and face 'b' to be
// the incident face (the closest face of the other box).
const btScalar *Ra,*Rb,*pa,*pb,*Sa,*Sb;
if (code <= 3) {
Ra = R1;
Rb = R2;
pa = p1;
pb = p2;
Sa = A;
Sb = B;
}
else {
Ra = R2;
Rb = R1;
pa = p2;
pb = p1;
Sa = B;
Sb = A;
}
// nr = normal vector of reference face dotted with axes of incident box.
// anr = absolute values of nr.
btVector3 normal2,nr,anr;
if (code <= 3) {
normal2[0] = normal[0];
normal2[1] = normal[1];
normal2[2] = normal[2];
}
else {
normal2[0] = -normal[0];
normal2[1] = -normal[1];
normal2[2] = -normal[2];
}
dMULTIPLY1_331 (nr,Rb,normal2);
anr[0] = btFabs (nr[0]);
anr[1] = btFabs (nr[1]);
anr[2] = btFabs (nr[2]);
// find the largest compontent of anr: this corresponds to the normal
// for the indident face. the other axis numbers of the indicent face
// are stored in a1,a2.
int lanr,a1,a2;
if (anr[1] > anr[0]) {
if (anr[1] > anr[2]) {
a1 = 0;
lanr = 1;
a2 = 2;
}
else {
a1 = 0;
a2 = 1;
lanr = 2;
}
}
else {
if (anr[0] > anr[2]) {
lanr = 0;
a1 = 1;
a2 = 2;
}
else {
a1 = 0;
a2 = 1;
lanr = 2;
}
}
// compute center point of incident face, in reference-face coordinates
btVector3 center;
if (nr[lanr] < 0) {
for (i=0; i<3; i++) center[i] = pb[i] - pa[i] + Sb[lanr] * Rb[i*4+lanr];
}
else {
for (i=0; i<3; i++) center[i] = pb[i] - pa[i] - Sb[lanr] * Rb[i*4+lanr];
}
// find the normal and non-normal axis numbers of the reference box
int codeN,code1,code2;
if (code <= 3) codeN = code-1; else codeN = code-4;
if (codeN==0) {
code1 = 1;
code2 = 2;
}
else if (codeN==1) {
code1 = 0;
code2 = 2;
}
else {
code1 = 0;
code2 = 1;
}
// find the four corners of the incident face, in reference-face coordinates
btScalar quad[8]; // 2D coordinate of incident face (x,y pairs)
btScalar c1,c2,m11,m12,m21,m22;
c1 = dDOT14 (center,Ra+code1);
c2 = dDOT14 (center,Ra+code2);
// optimize this? - we have already computed this data above, but it is not
// stored in an easy-to-index format. for now it's quicker just to recompute
// the four dot products.
m11 = dDOT44 (Ra+code1,Rb+a1);
m12 = dDOT44 (Ra+code1,Rb+a2);
m21 = dDOT44 (Ra+code2,Rb+a1);
m22 = dDOT44 (Ra+code2,Rb+a2);
{
btScalar k1 = m11*Sb[a1];
btScalar k2 = m21*Sb[a1];
btScalar k3 = m12*Sb[a2];
btScalar k4 = m22*Sb[a2];
quad[0] = c1 - k1 - k3;
quad[1] = c2 - k2 - k4;
quad[2] = c1 - k1 + k3;
quad[3] = c2 - k2 + k4;
quad[4] = c1 + k1 + k3;
quad[5] = c2 + k2 + k4;
quad[6] = c1 + k1 - k3;
quad[7] = c2 + k2 - k4;
}
// find the size of the reference face
btScalar rect[2];
rect[0] = Sa[code1];
rect[1] = Sa[code2];
// intersect the incident and reference faces
btScalar ret[16];
int n = intersectRectQuad2 (rect,quad,ret);
if (n < 1) return 0; // this should never happen
// convert the intersection points into reference-face coordinates,
// and compute the contact position and depth for each point. only keep
// those points that have a positive (penetrating) depth. delete points in
// the 'ret' array as necessary so that 'point' and 'ret' correspond.
btScalar point[3*8]; // penetrating contact points
btScalar dep[8]; // depths for those points
btScalar det1 = 1.f/(m11*m22 - m12*m21);
m11 *= det1;
m12 *= det1;
m21 *= det1;
m22 *= det1;
int cnum = 0; // number of penetrating contact points found
for (j=0; j < n; j++) {
btScalar k1 = m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2);
btScalar k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2);
for (i=0; i<3; i++) point[cnum*3+i] =
center[i] + k1*Rb[i*4+a1] + k2*Rb[i*4+a2];
dep[cnum] = Sa[codeN] - dDOT(normal2,point+cnum*3);
if (dep[cnum] >= 0) {
ret[cnum*2] = ret[j*2];
ret[cnum*2+1] = ret[j*2+1];
cnum++;
}
}
if (cnum < 1) return 0; // this should never happen
// we can't generate more contacts than we actually have
if (maxc > cnum) maxc = cnum;
if (maxc < 1) maxc = 1;
if (cnum <= maxc) {
// we have less contacts than we need, so we use them all
for (j=0; j < cnum; j++) {
//AddContactPoint...
//dContactGeom *con = CONTACT(contact,skip*j);
//for (i=0; i<3; i++) con->pos[i] = point[j*3+i] + pa[i];
//con->depth = dep[j];
btVector3 pointInWorld;
for (i=0; i<3; i++)
pointInWorld[i] = point[j*3+i] + pa[i];
output.addContactPoint(-normal,pointInWorld,-dep[j]);
}
}
else {
// we have more contacts than are wanted, some of them must be culled.
// find the deepest point, it is always the first contact.
int i1 = 0;
btScalar maxdepth = dep[0];
for (i=1; i<cnum; i++) {
if (dep[i] > maxdepth) {
maxdepth = dep[i];
i1 = i;
}
}
int iret[8];
cullPoints2 (cnum,ret,maxc,i1,iret);
for (j=0; j < maxc; j++) {
// dContactGeom *con = CONTACT(contact,skip*j);
// for (i=0; i<3; i++) con->pos[i] = point[iret[j]*3+i] + pa[i];
// con->depth = dep[iret[j]];
btVector3 posInWorld;
for (i=0; i<3; i++)
posInWorld[i] = point[iret[j]*3+i] + pa[i];
output.addContactPoint(-normal,posInWorld,-dep[iret[j]]);
}
cnum = maxc;
}
*return_code = code;
return cnum;
}
void btBoxBoxDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* /*debugDraw*/,bool /*swapResults*/)
{
const btTransform& transformA = input.m_transformA;
const btTransform& transformB = input.m_transformB;
int skip = 0;
dContactGeom *contact = 0;
dMatrix3 R1;
dMatrix3 R2;
for (int j=0;j<3;j++)
{
R1[0+4*j] = transformA.getBasis()[j].x();
R2[0+4*j] = transformB.getBasis()[j].x();
R1[1+4*j] = transformA.getBasis()[j].y();
R2[1+4*j] = transformB.getBasis()[j].y();
R1[2+4*j] = transformA.getBasis()[j].z();
R2[2+4*j] = transformB.getBasis()[j].z();
}
btVector3 normal;
btScalar depth;
int return_code;
int maxc = 4;
dBoxBox2 (transformA.getOrigin(),
R1,
2.f*m_box1->getHalfExtentsWithMargin(),
transformB.getOrigin(),
R2,
2.f*m_box2->getHalfExtentsWithMargin(),
normal, &depth, &return_code,
maxc, contact, skip,
output
);
}

View File

@@ -1,44 +0,0 @@
/*
* Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
* Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
* All rights reserved. Email: russ@q12.org Web: www.q12.org
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 BOX_BOX_DETECTOR_H
#define 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
{
btBoxShape* m_box1;
btBoxShape* m_box2;
public:
btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2);
virtual ~btBoxBoxDetector() {};
virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
};
#endif //BT_BOX_BOX_DETECTOR_H

View File

@@ -1,47 +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_CONFIGURATION
#define BT_COLLISION_CONFIGURATION
struct btCollisionAlgorithmCreateFunc;
class btStackAlloc;
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
{
public:
virtual ~btCollisionConfiguration()
{
}
///memory pools
virtual btPoolAllocator* getPersistentManifoldPool() = 0;
virtual btPoolAllocator* getCollisionAlgorithmPool() = 0;
virtual btStackAlloc* getStackAllocator() = 0;
virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0;
};
#endif //BT_COLLISION_CONFIGURATION

View File

@@ -16,7 +16,7 @@ subject to the following restrictions:
#ifndef COLLISION_CREATE_FUNC
#define COLLISION_CREATE_FUNC
#include "LinearMath/btAlignedObjectArray.h"
#include "../../LinearMath/btAlignedObjectArray.h"
typedef btAlignedObjectArray<class btCollisionObject*> btCollisionObjectArray;
class btCollisionAlgorithm;
class btCollisionObject;

View File

@@ -19,39 +19,69 @@ subject to the following restrictions:
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.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"
int gNumManifold = 0;
#ifdef BT_DEBUG
#include <stdio.h>
#endif
btCollisionDispatcher::btCollisionDispatcher(bool noDefaultAlgorithms):
m_count(0),
m_useIslands(true),
m_convexConvexCreateFunc(0),
m_convexConcaveCreateFunc(0),
m_swappedConvexConcaveCreateFunc(0),
m_compoundCreateFunc(0),
m_swappedCompoundCreateFunc(0),
m_emptyCreateFunc(0)
{
(void)noDefaultAlgorithms;
int i;
btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration):
setNearCallback(defaultNearCallback);
m_emptyCreateFunc = new btEmptyAlgorithm::CreateFunc;
for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
{
for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
{
m_doubleDispatch[i][j] = m_emptyCreateFunc;
}
}
}
//if you want to not link with the default collision algorithms, you can
//define BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION
//in your Bullet library build system
#ifndef BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION
btCollisionDispatcher::btCollisionDispatcher ():
m_count(0),
m_useIslands(true),
m_staticWarningReported(false),
m_collisionConfiguration(collisionConfiguration)
m_useIslands(true)
{
int i;
setNearCallback(defaultNearCallback);
m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool();
m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool();
//default CreationFunctions, filling the m_doubleDispatch table
m_convexConvexCreateFunc = new btConvexConvexAlgorithm::CreateFunc;
m_convexConcaveCreateFunc = new btConvexConcaveCollisionAlgorithm::CreateFunc;
m_swappedConvexConcaveCreateFunc = new btConvexConcaveCollisionAlgorithm::SwappedCreateFunc;
m_compoundCreateFunc = new btCompoundCollisionAlgorithm::CreateFunc;
m_swappedCompoundCreateFunc = new btCompoundCollisionAlgorithm::SwappedCreateFunc;
m_emptyCreateFunc = new btEmptyAlgorithm::CreateFunc;
for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
{
for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
{
m_doubleDispatch[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i,j);
m_doubleDispatch[i][j] = internalFindCreateFunc(i,j);
assert(m_doubleDispatch[i][j]);
}
}
@@ -59,6 +89,8 @@ btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisio
};
#endif //BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION
void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
{
@@ -67,6 +99,12 @@ void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int prox
btCollisionDispatcher::~btCollisionDispatcher()
{
delete m_convexConvexCreateFunc;
delete m_convexConcaveCreateFunc;
delete m_swappedConvexConcaveCreateFunc;
delete m_compoundCreateFunc;
delete m_swappedCompoundCreateFunc;
delete m_emptyCreateFunc;
}
btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1)
@@ -79,18 +117,7 @@ btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1)
btCollisionObject* body0 = (btCollisionObject*)b0;
btCollisionObject* body1 = (btCollisionObject*)b1;
void* mem = 0;
if (m_persistentManifoldPoolAllocator->getFreeCount())
{
mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
} else
{
mem = btAlignedAlloc(sizeof(btPersistentManifold),16);
}
btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0);
manifold->m_index1a = m_manifoldsPtr.size();
btPersistentManifold* manifold = new btPersistentManifold (body0,body1);
m_manifoldsPtr.push_back(manifold);
return manifold;
@@ -110,19 +137,13 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
//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[findIndex]->m_index1a = findIndex;
m_manifoldsPtr.pop_back();
manifold->~btPersistentManifold();
if (m_persistentManifoldPoolAllocator->validPtr(manifold))
///todo: this can be improved a lot, linear search might be slow part!
int findIndex = m_manifoldsPtr.findLinearSearch(manifold);
if (findIndex < m_manifoldsPtr.size())
{
m_persistentManifoldPoolAllocator->freeMemory(manifold);
} else
{
btAlignedFree(manifold);
m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1);
m_manifoldsPtr.pop_back();
delete manifold;
}
}
@@ -131,19 +152,99 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold)
{
#ifdef USE_DISPATCH_REGISTRY_ARRAY
btCollisionAlgorithmConstructionInfo ci;
ci.m_dispatcher1 = this;
ci.m_dispatcher = this;
ci.m_manifold = sharedManifold;
btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1);
btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]
->CreateCollisionAlgorithm(ci,body0,body1);
#else
btCollisionAlgorithm* algo = internalFindAlgorithm(body0,body1);
#endif //USE_DISPATCH_REGISTRY_ARRAY
return algo;
}
#ifndef BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION
btCollisionAlgorithmCreateFunc* btCollisionDispatcher::internalFindCreateFunc(int proxyType0,int proxyType1)
{
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))
{
return m_compoundCreateFunc;
} else
{
if (btBroadphaseProxy::isCompound(proxyType1))
{
return m_swappedCompoundCreateFunc;
}
}
//failed to find an algorithm
return m_emptyCreateFunc;
}
#endif //BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION
#ifndef USE_DISPATCH_REGISTRY_ARRAY
btCollisionAlgorithm* btCollisionDispatcher::internalFindAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold)
{
m_count++;
btCollisionAlgorithmConstructionInfo ci;
ci.m_dispatcher = this;
if (body0->getCollisionShape()->isConvex() && body1->getCollisionShape()->isConvex() )
{
return new btConvexConvexAlgorithm(sharedManifold,ci,body0,body1);
}
if (body0->getCollisionShape()->isConvex() && body1->getCollisionShape()->isConcave())
{
return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,false);
}
if (body1->getCollisionShape()->isConvex() && body0->getCollisionShape()->isConcave())
{
return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,true);
}
if (body0->getCollisionShape()->isCompound())
{
return new btCompoundCollisionAlgorithm(ci,body0,body1,false);
} else
{
if (body1->getCollisionShape()->isCompound())
{
return new btCompoundCollisionAlgorithm(ci,body0,body1,true);
}
}
//failed to find an algorithm
return new btEmptyAlgorithm(ci);
}
#endif //USE_DISPATCH_REGISTRY_ARRAY
bool btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1)
{
@@ -163,19 +264,13 @@ bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionO
bool needsCollision = true;
#ifdef BT_DEBUG
if (!m_staticWarningReported)
//broadphase filtering already deals with this
if ((body0->isStaticObject() || body0->isKinematicObject()) &&
(body1->isStaticObject() || body1->isKinematicObject()))
{
//broadphase filtering already deals with this
if ((body0->isStaticObject() || body0->isKinematicObject()) &&
(body1->isStaticObject() || body1->isKinematicObject()))
{
m_staticWarningReported = true;
printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
}
printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
}
#endif //BT_DEBUG
if ((!body0->isActive()) && (!body1->isActive()))
needsCollision = false;
else if (!body0->checkCollideWith(body1))
@@ -191,25 +286,23 @@ bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionO
///this is useful for the collision dispatcher.
class btCollisionPairCallback : public btOverlapCallback
{
const btDispatcherInfo& m_dispatchInfo;
btDispatcherInfo& m_dispatchInfo;
btCollisionDispatcher* m_dispatcher;
public:
btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher)
btCollisionPairCallback(btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher)
:m_dispatchInfo(dispatchInfo),
m_dispatcher(dispatcher)
{
}
/*btCollisionPairCallback& operator=(btCollisionPairCallback& other)
btCollisionPairCallback& operator=(btCollisionPairCallback& other)
{
m_dispatchInfo = other.m_dispatchInfo;
m_dispatcher = other.m_dispatcher;
return *this;
}
*/
virtual ~btCollisionPairCallback() {}
@@ -223,14 +316,13 @@ public:
};
void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)
void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo)
{
//m_blockedForChanges = true;
btCollisionPairCallback collisionCallback(dispatchInfo,this);
pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
pairCache->processAllOverlappingPairs(&collisionCallback);
//m_blockedForChanges = false;
@@ -240,7 +332,7 @@ void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pa
//by default, Bullet will use this near callback
void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo)
{
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
@@ -273,26 +365,3 @@ void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair,
}
}
void* btCollisionDispatcher::allocateCollisionAlgorithm(int size)
{
if (m_collisionAlgorithmPoolAllocator->getFreeCount())
{
return m_collisionAlgorithmPoolAllocator->allocate(size);
}
//warn user for overflow?
return btAlignedAlloc(static_cast<size_t>(size), 16);
}
void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
{
if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
{
m_collisionAlgorithmPoolAllocator->freeMemory(ptr);
} else
{
btAlignedFree(ptr);
}
}

View File

@@ -16,18 +16,17 @@ subject to the following restrictions:
#ifndef COLLISION__DISPATCHER_H
#define COLLISION__DISPATCHER_H
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
#include "../BroadphaseCollision/btDispatcher.h"
#include "../NarrowPhaseCollision/btPersistentManifold.h"
#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
#include "../CollisionDispatch/btManifoldResult.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h"
#include "../../LinearMath/btAlignedObjectArray.h"
class btIDebugDraw;
class btOverlappingPairCache;
class btPoolAllocator;
class btCollisionConfiguration;
#include "btCollisionCreateFunc.h"
@@ -35,7 +34,7 @@ class btCollisionConfiguration;
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);
typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo);
///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs.
@@ -47,22 +46,26 @@ class btCollisionDispatcher : public btDispatcher
btAlignedObjectArray<btPersistentManifold*> m_manifoldsPtr;
bool m_useIslands;
bool m_staticWarningReported;
btManifoldResult m_defaultManifoldResult;
btNearCallback m_nearCallback;
btPoolAllocator* m_collisionAlgorithmPoolAllocator;
btPoolAllocator* m_persistentManifoldPoolAllocator;
btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
btCollisionAlgorithmCreateFunc* internalFindCreateFunc(int proxyType0,int proxyType1);
btCollisionConfiguration* m_collisionConfiguration;
//default CreationFunctions, filling the m_doubleDispatch table
btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc;
btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc;
btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc;
btCollisionAlgorithmCreateFunc* m_compoundCreateFunc;
btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc;
btCollisionAlgorithmCreateFunc* m_emptyCreateFunc;
#ifndef USE_DISPATCH_REGISTRY_ARRAY
btCollisionAlgorithm* internalFindAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold = 0);
#endif //USE_DISPATCH_REGISTRY_ARRAY
public:
@@ -89,7 +92,11 @@ public:
return m_manifoldsPtr[index];
}
btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration);
///the default constructor creates/register default collision algorithms, for convex, compound and concave shape support
btCollisionDispatcher ();
///a special constructor that doesn't create/register the default collision algorithms
btCollisionDispatcher(bool noDefaultAlgorithms);
virtual ~btCollisionDispatcher();
@@ -107,7 +114,7 @@ public:
virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1);
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ;
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo);
void setNearCallback(btNearCallback nearCallback)
{
@@ -120,26 +127,7 @@ public:
}
//by default, Bullet will use this near callback
static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
virtual void* allocateCollisionAlgorithm(int size);
virtual void freeCollisionAlgorithm(void* ptr);
btCollisionConfiguration* getCollisionConfiguration()
{
return m_collisionConfiguration;
}
const btCollisionConfiguration* getCollisionConfiguration() const
{
return m_collisionConfiguration;
}
void setCollisionConfiguration(btCollisionConfiguration* config)
{
m_collisionConfiguration = config;
}
static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo);
};

View File

@@ -13,25 +13,18 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "btCollisionObject.h"
btCollisionObject::btCollisionObject()
: m_broadphaseHandle(0),
m_collisionShape(0),
m_rootCollisionShape(0),
m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT),
m_islandTag1(-1),
m_companionId(-1),
m_collisionFlags(0),
m_activationState1(1),
m_deactivationTime(btScalar(0.)),
m_friction(btScalar(0.5)),
m_restitution(btScalar(0.)),
m_userObjectPointer(0),
m_internalType(CO_COLLISION_OBJECT),
m_hitFraction(btScalar(1.)),
m_ccdSweptSphereRadius(btScalar(0.)),
m_ccdMotionThreshold(btScalar(0.)),
m_ccdSquareMotionThreshold(btScalar(0.)),
m_checkCollideWith(false)
{
@@ -62,4 +55,3 @@ void btCollisionObject::activate(bool forceActivation)
}

View File

@@ -16,7 +16,7 @@ subject to the following restrictions:
#ifndef COLLISION_OBJECT_H
#define COLLISION_OBJECT_H
#include "LinearMath/btTransform.h"
#include "../../LinearMath/btTransform.h"
//island management, m_activationState1
#define ACTIVE_TAG 1
@@ -27,8 +27,7 @@ subject to the following restrictions:
struct btBroadphaseProxy;
class btCollisionShape;
#include "LinearMath/btMotionState.h"
#include "LinearMath/btAlignedAllocator.h"
#include "../../LinearMath/btMotionState.h"
@@ -51,11 +50,6 @@ protected:
btVector3 m_interpolationAngularVelocity;
btBroadphaseProxy* m_broadphaseHandle;
btCollisionShape* m_collisionShape;
///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;
int m_collisionFlags;
@@ -71,9 +65,8 @@ protected:
///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer
void* m_userObjectPointer;
///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody etc.
///do not assign your own m_internalType unless you write a new dynamics object class.
int m_internalType;
///m_internalOwner is reserved to point to Bullet's btRigidBody. Don't use this, use m_userObjectPointer instead.
void* m_internalOwner;
///time of impact calculation
btScalar m_hitFraction;
@@ -81,23 +74,21 @@ protected:
///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
btScalar m_ccdSweptSphereRadius;
/// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
btScalar m_ccdMotionThreshold;
/// Don't do continuous collision detection if square motion (in one step) is less then m_ccdSquareMotionThreshold
btScalar m_ccdSquareMotionThreshold;
/// If some object should have elaborate collision filtering by sub-classes
bool m_checkCollideWith;
char m_pad[7];
virtual bool checkCollideWithOverride(btCollisionObject* /* co */)
virtual bool checkCollideWithOverride(btCollisionObject* co)
{
return true;
}
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
enum CollisionFlags
{
CF_STATIC_OBJECT= 1,
@@ -106,35 +97,29 @@ public:
CF_CUSTOM_MATERIAL_CALLBACK = 8//this allows per-triangle material (friction/restitution)
};
enum CollisionObjectTypes
{
CO_COLLISION_OBJECT =1,
CO_RIGID_BODY,
CO_SOFT_BODY
};
SIMD_FORCE_INLINE bool mergesSimulationIslands() const
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);
}
SIMD_FORCE_INLINE bool isStaticObject() const {
inline bool isStaticObject() const {
return (m_collisionFlags & CF_STATIC_OBJECT) != 0;
}
SIMD_FORCE_INLINE bool isKinematicObject() const
inline bool isKinematicObject() const
{
return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0;
}
SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const
inline bool isStaticOrKinematicObject() const
{
return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0 ;
}
SIMD_FORCE_INLINE bool hasContactResponse() const {
inline bool hasContactResponse() const {
return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0;
}
@@ -146,35 +131,20 @@ public:
void setCollisionShape(btCollisionShape* collisionShape)
{
m_collisionShape = collisionShape;
m_rootCollisionShape = collisionShape;
}
SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const
const btCollisionShape* getCollisionShape() const
{
return m_collisionShape;
}
SIMD_FORCE_INLINE btCollisionShape* getCollisionShape()
btCollisionShape* getCollisionShape()
{
return m_collisionShape;
}
SIMD_FORCE_INLINE const btCollisionShape* getRootCollisionShape() const
{
return m_rootCollisionShape;
}
SIMD_FORCE_INLINE btCollisionShape* getRootCollisionShape()
{
return m_rootCollisionShape;
}
///Avoid using this internal API call
///internalSetTemporaryCollisionShape is used to temporary replace the actual collision shape by a child collision shape.
void internalSetTemporaryCollisionShape(btCollisionShape* collisionShape)
{
m_collisionShape = collisionShape;
}
int getActivationState() const { return m_activationState1;}
@@ -216,9 +186,14 @@ public:
}
///reserved for Bullet internal usage
int getInternalType() const
void* getInternalOwner()
{
return m_internalType;
return m_internalOwner;
}
const void* getInternalOwner() const
{
return m_internalOwner;
}
btTransform& getWorldTransform()
@@ -268,15 +243,6 @@ public:
m_interpolationWorldTransform = trans;
}
void setInterpolationLinearVelocity(const btVector3& linvel)
{
m_interpolationLinearVelocity = linvel;
}
void setInterpolationAngularVelocity(const btVector3& angvel)
{
m_interpolationAngularVelocity = angvel;
}
const btVector3& getInterpolationLinearVelocity() const
{
@@ -341,22 +307,16 @@ public:
m_ccdSweptSphereRadius = radius;
}
btScalar getCcdMotionThreshold() const
{
return m_ccdMotionThreshold;
}
btScalar getCcdSquareMotionThreshold() const
{
return m_ccdMotionThreshold*m_ccdMotionThreshold;
return m_ccdSquareMotionThreshold;
}
/// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
void setCcdMotionThreshold(btScalar ccdMotionThreshold)
/// Don't do continuous collision detection if square motion (in one step) is less then m_ccdSquareMotionThreshold
void setCcdSquareMotionThreshold(btScalar ccdSquareMotionThreshold)
{
m_ccdMotionThreshold = ccdMotionThreshold*ccdMotionThreshold;
m_ccdSquareMotionThreshold = ccdSquareMotionThreshold;
}
///users can point to their objects, userPointer is not used by Bullet
@@ -371,7 +331,6 @@ public:
m_userObjectPointer = userPointer;
}
inline bool checkCollideWith(btCollisionObject* co)
{
if (m_checkCollideWith)
@@ -379,6 +338,9 @@ public:
return true;
}
};
}
;
#endif //COLLISION_OBJECT_H

View File

@@ -4,8 +4,8 @@ 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,
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.
@@ -18,57 +18,59 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" //for raycasting
#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" //for raycasting
#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "LinearMath/btAabbUtil2.h"
#include "LinearMath/btQuickprof.h"
#include "LinearMath/btStackAlloc.h"
//When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor)
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration)
btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache, int stackSize)
:m_dispatcher1(dispatcher),
m_broadphasePairCache(pairCache),
m_debugDrawer(0)
m_ownsDispatcher(false),
m_ownsBroadphasePairCache(false)
{
m_stackAlloc = collisionConfiguration->getStackAllocator();
m_stackAlloc = new btStackAlloc(stackSize);
m_dispatchInfo.m_stackAllocator = m_stackAlloc;
}
btCollisionWorld::~btCollisionWorld()
{
m_stackAlloc->destroy();
delete m_stackAlloc;
//clean up remaining objects
int i;
for (i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* collisionObject= m_collisionObjects[i];
btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
if (bp)
{
//
// only clear the cached algorithms
//
getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
getBroadphase()->destroyProxy(bp,m_dispatcher1);
getBroadphase()->cleanProxyFromPairs(bp);
getBroadphase()->destroyProxy(bp);
}
}
if (m_ownsDispatcher)
delete m_dispatcher1;
if (m_ownsBroadphasePairCache)
delete m_broadphasePairCache;
}
@@ -103,105 +105,66 @@ void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,sho
type,
collisionObject,
collisionFilterGroup,
collisionFilterMask,
m_dispatcher1,0
collisionFilterMask
)) ;
}
void btCollisionWorld::updateAabbs()
{
BT_PROFILE("updateAabbs");
btTransform predictedTrans;
for ( int i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
//only update aabb of active objects
if (colObj->isActive())
{
btPoint3 minAabb,maxAabb;
colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
//need to increase the aabb for contact thresholds
btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold);
minAabb -= contactThreshold;
maxAabb += contactThreshold;
btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache;
//moving objects should be moderately sized, probably something wrong if not
if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12)))
{
bp->setAabb(colObj->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1);
} else
{
//something went wrong, investigate
//this assert is unwanted in 3D modelers (danger of loosing work)
colObj->setActivationState(DISABLE_SIMULATION);
static bool reportMe = true;
if (reportMe && m_debugDrawer)
{
reportMe = false;
m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation");
m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n");
m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n");
m_debugDrawer->reportErrorWarning("Thanks.\n");
}
}
}
}
}
void btCollisionWorld::performDiscreteCollisionDetection()
{
BT_PROFILE("performDiscreteCollisionDetection");
btDispatcherInfo& dispatchInfo = getDispatchInfo();
updateAabbs();
BEGIN_PROFILE("perform Broadphase Collision Detection");
//update aabb (of all moved objects)
btVector3 aabbMin,aabbMax;
for (int i=0;i<m_collisionObjects.size();i++)
{
BT_PROFILE("calculateOverlappingPairs");
m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
m_collisionObjects[i]->getCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),aabbMin,aabbMax);
m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax);
}
m_broadphasePairCache->refreshOverlappingPairs();
END_PROFILE("perform Broadphase Collision Detection");
BEGIN_PROFILE("performDiscreteCollisionDetection");
btDispatcher* dispatcher = getDispatcher();
{
BT_PROFILE("dispatchAllCollisionPairs");
if (dispatcher)
dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
}
if (dispatcher)
dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache,dispatchInfo);
END_PROFILE("performDiscreteCollisionDetection");
}
void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
{
//bool removeFromBroadphase = false;
{
btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
if (bp)
{
//
// only clear the cached algorithms
//
getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
getBroadphase()->destroyProxy(bp,m_dispatcher1);
getBroadphase()->cleanProxyFromPairs(bp);
getBroadphase()->destroyProxy(bp);
collisionObject->setBroadphaseHandle(0);
}
}
@@ -218,466 +181,192 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
RayResultCallback& resultCallback)
RayResultCallback& resultCallback,
short int collisionFilterMask,
bool faceNormal)
{
btSphereShape pointShape(btScalar(0.0));
pointShape.setMargin(0.f);
const btConvexShape* castShape = &pointShape;
if (collisionShape->isConvex())
{
btConvexCast::CastResult castResult;
castResult.m_fraction = resultCallback.m_closestHitFraction;
btConvexShape* convexShape = (btConvexShape*) collisionShape;
btVoronoiSimplexSolver simplexSolver;
#define USE_SUBSIMPLEX_CONVEX_CAST 1
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver);
#else
//btGjkConvexCast convexCaster(castShape,convexShape,&simplexSolver);
//btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
#endif //#USE_SUBSIMPLEX_CONVEX_CAST
if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
{
//add hit
if (castResult.m_normal.length2() > btScalar(0.0001))
{
if (castResult.m_fraction < resultCallback.m_closestHitFraction)
{
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
//rotate normal into worldspace
castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal;
#endif //USE_SUBSIMPLEX_CONVEX_CAST
castResult.m_normal.normalize();
btCollisionWorld::LocalRayResult localRayResult
(
collisionObject,
0,
castResult.m_normal,
castResult.m_fraction
);
bool normalInWorldSpace = true;
resultCallback.addSingleResult(localRayResult, normalInWorldSpace);
}
}
}
} else {
if (collisionShape->isConcave())
{
if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
{
///optimized version for btBvhTriangleMeshShape
btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
btTransform worldTocollisionObject = colObjWorldTransform.inverse();
btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
//ConvexCast::CastResult
struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
{
btCollisionWorld::RayResultCallback* m_resultCallback;
btCollisionObject* m_collisionObject;
btTriangleMeshShape* m_triangleMesh;
BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh):
btTriangleRaycastCallback(from,to),
m_resultCallback(resultCallback),
m_collisionObject(collisionObject),
m_triangleMesh(triangleMesh)
{
}
virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
{
btCollisionWorld::LocalShapeInfo shapeInfo;
shapeInfo.m_shapePart = partId;
shapeInfo.m_triangleIndex = triangleIndex;
btCollisionWorld::LocalRayResult rayResult
(m_collisionObject,
&shapeInfo,
hitNormalLocal,
hitFraction);
bool normalInWorldSpace = false;
return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace);
}
};
BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh);
rcb.m_hitFraction = resultCallback.m_closestHitFraction;
triangleMesh->performRaycast(&rcb,rayFromLocal,rayToLocal);
} else
{
btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape;
btTransform worldTocollisionObject = colObjWorldTransform.inverse();
btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
//ConvexCast::CastResult
struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
{
btCollisionWorld::RayResultCallback* m_resultCallback;
btCollisionObject* m_collisionObject;
btTriangleMeshShape* m_triangleMesh;
BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh):
btTriangleRaycastCallback(from,to),
m_resultCallback(resultCallback),
m_collisionObject(collisionObject),
m_triangleMesh(triangleMesh)
{
}
virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
{
btCollisionWorld::LocalShapeInfo shapeInfo;
shapeInfo.m_shapePart = partId;
shapeInfo.m_triangleIndex = triangleIndex;
btCollisionWorld::LocalRayResult rayResult
(m_collisionObject,
&shapeInfo,
hitNormalLocal,
hitFraction);
bool normalInWorldSpace = false;
return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace);
}
};
BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh);
rcb.m_hitFraction = resultCallback.m_closestHitFraction;
btVector3 rayAabbMinLocal = rayFromLocal;
rayAabbMinLocal.setMin(rayToLocal);
btVector3 rayAabbMaxLocal = rayFromLocal;
rayAabbMaxLocal.setMax(rayToLocal);
triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal);
}
} else {
//todo: use AABB tree or other BVH acceleration structure!
if (collisionShape->isCompound())
{
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
int i=0;
for (i=0;i<compoundShape->getNumChildShapes();i++)
{
btTransform childTrans = compoundShape->getChildTransform(i);
const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
btTransform childWorldTrans = colObjWorldTransform * childTrans;
// replace collision shape so that callback can determine the triangle
btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape();
collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape);
rayTestSingle(rayFromTrans,rayToTrans,
collisionObject,
childCollisionShape,
childWorldTrans,
resultCallback);
// restore
collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape);
}
}
}
}
objectQuerySingle(&pointShape,rayFromTrans,rayToTrans,
collisionObject,
collisionShape,
colObjWorldTransform,
resultCallback,collisionFilterMask,faceNormal);
}
void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& rayFromTrans,const btTransform& rayToTrans,
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
ConvexResultCallback& resultCallback, btScalar allowedPenetration)
RayResultCallback& resultCallback,
short int collisionFilterMask,
bool faceNormal)
{
if (collisionShape->isConvex())
{
btConvexCast::CastResult castResult;
castResult.m_allowedPenetration = allowedPenetration;
castResult.m_fraction = btScalar(1.);//??
btConvexShape* convexShape = (btConvexShape*) collisionShape;
btVoronoiSimplexSolver simplexSolver;
btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver;
btContinuousConvexCollision convexCaster1(castShape,convexShape,&simplexSolver,&gjkEpaPenetrationSolver);
//btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver);
//btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver);
btConvexCast* castPtr = &convexCaster1;
if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
{
//add hit
if (castResult.m_normal.length2() > btScalar(0.0001))
{
if (castResult.m_fraction < resultCallback.m_closestHitFraction)
btConvexCast::CastResult castResult;
castResult.m_fraction = btScalar(1.);//??
btConvexShape* convexShape = (btConvexShape*) collisionShape;
btVoronoiSimplexSolver simplexSolver;
btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver);
//GjkConvexCast convexCaster(castShape,convexShape,&simplexSolver);
//ContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
{
castResult.m_normal.normalize();
btCollisionWorld::LocalConvexResult localConvexResult
//add hit
if (castResult.m_normal.length2() > btScalar(0.0001))
{
castResult.m_normal.normalize();
if (castResult.m_fraction < resultCallback.m_closestHitFraction)
{
btCollisionWorld::LocalRayResult localRayResult
(
collisionObject,
collisionObject,
0,
castResult.m_normal,
castResult.m_hitPoint,
castResult.m_fraction
);
bool normalInWorldSpace = true;
resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
resultCallback.AddSingleResult(localRayResult);
}
}
}
}
}
} else {
if (collisionShape->isConcave())
{
if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
else
{
btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
btTransform worldTocollisionObject = colObjWorldTransform.inverse();
btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
// rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
//ConvexCast::CastResult
struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
{
btCollisionWorld::ConvexResultCallback* m_resultCallback;
btCollisionObject* m_collisionObject;
btTriangleMeshShape* m_triangleMesh;
BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld):
btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
m_resultCallback(resultCallback),
m_collisionObject(collisionObject),
m_triangleMesh(triangleMesh)
{
}
virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
if (collisionShape->isConcave())
{
btCollisionWorld::LocalShapeInfo shapeInfo;
shapeInfo.m_shapePart = partId;
shapeInfo.m_triangleIndex = triangleIndex;
if (hitFraction <= m_resultCallback->m_closestHitFraction)
btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape;
btTransform worldTocollisionObject = colObjWorldTransform.inverse();
btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
//ConvexCast::CastResult
struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
{
btCollisionWorld::RayResultCallback* m_resultCallback;
btCollisionObject* m_collisionObject;
btTriangleMeshShape* m_triangleMesh;
btCollisionWorld::LocalConvexResult convexResult
(m_collisionObject,
&shapeInfo,
hitNormalLocal,
hitPointLocal,
hitFraction);
bool normalInWorldSpace = true;
BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,bool faceNormal,
btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh):
btTriangleRaycastCallback(from,to,faceNormal),
m_resultCallback(resultCallback),
m_collisionObject(collisionObject),
m_triangleMesh(triangleMesh)
{
}
return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
}
return hitFraction;
}
};
BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform);
tccb.m_hitFraction = resultCallback.m_closestHitFraction;
btVector3 boxMinLocal, boxMaxLocal;
castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal);
} else
{
btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
btTransform worldTocollisionObject = colObjWorldTransform.inverse();
btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
// rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
//ConvexCast::CastResult
struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
{
btCollisionWorld::ConvexResultCallback* m_resultCallback;
btCollisionObject* m_collisionObject;
btTriangleMeshShape* m_triangleMesh;
BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld):
btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
m_resultCallback(resultCallback),
m_collisionObject(collisionObject),
m_triangleMesh(triangleMesh)
{
}
virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
{
btCollisionWorld::LocalShapeInfo shapeInfo;
shapeInfo.m_shapePart = partId;
shapeInfo.m_triangleIndex = triangleIndex;
shapeInfo.m_triangleShape = m_triangleMesh;
btCollisionWorld::LocalRayResult rayResult
(m_collisionObject,
&shapeInfo,
hitNormalLocal,
hitFraction);
return m_resultCallback->AddSingleResult(rayResult);
}
};
virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,faceNormal,&resultCallback,collisionObject,triangleMesh);
rcb.m_hitFraction = resultCallback.m_closestHitFraction;
btVector3 rayAabbMinLocal = rayFromLocal;
rayAabbMinLocal.setMin(rayToLocal);
btVector3 rayAabbMaxLocal = rayFromLocal;
rayAabbMaxLocal.setMax(rayToLocal);
triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal);
} else
{
btCollisionWorld::LocalShapeInfo shapeInfo;
shapeInfo.m_shapePart = partId;
shapeInfo.m_triangleIndex = triangleIndex;
if (hitFraction <= m_resultCallback->m_closestHitFraction)
//todo: use AABB tree or other BVH acceleration structure!
if (collisionShape->isCompound())
{
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
int i=0;
for (i=0;i<compoundShape->getNumChildShapes();i++)
{
btTransform childTrans = compoundShape->getChildTransform(i);
const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
btTransform childWorldTrans = colObjWorldTransform * childTrans;
objectQuerySingle(castShape, rayFromTrans,rayToTrans,
collisionObject,
childCollisionShape,
childWorldTrans,
resultCallback, collisionFilterMask, faceNormal);
btCollisionWorld::LocalConvexResult convexResult
(m_collisionObject,
&shapeInfo,
hitNormalLocal,
hitPointLocal,
hitFraction);
}
bool normalInWorldSpace = false;
return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
}
return hitFraction;
}
};
BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform);
tccb.m_hitFraction = resultCallback.m_closestHitFraction;
btVector3 boxMinLocal, boxMaxLocal;
castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
btVector3 rayAabbMinLocal = convexFromLocal;
rayAabbMinLocal.setMin(convexToLocal);
btVector3 rayAabbMaxLocal = convexFromLocal;
rayAabbMaxLocal.setMax(convexToLocal);
rayAabbMinLocal += boxMinLocal;
rayAabbMaxLocal += boxMaxLocal;
triangleMesh->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal);
}
} else {
//todo: use AABB tree or other BVH acceleration structure!
if (collisionShape->isCompound())
{
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
int i=0;
for (i=0;i<compoundShape->getNumChildShapes();i++)
{
btTransform childTrans = compoundShape->getChildTransform(i);
const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
btTransform childWorldTrans = colObjWorldTransform * childTrans;
// replace collision shape so that callback can determine the triangle
btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape();
collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape);
objectQuerySingle(castShape, convexFromTrans,convexToTrans,
collisionObject,
childCollisionShape,
childWorldTrans,
resultCallback, allowedPenetration);
// restore
collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape);
}
}
}
}
}
void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback,short int collisionFilterMask, bool faceNormal)
{
btTransform rayFromTrans,rayToTrans;
rayFromTrans.setIdentity();
rayFromTrans.setOrigin(rayFromWorld);
rayToTrans.setIdentity();
rayToTrans.setOrigin(rayToWorld);
/// go over all objects, and if the ray intersects their aabb, do a ray-shape query using convexCaster (CCD)
int i;
for (i=0;i<m_collisionObjects.size();i++)
{
///terminate further ray tests, once the closestHitFraction reached zero
if (resultCallback.m_closestHitFraction == btScalar(0.f))
break;
btCollisionObject* collisionObject= m_collisionObjects[i];
//only perform raycast if filterMask matches
if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
if(collisionObject->getBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) {
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
btScalar hitLambda = resultCallback.m_closestHitFraction;
btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
btVector3 hitNormal;
if (btRayAabb(rayFromWorld,rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
{
rayTestSingle(rayFromTrans,rayToTrans,
collisionObject,
collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(),
resultCallback);
}
}
}
}
void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback) const
{
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);
btTransform R;
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_collisionObjects.size();i++)
{
btCollisionObject* collisionObject= m_collisionObjects[i];
//only perform raycast if filterMask matches
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 hitNormal;
if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
{
objectQuerySingle(castShape, convexFromTrans,convexToTrans,
collisionObject,
collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(),
resultCallback,
getDispatchInfo().m_allowedCcdPenetration);
}
// before testing this object, verify that it is not filtered out
if (resultCallback.NeedRayCast(collisionObject))
{
rayTestSingle(rayFromTrans,rayToTrans,
collisionObject,
collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(),
resultCallback,
collisionFilterMask,
faceNormal);
}
}
}
}

View File

@@ -68,12 +68,12 @@ class btStackAlloc;
class btCollisionShape;
class btConvexShape;
class btBroadphaseInterface;
#include "LinearMath/btVector3.h"
#include "LinearMath/btTransform.h"
#include "../../LinearMath/btVector3.h"
#include "../../LinearMath/btTransform.h"
#include "btCollisionObject.h"
#include "btCollisionDispatcher.h" //for definition of btCollisionObjectArray
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "../BroadphaseCollision/btOverlappingPairCache.h"
#include "../../LinearMath/btAlignedObjectArray.h"
///CollisionWorld is interface and container for the collision detection
class btCollisionWorld
@@ -90,22 +90,18 @@ protected:
btStackAlloc* m_stackAlloc;
btBroadphaseInterface* m_broadphasePairCache;
btIDebugDraw* m_debugDrawer;
btOverlappingPairCache* m_broadphasePairCache;
bool m_ownsDispatcher;
bool m_ownsBroadphasePairCache;
public:
//this constructor doesn't own the dispatcher and paircache/broadphase
btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration);
btCollisionWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache, int stackSize = 2*1024*1024);
virtual ~btCollisionWorld();
void setBroadphase(btBroadphaseInterface* pairCache)
{
m_broadphasePairCache = pairCache;
}
btBroadphaseInterface* getBroadphase()
{
@@ -114,7 +110,7 @@ public:
btOverlappingPairCache* getPairCache()
{
return m_broadphasePairCache->getOverlappingPairCache();
return m_broadphasePairCache;
}
@@ -123,32 +119,14 @@ public:
return m_dispatcher1;
}
const btDispatcher* getDispatcher() const
{
return m_dispatcher1;
}
virtual void updateAabbs();
virtual void setDebugDrawer(btIDebugDraw* debugDrawer)
{
m_debugDrawer = debugDrawer;
}
virtual btIDebugDraw* getDebugDrawer()
{
return m_debugDrawer;
}
///LocalShapeInfo gives extra information for complex shapes
///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart
struct LocalShapeInfo
{
int m_shapePart;
int m_triangleIndex;
//const btCollisionShape* m_shapeTemp;
// needed in case of compound shape
const btCollisionShape* m_triangleShape;
//const btTransform* m_shapeLocalTransform;
};
@@ -175,43 +153,32 @@ public:
///RayResultCallback is used to report new raycast results
struct RayResultCallback
{
btScalar m_closestHitFraction;
btCollisionObject* m_collisionObject;
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
virtual ~RayResultCallback()
{
}
bool hasHit() const
btScalar m_closestHitFraction;
bool HasHit()
{
return (m_collisionObject != 0);
return (m_closestHitFraction < btScalar(1.));
}
RayResultCallback()
:m_closestHitFraction(btScalar(1.)),
m_collisionObject(0),
m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
m_collisionFilterMask(btBroadphaseProxy::AllFilter)
:m_closestHitFraction(btScalar(1.))
{
}
virtual bool needsCollision(btBroadphaseProxy* proxy0) const
virtual bool NeedRayCast(btCollisionObject* object)
{
bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
return collides;
return true;
}
virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0;
virtual btScalar AddSingleResult(LocalRayResult& rayResult) = 0;
};
struct ClosestRayResultCallback : public RayResultCallback
{
ClosestRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld)
:m_rayFromWorld(rayFromWorld),
m_rayToWorld(rayToWorld)
m_rayToWorld(rayToWorld),
m_collisionObject(0)
{
}
@@ -220,121 +187,24 @@ public:
btVector3 m_hitNormalWorld;
btVector3 m_hitPointWorld;
virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace)
btCollisionObject* m_collisionObject;
virtual btScalar AddSingleResult(LocalRayResult& rayResult)
{
//caller already does the filter on the m_closestHitFraction
btAssert(rayResult.m_hitFraction <= m_closestHitFraction);
//caller already does the filter on the m_closestHitFraction
assert(rayResult.m_hitFraction <= m_closestHitFraction);
m_closestHitFraction = rayResult.m_hitFraction;
m_collisionObject = rayResult.m_collisionObject;
if (normalInWorldSpace)
{
m_hitNormalWorld = rayResult.m_hitNormalLocal;
} 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);
return rayResult.m_hitFraction;
}
};
struct LocalConvexResult
{
LocalConvexResult(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)
{
}
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
{
btScalar m_closestHitFraction;
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
ConvexResultCallback()
:m_closestHitFraction(btScalar(1.)),
m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
m_collisionFilterMask(btBroadphaseProxy::AllFilter)
{
}
virtual ~ConvexResultCallback()
{
}
bool hasHit() const
{
return (m_closestHitFraction < btScalar(1.));
}
virtual bool needsCollision(btBroadphaseProxy* proxy0) const
{
bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
return collides;
}
virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) = 0;
};
struct ClosestConvexResultCallback : public ConvexResultCallback
{
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_hitNormalWorld;
btVector3 m_hitPointWorld;
btCollisionObject* m_hitCollisionObject;
virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace)
{
//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
{
///need to transform normal into worldspace
m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
}
m_hitPointWorld = convexResult.m_hitPointLocal;
return convexResult.m_hitFraction;
}
};
int getNumCollisionObjects() const
{
@@ -343,12 +213,7 @@ public:
/// 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.
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) const;
void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback, short int collisionFilterMask=-1, bool faceNormal=false);
/// 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.
@@ -357,16 +222,20 @@ public:
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
RayResultCallback& resultCallback);
RayResultCallback& resultCallback,
short int collisionFilterMask=-1,
bool faceNormal=false);
/// 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);
RayResultCallback& resultCallback,
short int collisionFilterMask=-1,
bool faceNormal=false);
void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter);
void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=1,short int collisionFilterMask=1);
btCollisionObjectArray& getCollisionObjectArray()
{
@@ -388,11 +257,6 @@ public:
return m_dispatchInfo;
}
const btDispatcherInfo& getDispatchInfo() const
{
return m_dispatchInfo;
}
};

View File

@@ -16,17 +16,11 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "BulletCollision/BroadphaseCollision/btDbvt.h"
#include "LinearMath/btIDebugDraw.h"
#include "LinearMath/btAabbUtil2.h"
btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
:btCollisionAlgorithm(ci),
m_isSwapped(isSwapped),
m_sharedManifold(ci.m_manifold)
:m_isSwapped(isSwapped)
{
m_ownsManifold = false;
btCollisionObject* colObj = m_isSwapped? body1 : body0;
btCollisionObject* otherObj = m_isSwapped? body0 : body1;
assert (colObj->getCollisionShape()->isCompound());
@@ -38,17 +32,11 @@ m_sharedManifold(ci.m_manifold)
m_childCollisionAlgorithms.resize(numChildren);
for (i=0;i<numChildren;i++)
{
if (compoundShape->getDynamicAabbTree())
{
m_childCollisionAlgorithms[i] = 0;
} else
{
btCollisionShape* tmpShape = colObj->getCollisionShape();
btCollisionShape* childShape = compoundShape->getChildShape(i);
colObj->internalSetTemporaryCollisionShape( childShape );
m_childCollisionAlgorithms[i] = ci.m_dispatcher1->findAlgorithm(colObj,otherObj,m_sharedManifold);
colObj->internalSetTemporaryCollisionShape( tmpShape );
}
btCollisionShape* childShape = compoundShape->getChildShape(i);
btCollisionShape* orgShape = colObj->getCollisionShape();
colObj->setCollisionShape( childShape );
m_childCollisionAlgorithms[i] = ci.m_dispatcher->findAlgorithm(colObj,otherObj);
colObj->setCollisionShape( orgShape );
}
}
@@ -59,109 +47,10 @@ btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm()
int i;
for (i=0;i<numChildren;i++)
{
if (m_childCollisionAlgorithms[i])
{
m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
}
delete m_childCollisionAlgorithms[i];
}
}
struct btCompoundLeafCallback : btDbvt::ICollide
{
public:
btCollisionObject* m_compoundColObj;
btCollisionObject* m_otherObj;
btDispatcher* m_dispatcher;
const btDispatcherInfo& m_dispatchInfo;
btManifoldResult* m_resultOut;
btCollisionAlgorithm** m_childCollisionAlgorithms;
btPersistentManifold* m_sharedManifold;
btCompoundLeafCallback (btCollisionObject* compoundObj,btCollisionObject* otherObj,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut,btCollisionAlgorithm** childCollisionAlgorithms,btPersistentManifold* sharedManifold)
:m_compoundColObj(compoundObj),m_otherObj(otherObj),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
m_childCollisionAlgorithms(childCollisionAlgorithms),
m_sharedManifold(sharedManifold)
{
}
void ProcessChildShape(btCollisionShape* childShape,int index)
{
btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape());
//backup
btTransform orgTrans = m_compoundColObj->getWorldTransform();
btTransform orgInterpolationTrans = m_compoundColObj->getInterpolationWorldTransform();
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_otherObj->getCollisionShape()->getAabb(m_otherObj->getWorldTransform(),aabbMin1,aabbMax1);
if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
{
m_compoundColObj->setWorldTransform( newChildWorldTrans);
m_compoundColObj->setInterpolationWorldTransform(newChildWorldTrans);
//the contactpoint is still projected back using the original inverted worldtrans
btCollisionShape* tmpShape = m_compoundColObj->getCollisionShape();
m_compoundColObj->internalSetTemporaryCollisionShape( childShape );
if (!m_childCollisionAlgorithms[index])
m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(m_compoundColObj,m_otherObj,m_sharedManifold);
m_childCollisionAlgorithms[index]->processCollision(m_compoundColObj,m_otherObj,m_dispatchInfo,m_resultOut);
if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
{
btVector3 worldAabbMin,worldAabbMax;
m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1));
m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1));
}
//revert back transform
m_compoundColObj->internalSetTemporaryCollisionShape( tmpShape);
m_compoundColObj->setWorldTransform( orgTrans );
m_compoundColObj->setInterpolationWorldTransform(orgInterpolationTrans);
}
}
void Process(const btDbvtNode* leaf)
{
int index = leaf->dataAsInt;
btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape());
btCollisionShape* childShape = compoundShape->getChildShape(index);
if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
{
btVector3 worldAabbMin,worldAabbMax;
btTransform orgTrans = m_compoundColObj->getWorldTransform();
btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax);
m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0));
}
ProcessChildShape(childShape,index);
}
};
void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
btCollisionObject* colObj = m_isSwapped? body1 : body0;
@@ -170,69 +59,33 @@ void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,bt
assert (colObj->getCollisionShape()->isCompound());
btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
btDbvt* tree = compoundShape->getDynamicAabbTree();
//use a dynamic aabb tree to cull potential child-overlaps
btCompoundLeafCallback callback(colObj,otherObj,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);
//We will use the OptimizedBVH, AABB tree to cull potential child-overlaps
//If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals
//given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means:
//determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1
//then use each overlapping node AABB against Tree0
//and vise versa.
if (tree)
int numChildren = m_childCollisionAlgorithms.size();
int i;
for (i=0;i<numChildren;i++)
{
//temporarily exchange parent btCollisionShape with childShape, and recurse
btCollisionShape* childShape = compoundShape->getChildShape(i);
btVector3 localAabbMin,localAabbMax;
btTransform otherInCompoundSpace;
otherInCompoundSpace = colObj->getWorldTransform().inverse() * otherObj->getWorldTransform();
otherObj->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax);
const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
//process all children, that overlap with the given AABB bounds
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++)
{
callback.ProcessChildShape(compoundShape->getChildShape(i),i);
}
}
{
//iterate over all children, perform an AABB check inside ProcessChildShape
int numChildren = m_childCollisionAlgorithms.size();
int i;
btManifoldArray manifoldArray;
for (i=0;i<numChildren;i++)
{
if (m_childCollisionAlgorithms[i])
{
btCollisionShape* childShape = compoundShape->getChildShape(i);
//if not longer overlapping, remove the algorithm
btTransform orgTrans = colObj->getWorldTransform();
btTransform orgInterpolationTrans = colObj->getInterpolationWorldTransform();
const btTransform& childTrans = compoundShape->getChildTransform(i);
btTransform newChildWorldTrans = orgTrans*childTrans ;
//perform an AABB check first
btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
otherObj->getCollisionShape()->getAabb(otherObj->getWorldTransform(),aabbMin1,aabbMax1);
if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
{
m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
m_childCollisionAlgorithms[i] = 0;
}
}
}
//backup
btTransform orgTrans = colObj->getWorldTransform();
btCollisionShape* orgShape = colObj->getCollisionShape();
const btTransform& childTrans = compoundShape->getChildTransform(i);
//btTransform newChildWorldTrans = orgTrans*childTrans ;
colObj->setWorldTransform( orgTrans*childTrans );
//the contactpoint is still projected back using the original inverted worldtrans
colObj->setCollisionShape( childShape );
m_childCollisionAlgorithms[i]->processCollision(colObj,otherObj,dispatchInfo,resultOut);
//revert back
colObj->setCollisionShape( orgShape);
colObj->setWorldTransform( orgTrans );
}
}
@@ -264,20 +117,20 @@ btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject*
//backup
btTransform orgTrans = colObj->getWorldTransform();
btCollisionShape* orgShape = colObj->getCollisionShape();
const btTransform& childTrans = compoundShape->getChildTransform(i);
//btTransform newChildWorldTrans = orgTrans*childTrans ;
colObj->setWorldTransform( orgTrans*childTrans );
btCollisionShape* tmpShape = colObj->getCollisionShape();
colObj->internalSetTemporaryCollisionShape( childShape );
colObj->setCollisionShape( childShape );
btScalar frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut);
if (frac<hitFraction)
{
hitFraction = frac;
}
//revert back
colObj->internalSetTemporaryCollisionShape( tmpShape);
colObj->setCollisionShape( orgShape);
colObj->setWorldTransform( orgTrans);
}
return hitFraction;

View File

@@ -16,25 +16,22 @@ subject to the following restrictions:
#ifndef COMPOUND_COLLISION_ALGORITHM_H
#define COMPOUND_COLLISION_ALGORITHM_H
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "../BroadphaseCollision/btCollisionAlgorithm.h"
#include "../BroadphaseCollision/btDispatcher.h"
#include "../BroadphaseCollision/btBroadphaseInterface.h"
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
#include "../NarrowPhaseCollision/btPersistentManifold.h"
class btDispatcher;
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h"
#include "btCollisionCreateFunc.h"
#include "LinearMath/btAlignedObjectArray.h"
class btDispatcher;
#include "../../LinearMath/btAlignedObjectArray.h"
/// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes
/// Place holder, not fully implemented yet
class btCompoundCollisionAlgorithm : public btCollisionAlgorithm
{
btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithms;
bool m_isSwapped;
class btPersistentManifold* m_sharedManifold;
bool m_ownsManifold;
public:
@@ -46,22 +43,11 @@ public:
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++)
{
if (m_childCollisionAlgorithms[i])
m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
}
}
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,false);
return new btCompoundCollisionAlgorithm(ci,body0,body1,false);
}
};
@@ -69,8 +55,7 @@ public:
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,true);
return new btCompoundCollisionAlgorithm(ci,body0,body1,true);
}
};

View File

@@ -29,7 +29,7 @@ subject to the following restrictions:
btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
: btCollisionAlgorithm(ci),
m_isSwapped(isSwapped),
m_btConvexTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped)
m_btConvexTriangleCallback(ci.m_dispatcher,body0,body1,isSwapped)
{
}
@@ -37,13 +37,6 @@ btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm()
{
}
void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_btConvexTriangleCallback.m_manifoldPtr)
{
manifoldArray.push_back(m_btConvexTriangleCallback.m_manifoldPtr);
}
}
btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped):
@@ -86,7 +79,7 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i
//aabb filter is already applied!
btCollisionAlgorithmConstructionInfo ci;
ci.m_dispatcher1 = m_dispatcher;
ci.m_dispatcher = m_dispatcher;
btCollisionObject* ob = static_cast<btCollisionObject*>(m_triBody);
@@ -116,11 +109,13 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i
{
btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
tm.setMargin(m_collisionMarginTriangle);
btCollisionShape* tmpShape = ob->getCollisionShape();
ob->internalSetTemporaryCollisionShape( &tm );
ob->setCollisionShape( &tm );
btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr);
btCollisionAlgorithm* colAlgo = ci.m_dispatcher->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr);
///this should use the btDispatcher, so the actual registered algorithm is used
// btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody);
@@ -128,11 +123,12 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i
// cvxcvxalgo.setShapeIdentifiers(-1,-1,partId,triangleIndex);
// cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
colAlgo->processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
colAlgo->~btCollisionAlgorithm();
ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
ob->internalSetTemporaryCollisionShape( tmpShape);
delete colAlgo;
ob->setCollisionShape( tmpShape );
}
}
@@ -192,10 +188,9 @@ void btConvexConcaveCollisionAlgorithm::processCollision (btCollisionObject* bod
concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax());
resultOut->refreshContactPoints();
}
}
}

View File

@@ -16,13 +16,13 @@ subject to the following restrictions:
#ifndef CONVEX_CONCAVE_COLLISION_ALGORITHM_H
#define CONVEX_CONCAVE_COLLISION_ALGORITHM_H
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
#include "../BroadphaseCollision/btCollisionAlgorithm.h"
#include "../BroadphaseCollision/btDispatcher.h"
#include "../BroadphaseCollision/btBroadphaseInterface.h"
#include "../CollisionShapes/btTriangleCallback.h"
#include "../NarrowPhaseCollision/btPersistentManifold.h"
class btDispatcher;
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h"
#include "btCollisionCreateFunc.h"
///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called.
@@ -55,11 +55,11 @@ int m_triangleCount;
void clearCache();
SIMD_FORCE_INLINE const btVector3& getAabbMin() const
inline const btVector3& getAabbMin() const
{
return m_aabbMin;
}
SIMD_FORCE_INLINE const btVector3& getAabbMax() const
inline const btVector3& getAabbMax() const
{
return m_aabbMax;
}
@@ -88,16 +88,13 @@ public:
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray);
void clearCache();
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,false);
return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,false);
}
};
@@ -105,8 +102,7 @@ public:
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,true);
return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,true);
}
};

View File

@@ -15,7 +15,7 @@ subject to the following restrictions:
#include "btConvexConvexAlgorithm.h"
//#include <stdio.h>
#include <stdio.h>
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
@@ -33,6 +33,7 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h"
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
@@ -47,16 +48,26 @@ subject to the following restrictions:
btConvexConvexAlgorithm::CreateFunc::CreateFunc()
{
m_ownsSolvers = true;
m_simplexSolver = new btVoronoiSimplexSolver();
m_pdSolver = new btGjkEpaPenetrationDepthSolver;
}
btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
{
m_ownsSolvers = false;
m_simplexSolver = simplexSolver;
m_pdSolver = pdSolver;
}
btConvexConvexAlgorithm::CreateFunc::~CreateFunc()
{
if (m_ownsSolvers){
delete m_simplexSolver;
delete m_pdSolver;
}
}
btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
@@ -141,11 +152,6 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
m_gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
#endif
if (m_ownManifold)
{
resultOut->refreshContactPoints();
}
}

View File

@@ -16,13 +16,12 @@ subject to the following restrictions:
#ifndef CONVEX_CONVEX_ALGORITHM_H
#define CONVEX_CONVEX_ALGORITHM_H
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "../BroadphaseCollision/btCollisionAlgorithm.h"
#include "../NarrowPhaseCollision/btGjkPairDetector.h"
#include "../NarrowPhaseCollision/btPersistentManifold.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h"
#include "../NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "btCollisionCreateFunc.h"
#include "btCollisionDispatcher.h"
class btConvexPenetrationDepthSolver;
@@ -47,14 +46,6 @@ public:
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
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);
@@ -67,15 +58,15 @@ public:
{
btConvexPenetrationDepthSolver* m_pdSolver;
btSimplexSolverInterface* m_simplexSolver;
bool m_ownsSolvers;
CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
CreateFunc();
virtual ~CreateFunc();
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm));
return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver);
return new btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver);
}
};

View File

@@ -1,108 +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 "btConvexPlaneCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
//#include <stdio.h>
btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped)
: btCollisionAlgorithm(ci),
m_ownManifold(false),
m_manifoldPtr(mf),
m_isSwapped(isSwapped)
{
btCollisionObject* convexObj = m_isSwapped? col1 : col0;
btCollisionObject* planeObj = m_isSwapped? col0 : col1;
if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObj,planeObj))
{
m_manifoldPtr = m_dispatcher->getNewManifold(convexObj,planeObj);
m_ownManifold = true;
}
}
btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm()
{
if (m_ownManifold)
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}
}
void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)dispatchInfo;
(void)resultOut;
if (!m_manifoldPtr)
return;
btCollisionObject* convexObj = m_isSwapped? body1 : body0;
btCollisionObject* planeObj = m_isSwapped? body0: body1;
btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape();
btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape();
bool hasCollision = false;
const btVector3& planeNormal = planeShape->getPlaneNormal();
const btScalar& planeConstant = planeShape->getPlaneConstant();
btTransform planeInConvex;
planeInConvex= convexObj->getWorldTransform().inverse() * planeObj->getWorldTransform();
btTransform convexInPlaneTrans;
convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexObj->getWorldTransform();
btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
btVector3 vtxInPlane = convexInPlaneTrans(vtx);
btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected;
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 = planeObj->getWorldTransform().getBasis() * planeNormal;
btVector3 pOnB = vtxInPlaneWorld;
resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance);
}
if (m_ownManifold)
{
if (m_manifoldPtr->getNumContacts())
{
resultOut->refreshContactPoints();
}
}
}
btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
(void)col0;
(void)col1;
//not yet
return btScalar(1.);
}

View File

@@ -1,71 +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 CONVEX_PLANE_COLLISION_ALGORITHM_H
#define CONVEX_PLANE_COLLISION_ALGORITHM_H
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
class btPersistentManifold;
#include "btCollisionDispatcher.h"
#include "LinearMath/btVector3.h"
/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection.
/// Other features are frame-coherency (persistent data) and collision response.
class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_isSwapped;
public:
btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped);
virtual ~btConvexPlaneCollisionAlgorithm();
virtual void processCollision (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)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm));
if (!m_swapped)
{
return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,false);
} else
{
return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,true);
}
}
};
};
#endif //CONVEX_PLANE_COLLISION_ALGORITHM_H

View File

@@ -1,291 +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 "btDefaultCollisionConfiguration.h"
#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
#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/btStackAlloc.h"
#include "LinearMath/btPoolAllocator.h"
btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo)
//btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* stackAlloc,btPoolAllocator* persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool)
{
void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16);
m_simplexSolver = new (mem)btVoronoiSimplexSolver();
#define USE_EPA 1
#ifdef USE_EPA
mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16);
m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver;
#else
mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver),16);
m_pdSolver = new (mem)btMinkowskiPenetrationDepthSolver;
#endif//USE_EPA
//default CreationFunctions, filling the m_doubleDispatch table
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(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;
m_boxSphereCF->m_swapped = true;
#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;
m_triangleSphereCF->m_swapped = true;
mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc),16);
m_boxBoxCF = new(mem)btBoxBoxCollisionAlgorithm::CreateFunc;
//convex versus plane
mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
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(btEmptyAlgorithm);
int collisionAlgorithmMaxElementSize = btMax(maxSize,maxSize2);
collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3);
collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize4);
if (constructionInfo.m_stackAlloc)
{
m_ownsStackAllocator = false;
this->m_stackAlloc = constructionInfo.m_stackAlloc;
} else
{
m_ownsStackAllocator = true;
void* mem = btAlignedAlloc(sizeof(btStackAlloc),16);
m_stackAlloc = new(mem)btStackAlloc(constructionInfo.m_defaultStackAllocatorSize);
}
if (constructionInfo.m_persistentManifoldPool)
{
m_ownsPersistentManifoldPool = false;
m_persistentManifoldPool = constructionInfo.m_persistentManifoldPool;
} else
{
m_ownsPersistentManifoldPool = true;
void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),constructionInfo.m_defaultMaxPersistentManifoldPoolSize);
}
if (constructionInfo.m_collisionAlgorithmPool)
{
m_ownsCollisionAlgorithmPool = false;
m_collisionAlgorithmPool = constructionInfo.m_collisionAlgorithmPool;
} else
{
m_ownsCollisionAlgorithmPool = true;
void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
}
}
btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration()
{
if (m_ownsStackAllocator)
{
m_stackAlloc->destroy();
m_stackAlloc->~btStackAlloc();
btAlignedFree(m_stackAlloc);
}
if (m_ownsCollisionAlgorithmPool)
{
m_collisionAlgorithmPool->~btPoolAllocator();
btAlignedFree(m_collisionAlgorithmPool);
}
if (m_ownsPersistentManifoldPool)
{
m_persistentManifoldPool->~btPoolAllocator();
btAlignedFree(m_persistentManifoldPool);
}
m_convexConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree( m_convexConvexCreateFunc);
m_convexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree( m_convexConcaveCreateFunc);
m_swappedConvexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree( m_swappedConvexConcaveCreateFunc);
m_compoundCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree( m_compoundCreateFunc);
m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree( m_swappedCompoundCreateFunc);
m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree( m_emptyCreateFunc);
m_sphereSphereCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree( m_sphereSphereCF);
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
m_sphereBoxCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree( m_sphereBoxCF);
m_boxSphereCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree( m_boxSphereCF);
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree( m_sphereTriangleCF);
m_triangleSphereCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree( m_triangleSphereCF);
m_boxBoxCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree( m_boxBoxCF);
m_convexPlaneCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree( m_convexPlaneCF);
m_planeConvexCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree( m_planeConvexCF);
m_simplexSolver->~btVoronoiSimplexSolver();
btAlignedFree(m_simplexSolver);
m_pdSolver->~btConvexPenetrationDepthSolver();
btAlignedFree(m_pdSolver);
}
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;
}
if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
{
return m_boxBoxCF;
}
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))
{
return m_compoundCreateFunc;
} else
{
if (btBroadphaseProxy::isCompound(proxyType1))
{
return m_swappedCompoundCreateFunc;
}
}
//failed to find an algorithm
return m_emptyCreateFunc;
}

View File

@@ -1,115 +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_DEFAULT_COLLISION_CONFIGURATION
#define BT_DEFAULT_COLLISION_CONFIGURATION
#include "btCollisionConfiguration.h"
class btVoronoiSimplexSolver;
class btConvexPenetrationDepthSolver;
struct btDefaultCollisionConstructionInfo
{
btStackAlloc* m_stackAlloc;
btPoolAllocator* m_persistentManifoldPool;
btPoolAllocator* m_collisionAlgorithmPool;
int m_defaultMaxPersistentManifoldPoolSize;
int m_defaultMaxCollisionAlgorithmPoolSize;
int m_defaultStackAllocatorSize;
btDefaultCollisionConstructionInfo()
:m_stackAlloc(0),
m_persistentManifoldPool(0),
m_collisionAlgorithmPool(0),
m_defaultMaxPersistentManifoldPoolSize(65535),
m_defaultMaxCollisionAlgorithmPoolSize(65535),
m_defaultStackAllocatorSize(5*1024*1024)
{
}
};
///btCollisionConfiguration allows to configure Bullet collision detection
///stack allocator, pool memory allocators
///todo: describe the meaning
class btDefaultCollisionConfiguration : public btCollisionConfiguration
{
int m_persistentManifoldPoolSize;
btStackAlloc* m_stackAlloc;
bool m_ownsStackAllocator;
btPoolAllocator* m_persistentManifoldPool;
bool m_ownsPersistentManifoldPool;
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_swappedCompoundCreateFunc;
btCollisionAlgorithmCreateFunc* m_emptyCreateFunc;
btCollisionAlgorithmCreateFunc* m_sphereSphereCF;
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
btCollisionAlgorithmCreateFunc* m_sphereBoxCF;
btCollisionAlgorithmCreateFunc* m_boxSphereCF;
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
btCollisionAlgorithmCreateFunc* m_boxBoxCF;
btCollisionAlgorithmCreateFunc* m_sphereTriangleCF;
btCollisionAlgorithmCreateFunc* m_triangleSphereCF;
btCollisionAlgorithmCreateFunc* m_planeConvexCF;
btCollisionAlgorithmCreateFunc* m_convexPlaneCF;
public:
btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo());
virtual ~btDefaultCollisionConfiguration();
///memory pools
virtual btPoolAllocator* getPersistentManifoldPool()
{
return m_persistentManifoldPool;
}
virtual btPoolAllocator* getCollisionAlgorithmPool()
{
return m_collisionAlgorithmPool;
}
virtual btStackAlloc* getStackAllocator()
{
return m_stackAlloc;
}
virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1);
};
#endif //BT_DEFAULT_COLLISION_CONFIGURATION

View File

@@ -15,9 +15,8 @@ subject to the following restrictions:
#ifndef EMPTY_ALGORITH
#define EMPTY_ALGORITH
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "../BroadphaseCollision/btCollisionAlgorithm.h"
#include "btCollisionCreateFunc.h"
#include "btCollisionDispatcher.h"
#define ATTRIBUTE_ALIGNED(a)
@@ -34,18 +33,13 @@ public:
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
}
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
(void)body0;
(void)body1;
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm));
return new(mem) btEmptyAlgorithm(ci);
return new btEmptyAlgorithm(ci);
}
};

View File

@@ -79,30 +79,12 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b
}
btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
newPt.m_positionWorldOnA = pointA;
newPt.m_positionWorldOnB = pointInWorld;
int insertIndex = m_manifoldPtr->getCacheEntry(newPt);
newPt.m_combinedFriction = calculateCombinedFriction(m_body0,m_body1);
newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0,m_body1);
//BP mod, store contact triangles.
newPt.m_partId0 = m_partId0;
newPt.m_partId1 = m_partId1;
newPt.m_index0 = m_index0;
newPt.m_index1 = m_index1;
///todo, check this for any side effects
if (insertIndex >= 0)
{
//const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
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
@@ -112,8 +94,16 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b
//experimental feature info, for per-triangle material etc.
btCollisionObject* obj0 = isSwapped? m_body1 : m_body0;
btCollisionObject* obj1 = isSwapped? m_body0 : m_body1;
(*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex),obj0,m_partId0,m_index0,obj1,m_partId1,m_index1);
(*gContactAddedCallback)(newPt,obj0,m_partId0,m_index0,obj1,m_partId1,m_index1);
}
if (insertIndex >= 0)
{
//const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
m_manifoldPtr->replaceContactPoint(newPt,insertIndex);
} else
{
m_manifoldPtr->AddManifoldPoint(newPt);
}
}

View File

@@ -18,12 +18,12 @@ subject to the following restrictions:
#define MANIFOLD_RESULT_H
class btCollisionObject;
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
class btPersistentManifold;
class btManifoldPoint;
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
#include "LinearMath/btTransform.h"
#include "../../LinearMath/btTransform.h"
typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1);
extern ContactAddedCallback gContactAddedCallback;
@@ -60,15 +60,6 @@ public:
m_manifoldPtr = manifoldPtr;
}
const btPersistentManifold* getPersistentManifold() const
{
return m_manifoldPtr;
}
btPersistentManifold* getPersistentManifold()
{
return m_manifoldPtr;
}
virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1)
{
m_partId0=partId0;
@@ -79,22 +70,6 @@ public:
virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth);
SIMD_FORCE_INLINE void refreshContactPoints()
{
btAssert(m_manifoldPtr);
if (!m_manifoldPtr->getNumContacts())
return;
bool isSwapped = m_manifoldPtr->getBody0() != m_body0;
if (isSwapped)
{
m_manifoldPtr->refreshContactPoints(m_rootTransB,m_rootTransA);
} else
{
m_manifoldPtr->refreshContactPoints(m_rootTransA,m_rootTransB);
}
}
};

View File

@@ -1,17 +1,3 @@
/*
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 "LinearMath/btScalar.h"
@@ -21,7 +7,7 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
//#include <stdio.h>
#include <stdio.h>
#include "LinearMath/btQuickprof.h"
btSimulationIslandManager::btSimulationIslandManager()
@@ -39,17 +25,17 @@ void btSimulationIslandManager::initUnionFind(int n)
}
void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld)
void btSimulationIslandManager::findUnions(btDispatcher* dispatcher)
{
{
btBroadphasePair* pairPtr = colWorld->getPairCache()->getOverlappingPairArrayPtr();
for (int i=0;i<colWorld->getPairCache()->getNumOverlappingPairs();i++)
for (int i=0;i<dispatcher->getNumManifolds();i++)
{
const btBroadphasePair& collisionPair = pairPtr[i];
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
const btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
//static objects (invmass btScalar(0.)) don't merge !
const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
if (((colObj0) && ((colObj0)->mergesSimulationIslands())) &&
((colObj1) && ((colObj1)->mergesSimulationIslands())))
@@ -85,7 +71,7 @@ void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld
}
// do the union find
findUnions(dispatcher,colWorld);
findUnions(dispatcher);
@@ -143,13 +129,30 @@ class btPersistentManifoldSortPredicate
};
void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects)
//
// todo: this is random access, it can be walked 'cache friendly'!
//
void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback)
{
BT_PROFILE("islandUnionFindAndQuickSort");
m_islandmanifold.resize(0);
/*if (0)
{
int maxNumManifolds = dispatcher->getNumManifolds();
btCollisionDispatcher* colDis = (btCollisionDispatcher*)dispatcher;
btPersistentManifold** manifold = colDis->getInternalManifoldPointer();
callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, 0);
return;
}
*/
BEGIN_PROFILE("islandUnionFindAndHeapSort");
//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
@@ -180,7 +183,7 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
// printf("error in island management\n");
printf("error in island management\n");
}
assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
@@ -207,7 +210,7 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
// printf("error in island management\n");
printf("error in island management\n");
}
assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
@@ -228,7 +231,7 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
// printf("error in island management\n");
printf("error in island management\n");
}
assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
@@ -244,17 +247,11 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio
}
}
btAlignedObjectArray<btPersistentManifold*> islandmanifold;
int i;
int maxNumManifolds = dispatcher->getNumManifolds();
islandmanifold.reserve(maxNumManifolds);
#define SPLIT_ISLANDS 1
#ifdef SPLIT_ISLANDS
#endif //SPLIT_ISLANDS
for (i=0;i<maxNumManifolds ;i++)
{
btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
@@ -268,52 +265,29 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio
{
//kinematic objects don't merge islands, but wake up all connected objects
if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
if (colObj0->isStaticOrKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
{
colObj1->activate();
}
if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
if (colObj1->isStaticOrKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
{
colObj0->activate();
}
#ifdef SPLIT_ISLANDS
// //filtering for response
//filtering for response
if (dispatcher->needsResponse(colObj0,colObj1))
m_islandmanifold.push_back(manifold);
#endif //SPLIT_ISLANDS
islandmanifold.push_back(manifold);
}
}
}
int numManifolds = int (islandmanifold.size());
//
// todo: this is random access, it can be walked 'cache friendly'!
//
void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback)
{
buildIslands(dispatcher,collisionObjects);
int endIslandIndex=1;
int startIslandIndex;
int numElem = getUnionFind().getNumElements();
BT_PROFILE("processIslands");
#ifndef SPLIT_ISLANDS
btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer();
callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1);
#else
// Sort manifolds, based on islands
// Sort the vector using predicate and std::sort
//std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate);
int numManifolds = int (m_islandmanifold.size());
//we should do radix sort, it it much faster (O(n) instead of O (n log2(n))
m_islandmanifold.quickSort(btPersistentManifoldSortPredicate());
islandmanifold.heapSort(btPersistentManifoldSortPredicate());
//now process all active islands (sets of manifolds for now)
@@ -322,9 +296,10 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
//int islandId;
END_PROFILE("islandUnionFindAndHeapSort");
btAlignedObjectArray<btCollisionObject*> islandBodies;
// 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)
@@ -338,7 +313,7 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
{
int i = getUnionFind().getElement(endIslandIndex).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
m_islandBodies.push_back(colObj0);
islandBodies.push_back(colObj0);
if (!colObj0->isActive())
islandSleeping = true;
}
@@ -350,12 +325,12 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
if (startManifoldIndex<numManifolds)
{
int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]);
int curIslandId = getIslandId(islandmanifold[startManifoldIndex]);
if (curIslandId == islandId)
{
startManifold = &m_islandmanifold[startManifoldIndex];
startManifold = &islandmanifold[startManifoldIndex];
for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex]));endManifoldIndex++)
for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(islandmanifold[endManifoldIndex]));endManifoldIndex++)
{
}
@@ -367,8 +342,7 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
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(&islandBodies[0],islandBodies.size(),startManifold,numIslandManifolds, islandId);
}
if (numIslandManifolds)
@@ -376,9 +350,8 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
startManifoldIndex = endManifoldIndex;
}
m_islandBodies.resize(0);
islandBodies.resize(0);
}
#endif //SPLIT_ISLANDS
}

View File

@@ -16,26 +16,18 @@ subject to the following restrictions:
#ifndef SIMULATION_ISLAND_MANAGER_H
#define SIMULATION_ISLAND_MANAGER_H
#include "BulletCollision/CollisionDispatch/btUnionFind.h"
#include "../CollisionDispatch/btUnionFind.h"
#include "btCollisionCreateFunc.h"
#include "LinearMath/btAlignedObjectArray.h"
class btCollisionObject;
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;
public:
btSimulationIslandManager();
virtual ~btSimulationIslandManager();
@@ -50,7 +42,7 @@ public:
virtual void storeIslandActivationState(btCollisionWorld* world);
void findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld);
void findUnions(btDispatcher* dispatcher);
@@ -63,8 +55,6 @@ public:
void buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback);
void buildIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects);
};
#endif //SIMULATION_ISLAND_MANAGER_H

View File

@@ -68,25 +68,18 @@ void btSphereBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,b
btScalar dist = getSphereDistance(boxObj,pOnBox,pOnSphere,sphereCenter,radius);
resultOut->setPersistentManifold(m_manifoldPtr);
if (dist < SIMD_EPSILON)
{
btVector3 normalOnSurfaceB = (pOnBox- pOnSphere).normalize();
/// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->setPersistentManifold(m_manifoldPtr);
resultOut->addContactPoint(normalOnSurfaceB,pOnBox,dist);
}
if (m_ownManifold)
{
if (m_manifoldPtr->getNumContacts())
{
resultOut->refreshContactPoints();
}
}
}
@@ -109,8 +102,8 @@ btScalar btSphereBoxCollisionAlgorithm::getSphereDistance(btCollisionObject* box
btVector3 bounds[2];
btBoxShape* boxShape= (btBoxShape*)boxObj->getCollisionShape();
bounds[0] = -boxShape->getHalfExtentsWithoutMargin();
bounds[1] = boxShape->getHalfExtentsWithoutMargin();
bounds[0] = -boxShape->getHalfExtents();
bounds[1] = boxShape->getHalfExtents();
margins = boxShape->getMargin();//also add sphereShape margin?
@@ -216,10 +209,6 @@ btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btCollisionObject*
btVector3 p0, tmp, prel, n[6], normal;
btScalar fSep = btScalar(-10000000.0), fSepThis;
// set p0 and normal to a default value to shup up GCC
p0.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
normal.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
n[0].setValue( btScalar(-1.0), btScalar(0.0), btScalar(0.0) );
n[1].setValue( btScalar(0.0), btScalar(-1.0), btScalar(0.0) );
n[2].setValue( btScalar(0.0), btScalar(0.0), btScalar(-1.0) );

View File

@@ -16,13 +16,11 @@ subject to the following restrictions:
#ifndef SPHERE_BOX_COLLISION_ALGORITHM_H
#define SPHERE_BOX_COLLISION_ALGORITHM_H
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
#include "../BroadphaseCollision/btCollisionAlgorithm.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h"
#include "../CollisionDispatch/btCollisionCreateFunc.h"
class btPersistentManifold;
#include "btCollisionDispatcher.h"
#include "LinearMath/btVector3.h"
#include "../../LinearMath/btVector3.h"
/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection.
/// Other features are frame-coherency (persistent data) and collision response.
@@ -42,14 +40,6 @@ public:
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
btScalar getSphereDistance( btCollisionObject* boxObj,btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius );
btScalar getSpherePenetration( btCollisionObject* boxObj, btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax);
@@ -58,13 +48,12 @@ public:
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm));
if (!m_swapped)
{
return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false);
return new btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false);
} else
{
return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true);
return new btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true);
}
}
};

View File

@@ -46,8 +46,6 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0
if (!m_manifoldPtr)
return;
resultOut->setPersistentManifold(m_manifoldPtr);
btSphereShape* sphere0 = (btSphereShape*)col0->getCollisionShape();
btSphereShape* sphere1 = (btSphereShape*)col1->getCollisionShape();
@@ -56,41 +54,23 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0
btScalar radius0 = sphere0->getRadius();
btScalar radius1 = sphere1->getRadius();
#ifdef CLEAR_MANIFOLD
m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting
#endif
///iff distance positive, don't generate a new contact
if ( len > (radius0+radius1))
{
#ifndef CLEAR_MANIFOLD
resultOut->refreshContactPoints();
#endif //CLEAR_MANIFOLD
return;
}
///distance (negative means penetration)
btScalar dist = len - (radius0+radius1);
btVector3 normalOnSurfaceB(1,0,0);
if (len > SIMD_EPSILON)
{
normalOnSurfaceB = diff / len;
}
btVector3 normalOnSurfaceB = diff / len;
///point on A (worldspace)
btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB;
///point on B (worldspace)
btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB;
/// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->setPersistentManifold(m_manifoldPtr);
resultOut->addContactPoint(normalOnSurfaceB,pos1,dist);
#ifndef CLEAR_MANIFOLD
resultOut->refreshContactPoints();
#endif //CLEAR_MANIFOLD
}
btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)

View File

@@ -16,11 +16,9 @@ subject to the following restrictions:
#ifndef SPHERE_SPHERE_COLLISION_ALGORITHM_H
#define SPHERE_SPHERE_COLLISION_ALGORITHM_H
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
#include "btCollisionDispatcher.h"
#include "../BroadphaseCollision/btCollisionAlgorithm.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h"
#include "../CollisionDispatch/btCollisionCreateFunc.h"
class btPersistentManifold;
/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection.
@@ -41,13 +39,6 @@ public:
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
virtual ~btSphereSphereCollisionAlgorithm();
@@ -55,8 +46,7 @@ public:
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm));
return new(mem) btSphereSphereCollisionAlgorithm(0,ci,body0,body1);
return new btSphereSphereCollisionAlgorithm(0,ci,body0,body1);
}
};

View File

@@ -48,11 +48,8 @@ void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* co
if (!m_manifoldPtr)
return;
btCollisionObject* sphereObj = m_swapped? col1 : col0;
btCollisionObject* triObj = m_swapped? col0 : col1;
btSphereShape* sphere = (btSphereShape*)sphereObj->getCollisionShape();
btTriangleShape* triangle = (btTriangleShape*)triObj->getCollisionShape();
btSphereShape* sphere = (btSphereShape*)col0->getCollisionShape();
btTriangleShape* triangle = (btTriangleShape*)col1->getCollisionShape();
/// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->setPersistentManifold(m_manifoldPtr);
@@ -60,16 +57,11 @@ void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* co
btDiscreteCollisionDetectorInterface::ClosestPointInput input;
input.m_maximumDistanceSquared = btScalar(1e30);//todo: tighter bounds
input.m_transformA = sphereObj->getWorldTransform();
input.m_transformB = triObj->getWorldTransform();
input.m_transformA = col0->getWorldTransform();
input.m_transformB = col1->getWorldTransform();
bool swapResults = m_swapped;
detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
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)

View File

@@ -16,11 +16,10 @@ subject to the following restrictions:
#ifndef SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
#define SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
#include "../BroadphaseCollision/btCollisionAlgorithm.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h"
#include "../CollisionDispatch/btCollisionCreateFunc.h"
class btPersistentManifold;
#include "btCollisionDispatcher.h"
/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection.
/// Other features are frame-coherency (persistent data) and collision response.
@@ -41,13 +40,6 @@ public:
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
virtual ~btSphereTriangleCollisionAlgorithm();
@@ -57,9 +49,7 @@ public:
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm));
return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped);
return new btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped);
}
};

View File

@@ -18,7 +18,6 @@ subject to the following restrictions:
btUnionFind::~btUnionFind()
{
Free();
@@ -77,7 +76,8 @@ void btUnionFind::sortIslands()
// Sort the vector using predicate and std::sort
//std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate);
m_elements.quickSort(btUnionFindElementSortPredicate());
//perhaps use radix sort?
m_elements.heapSort(btUnionFindElementSortPredicate());
}

View File

@@ -16,7 +16,7 @@ subject to the following restrictions:
#ifndef UNION_FIND_H
#define UNION_FIND_H
#include "LinearMath/btAlignedObjectArray.h"
#include "../../LinearMath/btAlignedObjectArray.h"
#define USE_PATH_COMPRESSION 1
@@ -46,11 +46,11 @@ class btUnionFind
void reset(int N);
SIMD_FORCE_INLINE int getNumElements() const
inline int getNumElements() const
{
return int(m_elements.size());
}
SIMD_FORCE_INLINE bool isRoot(int x) const
inline bool isRoot(int x) const
{
return (x == m_elements[x].m_id);
}

View File

@@ -15,20 +15,35 @@ subject to the following restrictions:
#include "btBoxShape.h"
btVector3 btBoxShape::getHalfExtents() const
{
return m_implicitShapeDimensions * m_localScaling;
}
//{
void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
{
btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax);
btVector3 halfExtents = getHalfExtents();
btMatrix3x3 abs_b = t.getBasis().absolute();
btPoint3 center = t.getOrigin();
btVector3 extent = btVector3(abs_b[0].dot(halfExtents),
abs_b[1].dot(halfExtents),
abs_b[2].dot(halfExtents));
extent += btVector3(getMargin(),getMargin(),getMargin());
aabbMin = center - extent;
aabbMax = center + extent;
}
void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia)
{
//btScalar margin = btScalar(0.);
btVector3 halfExtents = getHalfExtentsWithMargin();
btVector3 halfExtents = getHalfExtents();
btScalar lx=btScalar(2.)*(halfExtents.x());
btScalar ly=btScalar(2.)*(halfExtents.y());

View File

@@ -18,11 +18,11 @@ subject to the following restrictions:
#include "btPolyhedralConvexShape.h"
#include "btCollisionMargin.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "LinearMath/btPoint3.h"
#include "LinearMath/btMinMax.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h"
#include "../../LinearMath/btPoint3.h"
#include "../../LinearMath/btSimdMinMax.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.
///btBoxShape implements both a feature based (vertex/edge/plane) and implicit (getSupportingVertex) Box
class btBoxShape: public btPolyhedralConvexShape
{
@@ -31,52 +31,47 @@ class btBoxShape: public btPolyhedralConvexShape
public:
btVector3 getHalfExtentsWithMargin() const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
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
}
btVector3 getHalfExtents() const;
virtual int getShapeType() const { return BOX_SHAPE_PROXYTYPE;}
virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
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()));
btVector3 halfExtents = getHalfExtents();
btVector3 supVertex;
supVertex = btPoint3(vec.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(),
vec.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(),
vec.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z());
return supVertex;
}
SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const
virtual 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()));
btVector3 halfExtents = getHalfExtents();
btVector3 margin(getMargin(),getMargin(),getMargin());
halfExtents -= margin;
return btVector3(vec.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(),
vec.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(),
vec.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z());
}
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
{
const btVector3& halfExtents = getHalfExtentsWithoutMargin();
btVector3 halfExtents = getHalfExtents();
btVector3 margin(getMargin(),getMargin(),getMargin());
halfExtents -= margin;
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()));
supportVerticesOut[i].setValue(vec.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(),
vec.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(),
vec.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z());
}
}
@@ -84,38 +79,14 @@ public:
btBoxShape( const btVector3& boxHalfExtents)
{
btVector3 margin(getMargin(),getMargin(),getMargin());
m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
m_implicitShapeDimensions = boxHalfExtents;
};
virtual void setMargin(btScalar collisionMargin)
{
//correct the m_implicitShapeDimensions for the margin
btVector3 oldMargin(getMargin(),getMargin(),getMargin());
btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
btConvexInternalShape::setMargin(collisionMargin);
btVector3 newMargin(getMargin(),getMargin(),getMargin());
m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
}
virtual void setLocalScaling(const btVector3& scaling)
{
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 calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia);
virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i ) const
{
@@ -145,7 +116,7 @@ public:
virtual void getVertex(int i,btVector3& vtx) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
btVector3 halfExtents = getHalfExtents();
vtx = btVector3(
halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1),
@@ -156,7 +127,7 @@ public:
virtual void getPlaneEquation(btVector4& plane,int i) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
btVector3 halfExtents = getHalfExtents();
switch (i)
{
@@ -263,7 +234,7 @@ public:
virtual bool isInside(const btPoint3& pt,btScalar tolerance) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
btVector3 halfExtents = getHalfExtents();
//btScalar minDist = 2*tolerance;
@@ -279,7 +250,7 @@ public:
//debugging
virtual const char* getName()const
virtual char* getName()const
{
return "Box";
}
@@ -320,4 +291,3 @@ public:
#endif //OBB_BOX_MINKOWSKI_H

View File

@@ -18,56 +18,32 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
///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_useQuantizedAabbCompression(useQuantizedAabbCompression),
m_ownsBvh(false)
btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression)
:btTriangleMeshShape(meshInterface),m_useQuantizedAabbCompression(useQuantizedAabbCompression)
{
//construct bvh from meshInterface
#ifndef DISABLE_BVH
m_bvh = new btOptimizedBvh();
btVector3 bvhAabbMin,bvhAabbMax;
if(meshInterface->hasPremadeAabb())
{
meshInterface->getPremadeAabb(&bvhAabbMin, &bvhAabbMax);
}
else
{
meshInterface->calculateAabbBruteForce(bvhAabbMin,bvhAabbMax);
}
if (buildBvh)
{
void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
m_bvh = new (mem) btOptimizedBvh();
m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
m_ownsBvh = true;
}
meshInterface->calculateAabbBruteForce(bvhAabbMin,bvhAabbMax);
m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
#endif //DISABLE_BVH
}
btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh)
:btTriangleMeshShape(meshInterface),
m_bvh(0),
m_useQuantizedAabbCompression(useQuantizedAabbCompression),
m_ownsBvh(false)
btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax)
:btTriangleMeshShape(meshInterface),m_useQuantizedAabbCompression(useQuantizedAabbCompression)
{
//construct bvh from meshInterface
#ifndef DISABLE_BVH
if (buildBvh)
{
void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
m_bvh = new (mem) btOptimizedBvh();
m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
m_ownsBvh = true;
}
m_bvh = new btOptimizedBvh();
m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
#endif //DISABLE_BVH
@@ -82,140 +58,16 @@ void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btV
}
void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax)
void btBvhTriangleMeshShape::refitTree()
{
m_bvh->refit( m_meshInterface, aabbMin,aabbMax );
m_bvh->refit( m_meshInterface );
recalcLocalAabb();
}
btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
{
if (m_ownsBvh)
{
m_bvh->~btOptimizedBvh();
btAlignedFree(m_bvh);
}
}
void btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
{
struct MyNodeOverlapCallback : public btNodeOverlapCallback
{
btStridingMeshInterface* m_meshInterface;
btTriangleCallback* m_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;
int numverts;
PHY_ScalarType type;
int stride;
const unsigned char *indexbase;
int indexstride;
int numfaces;
PHY_ScalarType indicestype;
m_meshInterface->getLockedReadOnlyVertexIndexBase(
&vertexbase,
numverts,
type,
stride,
&indexbase,
indexstride,
numfaces,
indicestype,
nodeSubPart);
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--)
{
int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
}
/* Perform ray vs. triangle collision here */
m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
}
};
MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget);
}
void btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
{
struct MyNodeOverlapCallback : public btNodeOverlapCallback
{
btStridingMeshInterface* m_meshInterface;
btTriangleCallback* m_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;
int numverts;
PHY_ScalarType type;
int stride;
const unsigned char *indexbase;
int indexstride;
int numfaces;
PHY_ScalarType indicestype;
m_meshInterface->getLockedReadOnlyVertexIndexBase(
&vertexbase,
numverts,
type,
stride,
&indexbase,
indexstride,
numfaces,
indicestype,
nodeSubPart);
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--)
{
int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
}
/* Perform ray vs. triangle collision here */
m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
}
};
MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
delete m_bvh;
}
//perform bvh tree traversal and report overlapping triangles to 'callback'
@@ -266,14 +118,13 @@ void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,co
indicestype,
nodeSubPart);
unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride);
const btVector3& meshScaling = m_meshInterface->getScaling();
for (int j=2;j>=0;j--)
{
int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
int graphicsindex = gfxbase[j];
#ifdef DEBUG_TRIANGLE_MESH
@@ -306,37 +157,17 @@ void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,co
}
void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
{
if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
{
btTriangleMeshShape::setLocalScaling(scaling);
if (m_ownsBvh)
{
m_bvh->~btOptimizedBvh();
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();
//rebuild the bvh...
m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax);
m_ownsBvh = true;
}
if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
{
btTriangleMeshShape::setLocalScaling(scaling);
delete m_bvh;
///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work
m_bvh = new btOptimizedBvh();
//rebuild the bvh...
m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax);
}
}
void btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling)
{
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);
}
}

View File

@@ -18,55 +18,45 @@ subject to the following restrictions:
#include "btTriangleMeshShape.h"
#include "btOptimizedBvh.h"
#include "LinearMath/btAlignedAllocator.h"
///The btBvhTriangleMeshShape is a static-triangle mesh shape with 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.
///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.
ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape
{
btOptimizedBvh* m_bvh;
bool m_useQuantizedAabbCompression;
bool m_ownsBvh;
bool m_pad[11];////need padding due to alignment
bool m_pad[12];////need padding due to alignment
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btBvhTriangleMeshShape() :btTriangleMeshShape(0),m_bvh(0),m_ownsBvh(false) {};
btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true);
btBvhTriangleMeshShape() :btTriangleMeshShape(0) {};
btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression);
///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);
virtual ~btBvhTriangleMeshShape();
bool getOwnsBvh () const
{
return m_ownsBvh;
}
/*
virtual int getShapeType() const
{
return TRIANGLE_MESH_SHAPE_PROXYTYPE;
}
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 refitTree(const btVector3& aabbMin,const btVector3& aabbMax);
void refitTree();
///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);
//debugging
virtual const char* getName()const {return "BVHTRIANGLEMESH";}
virtual char* getName()const {return "BVHTRIANGLEMESH";}
virtual void setLocalScaling(const btVector3& scaling);
@@ -75,10 +65,6 @@ public:
{
return m_bvh;
}
void setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& localScaling=btVector3(1,1,1));
bool usesQuantizedAabbCompression() const
{
return m_useQuantizedAabbCompression;

View File

@@ -21,7 +21,6 @@ subject to the following restrictions:
btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height)
{
m_upAxis = 1;
m_implicitShapeDimensions.setValue(radius,0.5f*height,radius);
}
@@ -51,9 +50,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height)
{
btVector3 pos(0,0,0);
pos[getUpAxis()] = getHalfHeight();
btVector3 pos(0,getHalfHeight(),0);
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx);
if (newDot > maxDot)
@@ -63,9 +60,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height)
}
}
{
btVector3 pos(0,0,0);
pos[getUpAxis()] = -getHalfHeight();
btVector3 pos(0,-getHalfHeight(),0);
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx);
if (newDot > maxDot)
@@ -93,8 +88,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height)
btVector3 vtx;
btScalar newDot;
{
btVector3 pos(0,0,0);
pos[getUpAxis()] = getHalfHeight();
btVector3 pos(0,getHalfHeight(),0);
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx);
if (newDot > maxDot)
@@ -104,8 +98,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height)
}
}
{
btVector3 pos(0,0,0);
pos[getUpAxis()] = -getHalfHeight();
btVector3 pos(0,-getHalfHeight(),0);
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx);
if (newDot > maxDot)
@@ -119,7 +112,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height)
}
void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia)
{
//as an approximation, take the inertia of the box that bounds the spheres
@@ -129,8 +122,7 @@ void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) con
btScalar radius = getRadius();
btVector3 halfExtents(radius,radius,radius);
halfExtents[getUpAxis()]+=getHalfHeight();
btVector3 halfExtents(radius,radius+getHalfHeight(),radius);
btScalar margin = CONVEX_DISTANCE_MARGIN;
@@ -148,22 +140,6 @@ void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) con
}
btCapsuleShapeX::btCapsuleShapeX(btScalar radius,btScalar height)
{
m_upAxis = 0;
m_implicitShapeDimensions.setValue(0.5f*height, radius,radius);
}
btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius,btScalar height)
{
m_upAxis = 2;
m_implicitShapeDimensions.setValue(radius,radius,0.5f*height);
}

View File

@@ -16,27 +16,20 @@ subject to the following restrictions:
#ifndef BT_CAPSULE_SHAPE_H
#define BT_CAPSULE_SHAPE_H
#include "btConvexInternalShape.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "btConvexShape.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types
///The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned around the X axis and btCapsuleShapeZ around the Z axis.
///The total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
///The btCapsuleShape is a convex hull of two spheres. The btMultiSphereShape is a more general collision shape that takes the convex hull of multiple sphere, so it can also represent a capsule when just using two spheres.
class btCapsuleShape : public btConvexInternalShape
///btCapsuleShape represents a capsule around the Y axis
///A more general solution that can represent capsules is the btMultiSphereShape
class btCapsuleShape : public btConvexShape
{
protected:
int m_upAxis;
protected:
///only used for btCapsuleShapeZ and btCapsuleShapeX subclasses.
btCapsuleShape() {};
public:
btCapsuleShape(btScalar radius,btScalar height);
///CollisionShape Interface
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia);
/// btConvexShape Interface
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
@@ -45,76 +38,23 @@ public:
virtual int getShapeType() const { return CAPSULE_SHAPE_PROXYTYPE; }
virtual void getAabb (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
btVector3 halfExtents(getRadius(),getRadius(),getRadius());
halfExtents[m_upAxis] = getRadius() + getHalfHeight();
halfExtents += btVector3(getMargin(),getMargin(),getMargin());
btMatrix3x3 abs_b = t.getBasis().absolute();
btPoint3 center = t.getOrigin();
btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));
aabbMin = center - extent;
aabbMax = center + extent;
}
virtual const char* getName()const
virtual char* getName()const
{
return "CapsuleShape";
}
int getUpAxis() const
{
return m_upAxis;
}
btScalar getRadius() const
{
int radiusAxis = (m_upAxis+2)%3;
return m_implicitShapeDimensions[radiusAxis];
return m_implicitShapeDimensions.getX();
}
btScalar getHalfHeight() const
{
return m_implicitShapeDimensions[m_upAxis];
return m_implicitShapeDimensions.getY();
}
};
///btCapsuleShapeX represents a capsule around the Z axis
///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
class btCapsuleShapeX : public btCapsuleShape
{
public:
btCapsuleShapeX(btScalar radius,btScalar height);
//debugging
virtual const char* getName()const
{
return "CapsuleX";
}
};
///btCapsuleShapeZ represents a capsule around the Z axis
///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
class btCapsuleShapeZ : public btCapsuleShape
{
public:
btCapsuleShapeZ(btScalar radius,btScalar height);
//debugging
virtual const char* getName()const
{
return "CapsuleZ";
}
};
#endif //BT_CAPSULE_SHAPE_H

View File

@@ -21,12 +21,7 @@ subject to the following restrictions:
can be used by probes that are checking whether the
library is actually installed.
*/
extern "C"
{
void btBulletCollisionProbe ();
void btBulletCollisionProbe () {}
}
extern "C" void btBulletCollisionProbe () {}
@@ -51,7 +46,7 @@ btScalar btCollisionShape::getAngularMotionDisc() const
return disc;
}
void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const
void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax)
{
//start with static aabb
getAabb(curTrans,temporalAabbMin,temporalAabbMax);

View File

@@ -16,21 +16,18 @@ subject to the following restrictions:
#ifndef COLLISION_SHAPE_H
#define COLLISION_SHAPE_H
#include "LinearMath/btTransform.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btMatrix3x3.h"
#include "LinearMath/btPoint3.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" //for the shape types
#include "../../LinearMath/btTransform.h"
#include "../../LinearMath/btVector3.h"
#include "../../LinearMath/btMatrix3x3.h"
#include "../../LinearMath/btPoint3.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" //for the shape types
///The btCollisionShape class provides an interface for collision shapes that can be shared among btCollisionObjects.
///btCollisionShape provides interface for collision shapes that can be shared among btCollisionObjects.
class btCollisionShape
{
void* m_userPointer;
public:
btCollisionShape() : m_userPointer(0)
btCollisionShape()
{
}
virtual ~btCollisionShape()
@@ -48,30 +45,30 @@ public:
///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep)
///result is conservative
void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const;
void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax);
#ifndef __SPU__
SIMD_FORCE_INLINE bool isPolyhedral() const
inline bool isPolyhedral() const
{
return btBroadphaseProxy::isPolyhedral(getShapeType());
}
SIMD_FORCE_INLINE bool isConvex() const
inline bool isConvex() const
{
return btBroadphaseProxy::isConvex(getShapeType());
}
SIMD_FORCE_INLINE bool isConcave() const
inline bool isConcave() const
{
return btBroadphaseProxy::isConcave(getShapeType());
}
SIMD_FORCE_INLINE bool isCompound() const
inline bool isCompound() const
{
return btBroadphaseProxy::isCompound(getShapeType());
}
///isInfinite is used to catch simulation error (aabb check)
SIMD_FORCE_INLINE bool isInfinite() const
inline bool isInfinite() const
{
return btBroadphaseProxy::isInfinite(getShapeType());
}
@@ -79,11 +76,11 @@ public:
virtual int getShapeType() const=0;
virtual void setLocalScaling(const btVector3& scaling) =0;
virtual const btVector3& getLocalScaling() const =0;
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const = 0;
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) = 0;
//debugging support
virtual const char* getName()const =0 ;
virtual char* getName()const =0 ;
#endif //__SPU__
@@ -91,18 +88,6 @@ public:
virtual void setMargin(btScalar margin) = 0;
virtual btScalar getMargin() const = 0;
///optional user data pointer
void setUserPointer(void* userPtr)
{
m_userPointer = userPtr;
}
void* getUserPointer() const
{
return m_userPointer;
}
};
#endif //COLLISION_SHAPE_H

View File

@@ -14,42 +14,29 @@ subject to the following restrictions:
*/
#include "btCompoundShape.h"
#include "btCollisionShape.h"
#include "BulletCollision/BroadphaseCollision/btDbvt.h"
btCompoundShape::btCompoundShape()
:m_localAabbMin(btScalar(1e30),btScalar(1e30),btScalar(1e30)),
m_localAabbMax(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)),
m_aabbTree(0),
m_collisionMargin(btScalar(0.)),
m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)),
m_dynamicAabbTree(0)
m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.))
{
void* mem = btAlignedAlloc(sizeof(btDbvt),16);
m_dynamicAabbTree = new(mem) btDbvt();
btAssert(mem==m_dynamicAabbTree);
}
btCompoundShape::~btCompoundShape()
{
if (m_dynamicAabbTree)
{
m_dynamicAabbTree->~btDbvt();
btAlignedFree(m_dynamicAabbTree);
}
}
void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape)
{
//m_childTransforms.push_back(localTransform);
//m_childShapes.push_back(shape);
btCompoundShapeChild child;
child.m_transform = localTransform;
child.m_childShape = shape;
child.m_childShapeType = shape->getShapeType();
child.m_childMargin = shape->getMargin();
m_children.push_back(child);
m_childTransforms.push_back(localTransform);
m_childShapes.push_back(shape);
//extend the local aabbMin/aabbMax
btVector3 localAabbMin,localAabbMax;
@@ -66,100 +53,39 @@ void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisio
}
}
if (m_dynamicAabbTree)
{
const btDbvtVolume bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
int index = m_children.size()-1;
child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index);
}
}
void btCompoundShape::removeChildShapeByIndex(int childShapeIndex)
{
btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size());
if (m_dynamicAabbTree)
{
m_dynamicAabbTree->remove(m_children[childShapeIndex].m_node);
}
m_children.swap(childShapeIndex,m_children.size()-1);
m_children.pop_back();
}
void btCompoundShape::removeChildShape(btCollisionShape* shape)
{
// Find the children containing the shape specified, and remove those children.
//note: there might be multiple children using the same shape!
for(int i = m_children.size()-1; i >= 0 ; i--)
{
if(m_children[i].m_childShape == shape)
{
m_children.swap(i,m_children.size()-1);
m_children.pop_back();
//remove it from the m_dynamicAabbTree too
//m_dynamicAabbTree->remove(m_aabbProxies[i]);
//m_aabbProxies.swap(i,m_children.size()-1);
//m_aabbProxies.pop_back();
}
}
recalculateLocalAabb();
}
void btCompoundShape::recalculateLocalAabb()
{
// Recalculate the local aabb
// Brute force, it iterates over all the shapes left.
m_localAabbMin = btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30));
m_localAabbMax = btVector3(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30));
//extend the local aabbMin/aabbMax
for (int j = 0; j < m_children.size(); j++)
{
btVector3 localAabbMin,localAabbMax;
m_children[j].m_childShape->getAabb(m_children[j].m_transform, localAabbMin, localAabbMax);
for (int i=0;i<3;i++)
{
if (m_localAabbMin[i] > localAabbMin[i])
m_localAabbMin[i] = localAabbMin[i];
if (m_localAabbMax[i] < localAabbMax[i])
m_localAabbMax[i] = localAabbMax[i];
}
}
}
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
{
btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin);
localHalfExtents += btVector3(getMargin(),getMargin(),getMargin());
btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin);
btMatrix3x3 abs_b = trans.getBasis().absolute();
btPoint3 center = trans(localCenter);
btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
abs_b[1].dot(localHalfExtents),
abs_b[2].dot(localHalfExtents));
aabbMin = center-extent;
aabbMax = center+extent;
abs_b[1].dot(localHalfExtents),
abs_b[2].dot(localHalfExtents));
extent += btVector3(getMargin(),getMargin(),getMargin());
aabbMin = center - extent;
aabbMax = center + extent;
}
void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia)
{
//approximation: take the inertia from the aabb for now
btTransform ident;
ident.setIdentity();
btVector3 aabbMin,aabbMax;
getAabb(ident,aabbMin,aabbMax);
btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
btScalar lx=btScalar(2.)*(halfExtents.x());
btScalar ly=btScalar(2.)*(halfExtents.y());
btScalar lz=btScalar(2.)*(halfExtents.z());
@@ -170,62 +96,5 @@ void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) co
}
void btCompoundShape::calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const
{
int n = m_children.size();
btScalar totalMass = 0;
btVector3 center(0, 0, 0);
for (int k = 0; k < n; k++)
{
center += m_children[k].m_transform.getOrigin() * masses[k];
totalMass += masses[k];
}
center /= totalMass;
principal.setOrigin(center);
btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0);
for (int k = 0; k < n; k++)
{
btVector3 i;
m_children[k].m_childShape->calculateLocalInertia(masses[k], i);
const btTransform& t = m_children[k].m_transform;
btVector3 o = t.getOrigin() - center;
//compute inertia tensor in coordinate system of compound shape
btMatrix3x3 j = t.getBasis().transpose();
j[0] *= i[0];
j[1] *= i[1];
j[2] *= i[2];
j = t.getBasis() * j;
//add inertia tensor
tensor[0] += j[0];
tensor[1] += j[1];
tensor[2] += j[2];
//compute inertia tensor of pointmass at o
btScalar o2 = o.length2();
j[0].setValue(o2, 0, 0);
j[1].setValue(0, o2, 0);
j[2].setValue(0, 0, o2);
j[0] += o * -o.x();
j[1] += o * -o.y();
j[2] += o * -o.z();
//add inertia tensor of pointmass
tensor[0] += masses[k] * j[0];
tensor[1] += masses[k] * j[1];
tensor[2] += masses[k] * j[2];
}
tensor.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
inertia.setValue(tensor[0][0], tensor[1][1], tensor[2][2]);
}

View File

@@ -18,97 +18,58 @@ subject to the following restrictions:
#include "btCollisionShape.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btTransform.h"
#include "LinearMath/btMatrix3x3.h"
#include "../../LinearMath/btVector3.h"
#include "../../LinearMath/btTransform.h"
#include "../../LinearMath/btMatrix3x3.h"
#include "btCollisionMargin.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "../../LinearMath/btAlignedObjectArray.h"
//class btOptimizedBvh;
struct btDbvt;
ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild
{
BT_DECLARE_ALIGNED_ALLOCATOR();
btTransform m_transform;
btCollisionShape* m_childShape;
int m_childShapeType;
btScalar m_childMargin;
struct btDbvtNode* m_node;
};
SIMD_FORCE_INLINE bool operator==(const btCompoundShapeChild& c1, const btCompoundShapeChild& c2)
{
return ( c1.m_transform == c2.m_transform &&
c1.m_childShape == c2.m_childShape &&
c1.m_childShapeType == c2.m_childShapeType &&
c1.m_childMargin == c2.m_childMargin );
}
class btOptimizedBvh;
/// btCompoundShape allows to store multiple other btCollisionShapes
/// This allows for moving concave collision objects. This is more general then the static concave btBvhTriangleMeshShape.
ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape
/// This allows for concave collision objects. This is more general then the Static Concave btTriangleMeshShape.
class btCompoundShape : public btCollisionShape
{
//btAlignedObjectArray<btTransform> m_childTransforms;
//btAlignedObjectArray<btCollisionShape*> m_childShapes;
btAlignedObjectArray<btCompoundShapeChild> m_children;
btAlignedObjectArray<btTransform> m_childTransforms;
btAlignedObjectArray<btCollisionShape*> m_childShapes;
btVector3 m_localAabbMin;
btVector3 m_localAabbMax;
//btOptimizedBvh* m_aabbTree;
btDbvt* m_dynamicAabbTree;
btOptimizedBvh* m_aabbTree;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btCompoundShape();
virtual ~btCompoundShape();
void addChildShape(const btTransform& localTransform,btCollisionShape* shape);
/// Remove all children shapes that contain the specified shape
virtual void removeChildShape(btCollisionShape* shape);
void removeChildShapeByIndex(int childShapeindex);
int getNumChildShapes() const
{
return int (m_children.size());
return int (m_childShapes.size());
}
btCollisionShape* getChildShape(int index)
{
return m_children[index].m_childShape;
return m_childShapes[index];
}
const btCollisionShape* getChildShape(int index) const
{
return m_children[index].m_childShape;
return m_childShapes[index];
}
btTransform getChildTransform(int index)
btTransform& getChildTransform(int index)
{
return m_children[index].m_transform;
return m_childTransforms[index];
}
const btTransform getChildTransform(int index) const
const btTransform& getChildTransform(int index) const
{
return m_children[index].m_transform;
}
btCompoundShapeChild* getChildList()
{
return &m_children[0];
return m_childTransforms[index];
}
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
/** Re-calculate the local Aabb. Is called at the end of removeChildShapes.
Use this yourself if you modify the children or their transforms. */
virtual void recalculateLocalAabb();
virtual void setLocalScaling(const btVector3& scaling)
{
@@ -119,8 +80,8 @@ public:
return m_localScaling;
}
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia);
virtual int getShapeType() const { return COMPOUND_SHAPE_PROXYTYPE;}
virtual void setMargin(btScalar margin)
@@ -131,7 +92,7 @@ public:
{
return m_collisionMargin;
}
virtual const char* getName()const
virtual char* getName()const
{
return "Compound";
}
@@ -139,19 +100,11 @@ public:
//this is optional, but should make collision queries faster, by culling non-overlapping nodes
void createAabbTreeFromChildren();
btDbvt* getDynamicAabbTree()
const btOptimizedBvh* getAabbTree() const
{
return m_dynamicAabbTree;
return m_aabbTree;
}
///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia
///and the center of mass to the current coordinate system. "masses" points to an array of masses of the children. The resulting transform
///"principal" has to be applied inversely to all children transforms in order for the local coordinate system of the compound
///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform
///of the collision object by the principal transform.
void calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const;
private:
btScalar m_collisionMargin;
protected:

View File

@@ -17,12 +17,12 @@ subject to the following restrictions:
#define CONCAVE_SHAPE_H
#include "btCollisionShape.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "btTriangleCallback.h"
///The btConcaveShape class provides an interface for non-moving (static) concave shapes.
///It has been implemented by the btStaticPlaneShape, btBvhTriangleMeshShape and btHeightfieldTerrainShape.
///Concave shape proves an interface concave shapes that can produce triangles that overlapping a given AABB.
///Static triangle mesh, infinite plane, height field/landscapes are example that implement this interface.
class btConcaveShape : public btCollisionShape
{
protected:

View File

@@ -16,11 +16,11 @@ subject to the following restrictions:
#ifndef CONE_MINKOWSKI_H
#define CONE_MINKOWSKI_H
#include "btConvexInternalShape.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "btConvexShape.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types
///The btConeShape implements a cone shape primitive, centered around the origin and aligned with the Y axis. The btConeShapeX is aligned around the X axis and btConeShapeZ around the Z axis.
class btConeShape : public btConvexInternalShape
///btConeShape implements a Cone shape, around the Y axis
class btConeShape : public btConvexShape
{
@@ -42,7 +42,7 @@ public:
btScalar getHeight() const { return m_height;}
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia)
{
btTransform identity;
identity.setIdentity();
@@ -72,7 +72,7 @@ public:
virtual int getShapeType() const { return CONE_SHAPE_PROXYTYPE; }
virtual const char* getName()const
virtual char* getName()const
{
return "Cone";
}

View File

@@ -36,13 +36,6 @@ btConvexHullShape ::btConvexHullShape (const btScalar* points,int numPoints,int
}
void btConvexHullShape::setLocalScaling(const btVector3& scaling)
{
m_localScaling = scaling;
recalcLocalAabb();
}
void btConvexHullShape::addPoint(const btPoint3& point)
{
m_points.push_back(point);

View File

@@ -17,17 +17,18 @@ subject to the following restrictions:
#define CONVEX_HULL_SHAPE_H
#include "btPolyhedralConvexShape.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "LinearMath/btAlignedObjectArray.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "../../LinearMath/btAlignedObjectArray.h"
///The btConvexHullShape implements an implicit convex hull of an array of vertices.
///Bullet provides a general and fast collision detector for convex shapes based on GJK and EPA using localGetSupportingVertex.
///ConvexHullShape implements an implicit (getSupportingVertex) Convex Hull of a Point Cloud (vertices)
///No connectivity is needed. localGetSupportingVertex iterates linearly though all vertices.
///on modern hardware, due to cache coherency this isn't that bad. Complex algorithms tend to trash the cash.
///(memory is much slower then the cpu)
ATTRIBUTE_ALIGNED16(class) btConvexHullShape : public btPolyhedralConvexShape
{
btAlignedObjectArray<btPoint3> m_points;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory.
@@ -42,12 +43,7 @@ public:
return &m_points[0];
}
const btPoint3* getPoints() const
{
return &m_points[0];
}
int getNumPoints() const
int getNumPoints()
{
return m_points.size();
}
@@ -60,7 +56,7 @@ public:
virtual int getShapeType()const { return CONVEX_HULL_SHAPE_PROXYTYPE; }
//debugging
virtual const char* getName()const {return "Convex";}
virtual char* getName()const {return "Convex";}
virtual int getNumVertices() const;
@@ -71,8 +67,7 @@ public:
virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i ) const;
virtual bool isInside(const btPoint3& pt,btScalar tolerance) const;
///in case we receive negative scaling
virtual void setLocalScaling(const btVector3& scaling);
};

View File

@@ -1,78 +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 "btConvexInternalShape.h"
btConvexInternalShape::btConvexInternalShape()
: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)),
m_collisionMargin(CONVEX_DISTANCE_MARGIN)
{
}
void btConvexInternalShape::setLocalScaling(const btVector3& scaling)
{
m_localScaling = scaling.absolute();
}
void btConvexInternalShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const
{
btScalar margin = getMargin();
for (int i=0;i<3;i++)
{
btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
vec[i] = btScalar(1.);
btVector3 sv = localGetSupportingVertex(vec*trans.getBasis());
btVector3 tmp = trans(sv);
maxAabb[i] = tmp[i]+margin;
vec[i] = btScalar(-1.);
tmp = trans(localGetSupportingVertex(vec*trans.getBasis()));
minAabb[i] = tmp[i]-margin;
}
};
btVector3 btConvexInternalShape::localGetSupportingVertex(const btVector3& vec)const
{
#ifndef __SPU__
btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
if ( getMargin()!=btScalar(0.) )
{
btVector3 vecnorm = vec;
if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
{
vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
}
vecnorm.normalize();
supVertex+= getMargin() * vecnorm;
}
return supVertex;
#else
return btVector3(0,0,0);
#endif //__SPU__
}

View File

@@ -1,98 +0,0 @@
#ifndef BT_CONVEX_INTERNAL_SHAPE_H
#define BT_CONVEX_INTERNAL_SHAPE_H
#include "btConvexShape.h"
///The btConvexInternalShape is an internal base class, shared by most convex shape implementations.
class btConvexInternalShape : public btConvexShape
{
protected:
//local scaling. collisionMargin is not scaled !
btVector3 m_localScaling;
btVector3 m_implicitShapeDimensions;
btScalar m_collisionMargin;
btScalar m_padding;
public:
btConvexInternalShape();
virtual ~btConvexInternalShape()
{
}
virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
#ifndef __SPU__
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const= 0;
//notice that the vectors should be unit length
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0;
#endif //#ifndef __SPU__
const btVector3& getImplicitShapeDimensions() const
{
return m_implicitShapeDimensions;
}
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
{
getAabbSlow(t,aabbMin,aabbMax);
}
virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
virtual void setLocalScaling(const btVector3& scaling);
virtual const btVector3& getLocalScaling() const
{
return m_localScaling;
}
const btVector3& getLocalScalingNV() const
{
return m_localScaling;
}
virtual void setMargin(btScalar margin)
{
m_collisionMargin = margin;
}
virtual btScalar getMargin() const
{
return m_collisionMargin;
}
btScalar getMarginNV() const
{
return m_collisionMargin;
}
virtual int getNumPreferredPenetrationDirections() const
{
return 0;
}
virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
{
(void)penetrationVector;
(void)index;
btAssert(0);
}
};
#endif //BT_CONVEX_INTERNAL_SHAPE_H

View File

@@ -16,3 +16,62 @@ subject to the following restrictions:
#include "btConvexShape.h"
btConvexShape::btConvexShape()
: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)),
m_collisionMargin(CONVEX_DISTANCE_MARGIN)
{
}
void btConvexShape::setLocalScaling(const btVector3& scaling)
{
m_localScaling = scaling;
}
void btConvexShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const
{
btScalar margin = getMargin();
for (int i=0;i<3;i++)
{
btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
vec[i] = btScalar(1.);
btVector3 sv = localGetSupportingVertex(vec*trans.getBasis());
btVector3 tmp = trans(sv);
maxAabb[i] = tmp[i]+margin;
vec[i] = btScalar(-1.);
tmp = trans(localGetSupportingVertex(vec*trans.getBasis()));
minAabb[i] = tmp[i]-margin;
}
};
btVector3 btConvexShape::localGetSupportingVertex(const btVector3& vec)const
{
#ifndef __SPU__
btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
if ( getMargin()!=btScalar(0.) )
{
btVector3 vecnorm = vec;
if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
{
vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
}
vecnorm.normalize();
supVertex+= getMargin() * vecnorm;
}
return supVertex;
#else
return btVector3(0,0,0);
#endif //__SPU__
}

View File

@@ -18,25 +18,37 @@ subject to the following restrictions:
#include "btCollisionShape.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btTransform.h"
#include "LinearMath/btMatrix3x3.h"
#include "../../LinearMath/btVector3.h"
#include "../../LinearMath/btTransform.h"
#include "../../LinearMath/btMatrix3x3.h"
#include "btCollisionMargin.h"
#include "LinearMath/btAlignedAllocator.h"
//todo: get rid of this btConvexCastResult thing!
struct btConvexCastResult;
#define MAX_PREFERRED_PENETRATION_DIRECTIONS 10
/// The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape, btConvexHullShape etc.
/// It describes general convex shapes using the localGetSupportingVertex interface, used by collision detectors such as btGjkPairDetector.
/// btConvexShape is an abstract shape interface.
/// The explicit part provides plane-equations, the implicit part provides GetClosestPoint interface.
/// used in combination with GJK or btConvexCast
ATTRIBUTE_ALIGNED16(class) btConvexShape : public btCollisionShape
{
protected:
//local scaling. collisionMargin is not scaled !
btVector3 m_localScaling;
btVector3 m_implicitShapeDimensions;
btScalar m_collisionMargin;
btScalar m_padding[2];
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btConvexShape();
virtual ~btConvexShape()
{
@@ -44,7 +56,7 @@ public:
}
virtual btVector3 localGetSupportingVertex(const btVector3& vec)const =0;
virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
#ifndef __SPU__
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const= 0;
@@ -52,24 +64,63 @@ public:
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0;
#endif //#ifndef __SPU__
const btVector3& getImplicitShapeDimensions() const
{
return m_implicitShapeDimensions;
}
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0;
void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
{
getAabbSlow(t,aabbMin,aabbMax);
}
virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0;
virtual void setLocalScaling(const btVector3& scaling) =0;
virtual const btVector3& getLocalScaling() const =0;
virtual void setMargin(btScalar margin)=0;
virtual btScalar getMargin() const=0;
virtual int getNumPreferredPenetrationDirections() const=0;
virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const=0;
virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
};
virtual void setLocalScaling(const btVector3& scaling);
virtual const btVector3& getLocalScaling() const
{
return m_localScaling;
}
const btVector3& getLocalScalingNV() const
{
return m_localScaling;
}
virtual void setMargin(btScalar margin)
{
m_collisionMargin = margin;
}
virtual btScalar getMargin() const
{
return m_collisionMargin;
}
btScalar getMarginNV() const
{
return m_collisionMargin;
}
virtual int getNumPreferredPenetrationDirections() const
{
return 0;
}
virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
{
(void)penetrationVector;
(void)index;
btAssert(0);
}
}
;

View File

@@ -19,11 +19,10 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface, bool calcAabb)
btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface)
:m_stridingMesh(meshInterface)
{
if ( calcAabb )
recalcLocalAabb();
recalcLocalAabb();
}
@@ -204,113 +203,3 @@ const btVector3& btConvexTriangleMeshShape::getLocalScaling() const
{
return m_stridingMesh->getScaling();
}
void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const
{
class CenterCallback: public btInternalTriangleIndexCallback
{
bool first;
btVector3 ref;
btVector3 sum;
btScalar volume;
public:
CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0)
{
}
virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
{
(void) triangleIndex;
(void) partId;
if (first)
{
ref = triangle[0];
first = false;
}
else
{
btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref));
sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref));
volume += vol;
}
}
btVector3 getCenter()
{
return (volume > 0) ? sum / volume : ref;
}
btScalar getVolume()
{
return volume * btScalar(1. / 6);
}
};
class InertiaCallback: public btInternalTriangleIndexCallback
{
btMatrix3x3 sum;
btVector3 center;
public:
InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center)
{
}
virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
{
(void) triangleIndex;
(void) partId;
btMatrix3x3 i;
btVector3 a = triangle[0] - center;
btVector3 b = triangle[1] - center;
btVector3 c = triangle[2] - center;
btVector3 abc = a + b + c;
btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6);
for (int j = 0; j < 3; j++)
{
for (int k = 0; k <= j; k++)
{
i[j][k] = i[k][j] = volNeg * (center[j] * center[k]
+ btScalar(0.25) * (center[j] * abc[k] + center[k] * abc[j])
+ btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k])
+ btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j]));
}
}
btScalar i00 = -i[0][0];
btScalar i11 = -i[1][1];
btScalar i22 = -i[2][2];
i[0][0] = i11 + i22;
i[1][1] = i22 + i00;
i[2][2] = i00 + i11;
sum[0] += i[0];
sum[1] += i[1];
sum[2] += i[2];
}
btMatrix3x3& getInertia()
{
return sum;
}
};
CenterCallback centerCallback;
btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30));
m_stridingMesh->InternalProcessAllTriangles(&centerCallback, -aabbMax, aabbMax);
btVector3 center = centerCallback.getCenter();
principal.setOrigin(center);
volume = centerCallback.getVolume();
InertiaCallback inertiaCallback(center);
m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax);
btMatrix3x3& i = inertiaCallback.getInertia();
i.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
inertia.setValue(i[0][0], i[1][1], i[2][2]);
inertia /= volume;
}

View File

@@ -3,24 +3,20 @@
#include "btPolyhedralConvexShape.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types
/// The btConvexTriangleMeshShape is a convex hull of a triangle mesh, but the performance is not as good as btConvexHullShape.
/// A small benefit of this class is that it uses the btStridingMeshInterface, so you can avoid the duplication of the triangle mesh data. Nevertheless, most users should use the much better performing btConvexHullShape instead.
/// btConvexTriangleMeshShape is a convex hull of a triangle mesh. If you just have a point cloud, you can use btConvexHullShape instead.
/// It uses the btStridingMeshInterface instead of a point cloud. This can avoid the duplication of the triangle mesh data.
class btConvexTriangleMeshShape : public btPolyhedralConvexShape
{
class btStridingMeshInterface* m_stridingMesh;
public:
btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface, bool calcAabb = true);
btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface);
class btStridingMeshInterface* getMeshInterface()
{
return m_stridingMesh;
}
const class btStridingMeshInterface* getMeshInterface() const
class btStridingMeshInterface* getStridingMesh()
{
return m_stridingMesh;
}
@@ -32,7 +28,7 @@ public:
virtual int getShapeType()const { return CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE; }
//debugging
virtual const char* getName()const {return "ConvexTrimesh";}
virtual char* getName()const {return "ConvexTrimesh";}
virtual int getNumVertices() const;
virtual int getNumEdges() const;
@@ -46,13 +42,6 @@ public:
virtual void setLocalScaling(const btVector3& scaling);
virtual const btVector3& getLocalScaling() const;
///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia
///and the center of mass to the current coordinate system. A mass of 1 is assumed, for other masses just multiply the computed "inertia"
///by the mass. The resulting transform "principal" has to be applied inversely to the mesh in order for the local coordinate system of the
///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform
///of the collision object by the principal transform. This method also computes the volume of the convex mesh.
void calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const;
};
@@ -60,4 +49,3 @@ public:
#endif //CONVEX_TRIANGLEMESH_SHAPE_H

View File

@@ -45,7 +45,7 @@ void btCylinderShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3&
}
SIMD_FORCE_INLINE btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v)
inline btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v)
{
const int cylinderUpAxis = 0;
const int XX = 1;
@@ -163,24 +163,24 @@ const int ZZ = 1;
btVector3 btCylinderShapeX::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
{
return CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vec);
return CylinderLocalSupportX(getHalfExtents(),vec);
}
btVector3 btCylinderShapeZ::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
{
return CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vec);
return CylinderLocalSupportZ(getHalfExtents(),vec);
}
btVector3 btCylinderShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
{
return CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vec);
return CylinderLocalSupportY(getHalfExtents(),vec);
}
void btCylinderShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
{
for (int i=0;i<numVectors;i++)
{
supportVerticesOut[i] = CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vectors[i]);
supportVerticesOut[i] = CylinderLocalSupportY(getHalfExtents(),vectors[i]);
}
}
@@ -188,7 +188,7 @@ void btCylinderShapeZ::batchedUnitVectorGetSupportingVertexWithoutMargin(const b
{
for (int i=0;i<numVectors;i++)
{
supportVerticesOut[i] = CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vectors[i]);
supportVerticesOut[i] = CylinderLocalSupportZ(getHalfExtents(),vectors[i]);
}
}
@@ -199,7 +199,7 @@ void btCylinderShapeX::batchedUnitVectorGetSupportingVertexWithoutMargin(const b
{
for (int i=0;i<numVectors;i++)
{
supportVerticesOut[i] = CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vectors[i]);
supportVerticesOut[i] = CylinderLocalSupportX(getHalfExtents(),vectors[i]);
}
}

View File

@@ -17,10 +17,10 @@ subject to the following restrictions:
#define CYLINDER_MINKOWSKI_H
#include "btBoxShape.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "LinearMath/btVector3.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "../../LinearMath/btVector3.h"
/// The btCylinderShape class implements a cylinder shape primitive, centered around the origin. Its central axis aligned with the Y axis. btCylinderShapeX is aligned with the X axis and btCylinderShapeZ around the Z axis.
/// implements cylinder shape interface
class btCylinderShape : public btBoxShape
{
@@ -60,7 +60,7 @@ public:
//use box inertia
// virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
// virtual void calculateLocalInertia(btScalar mass,btVector3& inertia);
virtual int getShapeType() const
{
@@ -74,11 +74,11 @@ public:
virtual btScalar getRadius() const
{
return getHalfExtentsWithMargin().getX();
return getHalfExtents().getX();
}
//debugging
virtual const char* getName()const
virtual char* getName()const
{
return "CylinderY";
}
@@ -96,14 +96,14 @@ public:
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
//debugging
virtual const char* getName()const
virtual char* getName()const
{
return "CylinderX";
}
virtual btScalar getRadius() const
{
return getHalfExtentsWithMargin().getY();
return getHalfExtents().getY();
}
};
@@ -121,14 +121,14 @@ public:
return 2;
}
//debugging
virtual const char* getName()const
virtual char* getName()const
{
return "CylinderZ";
}
virtual btScalar getRadius() const
{
return getHalfExtentsWithMargin().getX();
return getHalfExtents().getX();
}
};

View File

@@ -40,7 +40,7 @@ void btEmptyShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aa
}
void btEmptyShape::calculateLocalInertia(btScalar ,btVector3& ) const
void btEmptyShape::calculateLocalInertia(btScalar ,btVector3& )
{
btAssert(0);
}

View File

@@ -18,16 +18,16 @@ subject to the following restrictions:
#include "btConcaveShape.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btTransform.h"
#include "LinearMath/btMatrix3x3.h"
#include "../../LinearMath/btVector3.h"
#include "../../LinearMath/btTransform.h"
#include "../../LinearMath/btMatrix3x3.h"
#include "btCollisionMargin.h"
/// The btEmptyShape is a collision shape without actual collision detection shape, so most users should ignore this class.
/// It can be replaced by another shape during runtime, but the inertia tensor should be recomputed.
/// btEmptyShape is a collision shape without actual collision detection.
///It can be replaced by another shape during runtime
class btEmptyShape : public btConcaveShape
{
public:
@@ -49,12 +49,12 @@ public:
return m_localScaling;
}
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia);
virtual int getShapeType() const { return EMPTY_SHAPE_PROXYTYPE;}
virtual const char* getName()const
virtual char* getName()const
{
return "Empty";
}

View File

@@ -18,18 +18,16 @@ subject to the following restrictions:
#include "LinearMath/btTransformUtil.h"
btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges)
: m_heightStickWidth(heightStickWidth),
m_heightStickLength(heightStickLength),
m_maxHeight(maxHeight),
m_width((btScalar)heightStickWidth-1),
m_length((btScalar)heightStickLength-1),
btHeightfieldTerrainShape::btHeightfieldTerrainShape(int width,int length,void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges)
:m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)),
m_width(width),
m_length(length),
m_heightfieldDataUnknown(heightfieldData),
m_maxHeight(maxHeight),
m_upAxis(upAxis),
m_useFloatData(useFloatData),
m_flipQuadEdges(flipQuadEdges),
m_useDiamondSubdivision(false),
m_upAxis(upAxis),
m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.))
m_useDiamondSubdivision(false)
{
@@ -45,25 +43,25 @@ m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.))
case 0:
{
halfExtents.setValue(
btScalar(m_maxHeight),
btScalar(m_width), //?? don't know if this should change
btScalar(m_length));
m_maxHeight,
m_width,
m_length);
break;
}
case 1:
{
halfExtents.setValue(
btScalar(m_width),
btScalar(m_maxHeight),
btScalar(m_length));
m_width,
m_maxHeight,
m_length);
break;
};
case 2:
{
halfExtents.setValue(
btScalar(m_width),
btScalar(m_length),
btScalar(m_maxHeight)
m_width,
m_length,
m_maxHeight
);
break;
}
@@ -91,15 +89,19 @@ btHeightfieldTerrainShape::~btHeightfieldTerrainShape()
void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
{
/*
aabbMin.setValue(-1e30f,-1e30f,-1e30f);
aabbMax.setValue(1e30f,1e30f,1e30f);
*/
btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5);
halfExtents += btVector3(getMargin(),getMargin(),getMargin());
btMatrix3x3 abs_b = t.getBasis().absolute();
btPoint3 center = t.getOrigin();
btVector3 extent = btVector3(abs_b[0].dot(halfExtents),
abs_b[1].dot(halfExtents),
abs_b[2].dot(halfExtents));
extent += btVector3(getMargin(),getMargin(),getMargin());
aabbMin = center - extent;
aabbMax = center + extent;
@@ -112,11 +114,11 @@ btScalar btHeightfieldTerrainShape::getHeightFieldValue(int x,int y) const
btScalar val = 0.f;
if (m_useFloatData)
{
val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x];
val = m_heightfieldDataFloat[(y*m_width)+x];
} else
{
//assume unsigned short int
unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x];
unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_width)+x];
val = heightFieldValue* (m_maxHeight/btScalar(65535));
}
return val;
@@ -131,8 +133,8 @@ void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
btAssert(x>=0);
btAssert(y>=0);
btAssert(x<m_heightStickWidth);
btAssert(y<m_heightStickLength);
btAssert(x<m_width);
btAssert(y<m_length);
btScalar height = getHeightFieldValue(x,y);
@@ -143,25 +145,25 @@ void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
{
vertex.setValue(
height,
(-m_width/btScalar(2.0)) + x,
(-m_length/btScalar(2.0) ) + y
(-m_width/2 ) + x,
(-m_length/2 ) + y
);
break;
}
case 1:
{
vertex.setValue(
(-m_width/btScalar(2.0)) + x,
(-m_width/2 ) + x,
height,
(-m_length/btScalar(2.0)) + y
(-m_length/2 ) + y
);
break;
};
case 2:
{
vertex.setValue(
(-m_width/btScalar(2.0)) + x,
(-m_length/btScalar(2.0)) + y,
(-m_width/2 ) + x,
(-m_length/2 ) + y,
height
);
break;
@@ -178,20 +180,21 @@ void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
}
void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point,int /*isMax*/) const
void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point) const
{
btVector3 clampedPoint(point);
clampedPoint.setMax(m_localAabbMin);
clampedPoint.setMin(m_localAabbMax);
btVector3 v = (clampedPoint);// - m_bvhAabbMin) * m_bvhQuantization;
btVector3 v = (clampedPoint );// * m_quantization;
out[0] = (int)(v.getX());
out[1] = (int)(v.getY());
out[2] = (int)(v.getZ());
//correct for
//TODO: optimization: check out how to removed this btFabs
out[0] = (int)(v.getX() + v.getX() / btFabs(v.getX())* btScalar(0.5) );
out[1] = (int)(v.getY() + v.getY() / btFabs(v.getY())* btScalar(0.5) );
out[2] = (int)(v.getZ() + v.getZ() / btFabs(v.getZ())* btScalar(0.5) );
}
@@ -209,24 +212,24 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
btVector3 localAabbMin = aabbMin*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
btVector3 localAabbMax = aabbMax*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
quantizeWithClamp(quantizedAabbMin, localAabbMin,0);
quantizeWithClamp(quantizedAabbMax, localAabbMax,1);
quantizeWithClamp(quantizedAabbMin, localAabbMin);
quantizeWithClamp(quantizedAabbMax, localAabbMax);
int startX=0;
int endX=m_heightStickWidth-1;
int endX=m_width-1;
int startJ=0;
int endJ=m_heightStickLength-1;
int endJ=m_length-1;
switch (m_upAxis)
{
case 0:
{
quantizedAabbMin[1]+=m_heightStickWidth/2-1;
quantizedAabbMax[1]+=m_heightStickWidth/2+1;
quantizedAabbMin[2]+=m_heightStickLength/2-1;
quantizedAabbMax[2]+=m_heightStickLength/2+1;
quantizedAabbMin[1]+=m_width/2-1;
quantizedAabbMax[1]+=m_width/2+1;
quantizedAabbMin[2]+=m_length/2-1;
quantizedAabbMax[2]+=m_length/2+1;
if (quantizedAabbMin[1]>startX)
startX = quantizedAabbMin[1];
@@ -240,10 +243,10 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
}
case 1:
{
quantizedAabbMin[0]+=m_heightStickWidth/2-1;
quantizedAabbMax[0]+=m_heightStickWidth/2+1;
quantizedAabbMin[2]+=m_heightStickLength/2-1;
quantizedAabbMax[2]+=m_heightStickLength/2+1;
quantizedAabbMin[0]+=m_width/2-1;
quantizedAabbMax[0]+=m_width/2+1;
quantizedAabbMin[2]+=m_length/2-1;
quantizedAabbMax[2]+=m_length/2+1;
if (quantizedAabbMin[0]>startX)
startX = quantizedAabbMin[0];
@@ -257,10 +260,10 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
};
case 2:
{
quantizedAabbMin[0]+=m_heightStickWidth/2-1;
quantizedAabbMax[0]+=m_heightStickWidth/2+1;
quantizedAabbMin[1]+=m_heightStickLength/2-1;
quantizedAabbMax[1]+=m_heightStickLength/2+1;
quantizedAabbMin[0]+=m_width/2-1;
quantizedAabbMax[0]+=m_width/2+1;
quantizedAabbMin[1]+=m_length/2-1;
quantizedAabbMax[1]+=m_length/2+1;
if (quantizedAabbMin[0]>startX)
startX = quantizedAabbMin[0];
@@ -287,7 +290,7 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
for(int x=startX; x<endX; x++)
{
btVector3 vertices[3];
if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j+x) & 1)))
if (m_flipQuadEdges || (m_useDiamondSubdivision && ((j+x) & 1)))
{
//first triangle
getVertex(x,j,vertices[0]);
@@ -319,7 +322,7 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
}
void btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia) const
void btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia)
{
//moving concave objects not supported

View File

@@ -18,8 +18,7 @@ subject to the following restrictions:
#include "btConcaveShape.h"
///The btHeightfieldTerrainShape simulates a 2D heightfield terrain collision shape. You can also use the more general btBvhTriangleMeshShape instead.
///An example implementation of btHeightfieldTerrainShape is provided in Demos/VehicleDemo/VehicleDemo.cpp
///btHeightfieldTerrainShape simulates a 2D heightfield terrain
class btHeightfieldTerrainShape : public btConcaveShape
{
protected:
@@ -27,11 +26,9 @@ protected:
btVector3 m_localAabbMax;
///terrain data
int m_heightStickWidth;
int m_heightStickLength;
int m_width;
int m_length;
btScalar m_maxHeight;
btScalar m_width;
btScalar m_length;
union
{
unsigned char* m_heightfieldDataUnsignedChar;
@@ -48,7 +45,7 @@ protected:
btVector3 m_localScaling;
virtual btScalar getHeightFieldValue(int x,int y) const;
void quantizeWithClamp(int* out, const btVector3& point,int isMax) const;
void quantizeWithClamp(int* out, const btVector3& point) const;
void getVertex(int x,int y,btVector3& vertex) const;
inline bool testQuantizedAabbAgainstQuantizedAabb(int* aabbMin1, int* aabbMax1,const int* aabbMin2,const int* aabbMax2) const
@@ -61,7 +58,7 @@ protected:
}
public:
btHeightfieldTerrainShape(int heightStickWidth,int heightStickHeight,void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges);
btHeightfieldTerrainShape(int width,int height,void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges);
virtual ~btHeightfieldTerrainShape();
@@ -77,14 +74,14 @@ public:
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia);
virtual void setLocalScaling(const btVector3& scaling);
virtual const btVector3& getLocalScaling() const;
//debugging
virtual const char* getName()const {return "HEIGHTFIELD";}
virtual char* getName()const {return "HEIGHTFIELD";}
};

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